1 // This source code is dual-licensed under the Apache License, version
2 // 2.0, and the Mozilla Public License, version 1.1.
6 //---------------------------------------------------------------------------
7 // Copyright (C) 2007, 2008 LShift Ltd., Cohesive Financial
8 // Technologies LLC., and Rabbit Technologies Ltd.
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
14 // http://www.apache.org/licenses/LICENSE-2.0
16 // Unless required by applicable law or agreed to in writing, software
17 // distributed under the License is distributed on an "AS IS" BASIS,
18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 // See the License for the specific language governing permissions and
20 // limitations under the License.
21 //---------------------------------------------------------------------------
25 //---------------------------------------------------------------------------
26 // The contents of this file are subject to the Mozilla Public License
27 // Version 1.1 (the "License"); you may not use this file except in
28 // compliance with the License. You may obtain a copy of the License at
29 // http://www.rabbitmq.com/mpl.html
31 // Software distributed under the License is distributed on an "AS IS"
32 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
33 // License for the specific language governing rights and limitations
36 // The Original Code is The RabbitMQ .NET Client.
38 // The Initial Developers of the Original Code are LShift Ltd.,
39 // Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
41 // Portions created by LShift Ltd., Cohesive Financial Technologies
42 // LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007, 2008
43 // LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit
46 // All Rights Reserved.
48 // Contributor(s): ______________________________________.
50 //---------------------------------------------------------------------------
56 using RabbitMQ.Client;
59 namespace RabbitMQ.Client.Content {
60 ///<summary>Tags used in parsing and generating StreamWireFormatting message bodies.</summary>
61 public enum StreamWireFormattingTag {
75 ///<summary>Internal support class for use in reading and writing
76 ///information binary-compatible with QPid's "StreamMessage" wire
77 ///encoding.</summary>
78 public class StreamWireFormatting {
79 public static bool ReadBool(NetworkBinaryReader reader) {
80 object value = ReadNonnullObject("bool", reader);
84 if (value is string) {
85 return PrimitiveParser.ParseBool((string) value);
87 PrimitiveParser.InvalidConversion("bool", value);
91 public static int ReadInt32(NetworkBinaryReader reader) {
92 object value = ReadNonnullObject("int", reader);
93 if (value is int || value is short || value is byte) {
96 if (value is string) {
97 return PrimitiveParser.ParseInt((string) value);
99 PrimitiveParser.InvalidConversion("int", value);
103 public static short ReadInt16(NetworkBinaryReader reader) {
104 object value = ReadNonnullObject("short", reader);
105 if (value is short || value is byte) {
106 return (short) value;
108 if (value is string) {
109 return PrimitiveParser.ParseShort((string) value);
111 PrimitiveParser.InvalidConversion("short", value);
115 public static byte ReadByte(NetworkBinaryReader reader) {
116 object value = ReadNonnullObject("byte", reader);
120 if (value is string) {
121 return PrimitiveParser.ParseByte((string) value);
123 PrimitiveParser.InvalidConversion("byte", value);
127 public static char ReadChar(NetworkBinaryReader reader) {
128 object value = ReadNonnullObject("char", reader);
132 PrimitiveParser.InvalidConversion("char", value);
136 public static long ReadInt64(NetworkBinaryReader reader) {
137 object value = ReadNonnullObject("long", reader);
138 if (value is long || value is int || value is short || value is byte) {
141 if (value is string) {
142 return PrimitiveParser.ParseLong((string) value);
144 PrimitiveParser.InvalidConversion("long", value);
148 public static float ReadSingle(NetworkBinaryReader reader) {
149 object value = ReadNonnullObject("float", reader);
150 if (value is float) {
151 return (float) value;
153 if (value is string) {
154 return PrimitiveParser.ParseFloat((string) value);
156 PrimitiveParser.InvalidConversion("float", value);
160 public static double ReadDouble(NetworkBinaryReader reader) {
161 object value = ReadNonnullObject("double", reader);
162 if (value is double || value is float) {
163 return (double) value;
165 if (value is string) {
166 return PrimitiveParser.ParseDouble((string) value);
168 PrimitiveParser.InvalidConversion("double", value);
172 public static byte[] ReadBytes(NetworkBinaryReader reader) {
173 object value = ReadObject(reader);
177 if (value is byte[]) {
178 return (byte[]) value;
180 PrimitiveParser.InvalidConversion("byte[]", value);
184 public static string ReadString(NetworkBinaryReader reader) {
185 object value = ReadObject(reader);
189 if (value is byte[]) {
190 PrimitiveParser.InvalidConversion("string", value);
193 return value.ToString();
196 ///<exception cref="ProtocolViolationException"/>
197 public static object ReadNonnullObject(string target, NetworkBinaryReader reader) {
198 object value = ReadObject(reader);
200 throw new ProtocolViolationException(string.Format("Null {0} value not permitted",
206 ///<exception cref="EndOfStreamException"/>
207 ///<exception cref="ProtocolViolationException"/>
208 public static object ReadObject(NetworkBinaryReader reader) {
209 int typeTag = reader.ReadByte();
212 throw new EndOfStreamException("End of StreamMessage reached");
214 case (int) StreamWireFormattingTag.Bool: {
215 byte value = reader.ReadByte();
217 case 0x00: return false;
218 case 0x01: return true;
221 string.Format("Invalid boolean value in StreamMessage: {0}", value);
222 throw new ProtocolViolationException(message);
227 case (int) StreamWireFormattingTag.Byte:
228 return reader.ReadByte();
230 case (int) StreamWireFormattingTag.Bytes: {
231 int length = reader.ReadInt32();
235 return reader.ReadBytes(length);
239 case (int) StreamWireFormattingTag.Int16:
240 return reader.ReadInt16();
242 case (int) StreamWireFormattingTag.Char:
243 return (char) reader.ReadUInt16();
245 case (int) StreamWireFormattingTag.Int32:
246 return reader.ReadInt32();
248 case (int) StreamWireFormattingTag.Int64:
249 return reader.ReadInt64();
251 case (int) StreamWireFormattingTag.Single:
252 return reader.ReadSingle();
254 case (int) StreamWireFormattingTag.Double:
255 return reader.ReadDouble();
257 case (int) StreamWireFormattingTag.String:
258 return ReadUntypedString(reader);
260 case (int) StreamWireFormattingTag.Null:
264 string message = string.Format("Invalid type tag in StreamMessage: {0}",
266 throw new ProtocolViolationException(message);
271 public static string ReadUntypedString(NetworkBinaryReader reader) {
272 BinaryWriter buffer = NetworkBinaryWriter.TemporaryBinaryWriter(256);
274 byte b = reader.ReadByte();
276 return Encoding.UTF8.GetString(NetworkBinaryWriter.TemporaryContents(buffer));
283 public static void WriteBool(NetworkBinaryWriter writer, bool value) {
284 writer.Write((byte) StreamWireFormattingTag.Bool);
285 writer.Write(value ? (byte) 0x01 : (byte) 0x00);
288 public static void WriteInt32(NetworkBinaryWriter writer, int value) {
289 writer.Write((byte) StreamWireFormattingTag.Int32);
293 public static void WriteInt16(NetworkBinaryWriter writer, short value) {
294 writer.Write((byte) StreamWireFormattingTag.Int16);
298 public static void WriteByte(NetworkBinaryWriter writer, byte value) {
299 writer.Write((byte) StreamWireFormattingTag.Byte);
303 public static void WriteChar(NetworkBinaryWriter writer, char value) {
304 writer.Write((byte) StreamWireFormattingTag.Char);
305 writer.Write((ushort) value);
308 public static void WriteInt64(NetworkBinaryWriter writer, long value) {
309 writer.Write((byte) StreamWireFormattingTag.Int64);
313 public static void WriteSingle(NetworkBinaryWriter writer, float value) {
314 writer.Write((byte) StreamWireFormattingTag.Single);
318 public static void WriteDouble(NetworkBinaryWriter writer, double value) {
319 writer.Write((byte) StreamWireFormattingTag.Double);
323 public static void WriteBytes(NetworkBinaryWriter writer,
328 writer.Write((byte) StreamWireFormattingTag.Bytes);
329 writer.Write(length);
330 writer.Write(value, offset, length);
333 public static void WriteBytes(NetworkBinaryWriter writer, byte[] value) {
334 WriteBytes(writer, value, 0, value.Length);
337 public static void WriteString(NetworkBinaryWriter writer, string value) {
338 writer.Write((byte) StreamWireFormattingTag.String);
339 WriteUntypedString(writer, value);
342 ///<exception cref="ProtocolViolationException"/>
343 public static void WriteObject(NetworkBinaryWriter writer, object value) {
344 if (value is bool) { WriteBool(writer, (bool) value); }
345 else if (value is int) { WriteInt32(writer, (int) value); }
346 else if (value is short) { WriteInt16(writer, (short) value); }
347 else if (value is byte) { WriteByte(writer, (byte) value); }
348 else if (value is char) { WriteChar(writer, (char) value); }
349 else if (value is long) { WriteInt64(writer, (long) value); }
350 else if (value is float) { WriteSingle(writer, (float) value); }
351 else if (value is double) { WriteDouble(writer, (double) value); }
352 else if (value is byte[]) { WriteBytes(writer, (byte[]) value); }
353 else if (value is BinaryTableValue) { WriteBytes(writer,
354 ((BinaryTableValue) value).Bytes); }
355 else if (value is string) { WriteString(writer, (string) value); }
357 string message = string.Format("Invalid object in StreamMessage.WriteObject: {0}",
359 throw new ProtocolViolationException(message);
363 public static void WriteUntypedString(NetworkBinaryWriter writer, string value) {
364 writer.Write(Encoding.UTF8.GetBytes(value));
365 writer.Write((byte) 0);