projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs
branchbug21965
changeset 265 4def852523e2
parent 182 90884d46542b
child 323 584531d49c3c
     1.1 --- a/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs	Wed Aug 05 18:54:24 2009 +0100
     1.2 +++ b/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs	Wed Nov 25 17:48:00 2009 +0000
     1.3 @@ -128,7 +128,7 @@
     1.4          ///<remarks>
     1.5          /// Supports the AMQP 0-8/0-9 standard entry types S, I, D, T
     1.6          /// and F, as well as the QPid-0-8 specific b, d, f, l, s, t,
     1.7 -        /// x and V types.
     1.8 +        /// x and V types and the AMQP 0-9-1 A type.
     1.9          ///</remarks>
    1.10          public static IDictionary ReadTable(NetworkBinaryReader reader)
    1.11          {
    1.12 @@ -140,10 +140,36 @@
    1.13              while ((backingStream.Position - startPosition) < tableLength)
    1.14              {
    1.15                  string key = ReadShortstr(reader);
    1.16 -                object value = null;
    1.17 +                object value = ReadFieldValue(reader);
    1.18 +                
    1.19 +                if (!table.ContainsKey(key))
    1.20 +                {
    1.21 +                    table[key] = value;
    1.22 +                }
    1.23 +            }
    1.24  
    1.25 -                byte discriminator = reader.ReadByte();
    1.26 -                switch ((char)discriminator)
    1.27 +            return table;
    1.28 +        }
    1.29 +
    1.30 +        public static IList ReadArray(NetworkBinaryReader reader)
    1.31 +        {
    1.32 +            IList array = new ArrayList();
    1.33 +            long arrayLength = reader.ReadUInt32();
    1.34 +            Stream backingStream = reader.BaseStream;
    1.35 +            long startPosition = backingStream.Position;
    1.36 +            while ((backingStream.Position - startPosition) < arrayLength)
    1.37 +            {
    1.38 +                object value = ReadFieldValue(reader);
    1.39 +                array.Add(value);
    1.40 +            }
    1.41 +            return array;
    1.42 +        }
    1.43 +
    1.44 +        public static object ReadFieldValue(NetworkBinaryReader reader)
    1.45 +        {
    1.46 +            object value = null;
    1.47 +            byte discriminator = reader.ReadByte();
    1.48 +            switch ((char)discriminator)
    1.49                  {
    1.50                    case 'S':
    1.51                        value = ReadLongstr(reader);
    1.52 @@ -161,6 +187,9 @@
    1.53                        value = ReadTable(reader);
    1.54                        break;
    1.55  
    1.56 +                  case 'A':
    1.57 +                      value = ReadArray(reader);
    1.58 +                      break;
    1.59                    case 'b':
    1.60                        value = ReadOctet(reader);
    1.61                        break;
    1.62 @@ -190,16 +219,9 @@
    1.63                        throw new SyntaxError("Unrecognised type in table: " +
    1.64                                              (char) discriminator);
    1.65                  }
    1.66 -
    1.67 -                if (!table.ContainsKey(key))
    1.68 -                {
    1.69 -                    table[key] = value;
    1.70 -                }
    1.71 -            }
    1.72 -
    1.73 -            return table;
    1.74 +            return value;
    1.75          }
    1.76 -
    1.77 +      
    1.78          public static AmqpTimestamp ReadTimestamp(NetworkBinaryReader reader)
    1.79          {
    1.80              ulong stamp = ReadLonglong(reader);
    1.81 @@ -290,7 +312,7 @@
    1.82          ///<para>
    1.83          /// Supports the AMQP 0-8/0-9 standard entry types S, I, D, T
    1.84          /// and F, as well as the QPid-0-8 specific b, d, f, l, s, t
    1.85 -        /// x and V types.
    1.86 +        /// x and V types and the AMQP 0-9-1 A type.
    1.87          ///</para>
    1.88          ///</remarks>
    1.89          public static void WriteTable(NetworkBinaryWriter writer, IDictionary val)
    1.90 @@ -309,81 +331,7 @@
    1.91                  {
    1.92                      WriteShortstr(writer, (string)entry.Key);
    1.93                      object value = entry.Value;
    1.94 -
    1.95 -                    if (value == null)
    1.96 -                    {
    1.97 -                        WriteOctet(writer, (byte)'V');
    1.98 -                    }
    1.99 -                    else if (value is string)
   1.100 -                    {
   1.101 -                        WriteOctet(writer, (byte)'S');
   1.102 -                        WriteLongstr(writer, Encoding.UTF8.GetBytes((string)value));
   1.103 -                    }
   1.104 -                    else if (value is byte[])
   1.105 -                    {
   1.106 -                        WriteOctet(writer, (byte)'S');
   1.107 -                        WriteLongstr(writer, (byte[])value);
   1.108 -                    }
   1.109 -                    else if (value is int)
   1.110 -                    {
   1.111 -                        WriteOctet(writer, (byte)'I');
   1.112 -                        writer.Write((int)value);
   1.113 -                    }
   1.114 -                    else if (value is decimal)
   1.115 -                    {
   1.116 -                        WriteOctet(writer, (byte)'D');
   1.117 -                        WriteDecimal(writer, (decimal)value);
   1.118 -                    }
   1.119 -                    else if (value is AmqpTimestamp)
   1.120 -                    {
   1.121 -                        WriteOctet(writer, (byte)'T');
   1.122 -                        WriteTimestamp(writer, (AmqpTimestamp)value);
   1.123 -                    }
   1.124 -                    else if (value is IDictionary)
   1.125 -                    {
   1.126 -                        WriteOctet(writer, (byte)'F');
   1.127 -                        WriteTable(writer, (IDictionary)value);
   1.128 -                    }
   1.129 -                    else if (value is byte)
   1.130 -                    {
   1.131 -                        WriteOctet(writer, (byte)'b');
   1.132 -                        WriteOctet(writer, (byte)value);
   1.133 -                    }
   1.134 -                    else if (value is double)
   1.135 -                    {
   1.136 -                        WriteOctet(writer, (byte)'d');
   1.137 -                        writer.Write((double)value);
   1.138 -                    }
   1.139 -                    else if (value is float)
   1.140 -                    {
   1.141 -                        WriteOctet(writer, (byte)'f');
   1.142 -                        writer.Write((float)value);
   1.143 -                    }
   1.144 -                    else if (value is long)
   1.145 -                    {
   1.146 -                        WriteOctet(writer, (byte)'l');
   1.147 -                        writer.Write((long)value);
   1.148 -                    }
   1.149 -                    else if (value is short)
   1.150 -                    {
   1.151 -                        WriteOctet(writer, (byte)'s');
   1.152 -                        writer.Write((short)value);
   1.153 -                    }
   1.154 -                    else if (value is bool)
   1.155 -                    {
   1.156 -                        WriteOctet(writer, (byte)'t');
   1.157 -                        WriteOctet(writer, (byte)(((bool)value) ? 1 : 0));
   1.158 -                    }
   1.159 -                    else if (value is BinaryTableValue)
   1.160 -                    {
   1.161 -                        WriteOctet(writer, (byte)'x');
   1.162 -                        WriteLongstr(writer, ((BinaryTableValue)value).Bytes);
   1.163 -                    }
   1.164 -                    else
   1.165 -                    {
   1.166 -                        throw new WireFormattingException("Value cannot appear as table value",
   1.167 -                                                          value);
   1.168 -                    }
   1.169 +                    WriteFieldValue(writer, value);
   1.170                  }
   1.171  
   1.172                  // Now, backpatch the table length.
   1.173 @@ -395,6 +343,112 @@
   1.174              }
   1.175          }
   1.176  
   1.177 +        public static void WriteArray(NetworkBinaryWriter writer, IList val)
   1.178 +        {
   1.179 +            if (val == null)
   1.180 +            {
   1.181 +                writer.Write((uint)0);
   1.182 +            }
   1.183 +            else
   1.184 +            {
   1.185 +                Stream backingStream = writer.BaseStream;
   1.186 +                long patchPosition = backingStream.Position;
   1.187 +                writer.Write((uint)0); // length of table - will be backpatched
   1.188 +                foreach (object entry in val)
   1.189 +                {
   1.190 +                    WriteFieldValue(writer, entry);
   1.191 +                }
   1.192 +                long savedPosition = backingStream.Position;
   1.193 +                long tableLength = savedPosition - patchPosition - 4; // offset for length word
   1.194 +                backingStream.Seek(patchPosition, SeekOrigin.Begin);
   1.195 +                writer.Write((uint)tableLength);
   1.196 +                backingStream.Seek(savedPosition, SeekOrigin.Begin);
   1.197 +            }
   1.198 +        }
   1.199 +
   1.200 +        public static void WriteFieldValue(NetworkBinaryWriter writer, object value)
   1.201 +        {
   1.202 +            if (value == null)
   1.203 +            {
   1.204 +                WriteOctet(writer, (byte)'V');
   1.205 +            }
   1.206 +            else if (value is string)
   1.207 +            {
   1.208 +                WriteOctet(writer, (byte)'S');
   1.209 +                WriteLongstr(writer, Encoding.UTF8.GetBytes((string)value));
   1.210 +            }
   1.211 +            else if (value is byte[])
   1.212 +            {
   1.213 +                WriteOctet(writer, (byte)'S');
   1.214 +                WriteLongstr(writer, (byte[])value);
   1.215 +            }
   1.216 +            else if (value is int)
   1.217 +            {
   1.218 +                WriteOctet(writer, (byte)'I');
   1.219 +                writer.Write((int)value);
   1.220 +            }
   1.221 +            else if (value is decimal)
   1.222 +            {
   1.223 +                WriteOctet(writer, (byte)'D');
   1.224 +                WriteDecimal(writer, (decimal)value);
   1.225 +            }
   1.226 +            else if (value is AmqpTimestamp)
   1.227 +            {
   1.228 +                WriteOctet(writer, (byte)'T');
   1.229 +                WriteTimestamp(writer, (AmqpTimestamp)value);
   1.230 +            }
   1.231 +            else if (value is IDictionary)
   1.232 +            {
   1.233 +                WriteOctet(writer, (byte)'F');
   1.234 +                WriteTable(writer, (IDictionary)value);
   1.235 +            }
   1.236 +            else if (value is IList)
   1.237 +            {
   1.238 +                WriteOctet(writer, (byte)'A');
   1.239 +                WriteArray(writer, (IList)value);
   1.240 +            }
   1.241 +            else if (value is byte)
   1.242 +            {
   1.243 +                WriteOctet(writer, (byte)'b');
   1.244 +                WriteOctet(writer, (byte)value);
   1.245 +            }
   1.246 +            else if (value is double)
   1.247 +            {
   1.248 +                WriteOctet(writer, (byte)'d');
   1.249 +                writer.Write((double)value);
   1.250 +            }
   1.251 +            else if (value is float)
   1.252 +            {
   1.253 +                WriteOctet(writer, (byte)'f');
   1.254 +                writer.Write((float)value);
   1.255 +            }
   1.256 +            else if (value is long)
   1.257 +            {
   1.258 +                WriteOctet(writer, (byte)'l');
   1.259 +                writer.Write((long)value);
   1.260 +            }
   1.261 +            else if (value is short)
   1.262 +            {
   1.263 +                WriteOctet(writer, (byte)'s');
   1.264 +                writer.Write((short)value);
   1.265 +            }
   1.266 +            else if (value is bool)
   1.267 +            {
   1.268 +                WriteOctet(writer, (byte)'t');
   1.269 +                WriteOctet(writer, (byte)(((bool)value) ? 1 : 0));
   1.270 +            }
   1.271 +            else if (value is BinaryTableValue)
   1.272 +            {
   1.273 +                WriteOctet(writer, (byte)'x');
   1.274 +                WriteLongstr(writer, ((BinaryTableValue)value).Bytes);
   1.275 +            }
   1.276 +            else
   1.277 +            {
   1.278 +                throw new WireFormattingException("Value cannot appear as table value",
   1.279 +                                                  value);
   1.280 +            }
   1.281 +        }
   1.282 +        
   1.283          public static void WriteTimestamp(NetworkBinaryWriter writer, AmqpTimestamp val)
   1.284          {
   1.285              // 0-9 is afaict silent on the signedness of the timestamp.