private IASValue ReadArray() { int length = input.ReadInt(); if (length < 0) { throw new AMFException(ExceptionPrefix + "Encountered negative Array length."); } // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(result); IASValue[] indexedValues; // Read indexed values, if any. if (length != 0) { indexedValues = new IASValue[length]; for (int i = 0; i < length; i++) { indexedValues[i] = ReadObject(); } } else { indexedValues = EmptyArray <IASValue> .Instance; } result.SetProperties(indexedValues, EmptyDictionary <string, IASValue> .Instance); return(result); }
public void ConstructorWithLength() { ASArray array = new ASArray(10); Assert.AreEqual(10, array.IndexedValues.Count); Assert.AreEqual(0, array.DynamicProperties.Count); }
public void ReadObject_Objects_ReferenceCaching_AMF0() { // Read an array with multiple copies of each kind of object and including a self-reference SetStreamContents(new byte[] { (byte)AMF0ObjectTypeCode.MixedArray, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x61, (byte)AMF0ObjectTypeCode.Reference, 0x00, 0x01, // mixed array by reference 0x00, 0x01, 0x30, (byte)AMF0ObjectTypeCode.Object, 0x00, 0x00, (byte)AMF0ObjectTypeCode.EndOfObject, // obj 0x00, 0x01, 0x31, (byte)AMF0ObjectTypeCode.Array, 0x00, 0x00, 0x00, 0x00, // regular array 0x00, 0x01, 0x32, (byte)AMF0ObjectTypeCode.Reference, 0x00, 0x02, // obj by reference 0x00, 0x01, 0x33, (byte)AMF0ObjectTypeCode.Reference, 0x00, 0x03, // regular array by reference 0x00, 0x00, (byte)AMF0ObjectTypeCode.EndOfObject }); input.BeginObjectStream(); ASArray mixedArray = (ASArray)input.ReadObject(); Assert.AreEqual(AMFObjectEncoding.AMF0, input.ObjectEncoding); input.EndObjectStream(); Assert.AreEqual(4, mixedArray.IndexedValues.Count); Assert.AreEqual(1, mixedArray.DynamicProperties.Count); ASObject obj = (ASObject)mixedArray.IndexedValues[0]; ASArray regularArray = (ASArray)mixedArray.IndexedValues[1]; Assert.AreSame(obj, mixedArray.IndexedValues[2]); Assert.AreSame(regularArray, mixedArray.IndexedValues[3]); Assert.AreSame(mixedArray, mixedArray.DynamicProperties["a"]); }
public void ReadObject_Objects_ReferenceCaching_AMF3() { // Read an array with multiple copies of each kind of object and including a self-reference SetStreamContents(new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.Array, 0x0d, 0x03, 0x61, (byte)AMF3ObjectTypeCode.Array, 0x00, // array by reference 0x01, // end of mixed values (byte)AMF3ObjectTypeCode.Object, 0x0b, 0x01, 0x01, // obj (byte)AMF3ObjectTypeCode.ByteArray, 0x01, // byte array (byte)AMF3ObjectTypeCode.Date, 0x01, 0x3f, 0xf0, 0, 0, 0, 0, 0, 0, // date (byte)AMF3ObjectTypeCode.Object, 0x02, // obj by reference (byte)AMF3ObjectTypeCode.ByteArray, 0x04, // byte array by reference (byte)AMF3ObjectTypeCode.Date, 0x06, // date by reference }); input.BeginObjectStream(); ASArray array = (ASArray)input.ReadObject(); Assert.AreEqual(AMFObjectEncoding.AMF3, input.ObjectEncoding); input.EndObjectStream(); Assert.AreEqual(6, array.IndexedValues.Count); Assert.AreEqual(1, array.DynamicProperties.Count); ASObject obj = (ASObject)array.IndexedValues[0]; ASByteArray byteArray = (ASByteArray)array.IndexedValues[1]; ASDate date = (ASDate)array.IndexedValues[2]; Assert.AreSame(obj, array.IndexedValues[3]); Assert.AreSame(byteArray, array.IndexedValues[4]); Assert.AreSame(date, array.IndexedValues[5]); Assert.AreSame(array, array.DynamicProperties["a"]); }
public void ConstructorWithIndexedValues() { IASValue[] indexedValues = new IASValue[] { null, null, null }; ASArray array = new ASArray(indexedValues); Assert.AreSame(indexedValues, array.IndexedValues); Assert.AreEqual(0, array.DynamicProperties.Count); }
public void IndexedValueIndexer() { ASArray array = new ASArray(new IASValue[] { null, new ASString("abc"), null }); Assert.AreEqual(new ASString("abc"), array[1]); array[1] = new ASString("def"); Assert.AreEqual(new ASString("def"), array[1]); }
public void CreateUninitializedInstanceAndSetProperties() { ASArray array = ASArray.CreateUninitializedInstance(); array.SetProperties(EmptyArray <IASValue> .Instance, EmptyDictionary <string, IASValue> .Instance); Assert.AreSame(EmptyArray <IASValue> .Instance, array.IndexedValues); Assert.AreSame(EmptyDictionary <string, IASValue> .Instance, array.DynamicProperties); }
public void ConstructorWithIndexedAndMixedValues() { IASValue[] indexedValues = new IASValue[] { null, null, null }; IDictionary<string, IASValue> mixedValues = new Dictionary<string, IASValue>(); ASArray array = new ASArray(indexedValues, mixedValues); Assert.AreSame(indexedValues, array.IndexedValues); Assert.AreSame(mixedValues, array.DynamicProperties); }
public void ConstructorWithIndexedAndMixedValues() { IASValue[] indexedValues = new IASValue[] { null, null, null }; IDictionary <string, IASValue> mixedValues = new Dictionary <string, IASValue>(); ASArray array = new ASArray(indexedValues, mixedValues); Assert.AreSame(indexedValues, array.IndexedValues); Assert.AreSame(mixedValues, array.DynamicProperties); }
private IASValue ReadMixedArray() { int length = input.ReadInt(); if (length < 0) { throw new AMFException(ExceptionPrefix + "Encountered negative MixedArray length."); } // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(result); IASValue[] indexedValues = length == 0 ? EmptyArray <IASValue> .Instance : new IASValue[length]; IDictionary <string, IASValue> mixedValues = null; for (;;) { string key = input.ReadShortString(); if (key.Length == 0) { break; } IASValue value = input.ReadObject(); // If the string looks like a valid index, then stuff it into the array. int index; if (int.TryParse(key, NumberStyles.None, CultureInfo.InvariantCulture, out index) && index >= 0 && index < length) { indexedValues[index] = value; } else { // Otherwise add it as a mixed value. if (mixedValues == null) { mixedValues = new Dictionary <string, IASValue>(); } mixedValues.Add(key, value); } } if (mixedValues == null) { mixedValues = EmptyDictionary <string, IASValue> .Instance; } ConsumeEndOfObject(); result.SetProperties(indexedValues, mixedValues); return(result); }
public void MixedValueIndexer() { ASArray array = new ASArray(0); array["abc"] = new ASInt29(1); Assert.AreEqual(new ASInt29(1), array["abc"]); // do it twice to be sure array["abc"] = new ASInt29(2); Assert.AreEqual(new ASInt29(2), array["abc"]); }
public void WriteObject_Arrays(AMFObjectEncoding objectEncoding, byte[] expected, string[] values, string[] mixedKeysAndValues) { ASArray array = new ASArray(WrapStrings(values)); for (int i = 0; i < mixedKeysAndValues.Length; i += 2) { array.DynamicProperties[mixedKeysAndValues[i]] = new ASString(mixedKeysAndValues[i + 1]); } output.ObjectEncoding = objectEncoding; output.BeginObjectStream(); output.WriteObject(array); output.EndObjectStream(); CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
public void ReadObject_Arrays(AMFObjectEncoding objectEncoding, byte[] bytes, string[] indexedValues, string[] mixedKeysAndValues) { SetStreamContents(bytes); input.BeginObjectStream(); ASArray result = (ASArray)input.ReadObject(); Assert.AreEqual(objectEncoding, input.ObjectEncoding); input.EndObjectStream(); CollectionAssert.AreElementsEqual(WrapStrings(indexedValues), result.IndexedValues); Assert.AreEqual(mixedKeysAndValues.Length / 2, result.DynamicProperties.Count); for (int i = 0; i < mixedKeysAndValues.Length; i += 2) { Assert.AreEqual(new ASString(mixedKeysAndValues[i + 1]), result.DynamicProperties[mixedKeysAndValues[i]]); } }
public void ReadObject_Strings_Caching_AMF3() { ASString empty = new ASString(""); ASString valueA = new ASString("a"); ASString valueB = new ASString("b"); ASString valueC = new ASString("c"); byte[] bytes = new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x61, // valueA (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x62, // valueB (byte)AMF3ObjectTypeCode.String, 0x00, // valueA (by ref) (byte)AMF3ObjectTypeCode.Xml, 0x02, // valueB (by ref) (byte)AMF3ObjectTypeCode.Array, 0x05, 0x02, (byte)AMF3ObjectTypeCode.String, 0x00, 0x01, (byte)AMF3ObjectTypeCode.String, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, // array (byte)AMF3ObjectTypeCode.Object, 0x1b, 0x02, 0x03, 0x63, (byte)AMF3ObjectTypeCode.String, 0x04, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, 0x01 // object }; SetStreamContents(bytes); input.BeginObjectStream(); Assert.AreEqual(empty, input.ReadObject()); // empty strings are not cached Assert.AreEqual(valueA, input.ReadObject()); // will get string ref #0 Assert.AreEqual(empty, input.ReadObject()); // empty strings are not cached Assert.AreEqual(valueB, input.ReadObject()); // will get string ref #1 Assert.AreEqual(valueA, input.ReadObject()); // will use string ref #0 ASXmlDocument xml = (ASXmlDocument)input.ReadObject(); Assert.AreEqual(valueB.Value, xml.XmlString); // XML contents are same as valueB, will use ref #1 ASArray array = (ASArray)input.ReadObject(); // Array contains valueA and valueB and mixed values with key valueB and value valueA CollectionAssert.AreElementsEqual(new object[] { valueA, valueB }, array.IndexedValues); Assert.AreEqual(valueA, array.DynamicProperties[valueB.Value]); ASObject obj = (ASObject)input.ReadObject(); // Object has class name valueB contains member with key valueC and value valueA dynamic property with key valueA and value valueB CollectionAssert.AreElementsEqual(new object[] { valueC }, obj.MemberValues); Assert.AreEqual(valueB, obj.DynamicProperties[valueA.Value]); Assert.AreEqual(valueB.Value, obj.Class.ClassAlias); Assert.AreEqual(ASClassLayout.Dynamic, obj.Class.Layout); CollectionAssert.AreElementsEqual(new string[] { valueC.Value }, obj.Class.MemberNames); Assert.AreEqual(AMFObjectEncoding.AMF3, input.ObjectEncoding); input.EndObjectStream(); }
public void WriteObject_Strings_Caching_AMF3() { ASString empty = new ASString(""); ASString valueA = new ASString("a"); ASString valueB = new ASString("b"); ASString valueC = new ASString("c"); ASXmlDocument xml = new ASXmlDocument(valueB.Value); ASArray array = new ASArray(new IASValue[] { valueA, valueB }); array.DynamicProperties[valueB.Value] = valueA; ASClass clazz = new ASClass(valueB.Value, ASClassLayout.Dynamic, new string[] { valueC.Value }); ASObject obj = new ASObject(clazz); obj.MemberValues[0] = valueC; obj.DynamicProperties[valueA.Value] = valueB; output.ObjectEncoding = AMFObjectEncoding.AMF3; output.BeginObjectStream(); output.WriteObject(empty); // empty strings are not cached output.WriteObject(valueA); // will get string ref #0 output.WriteObject(empty); // empty strings are not cached output.WriteObject(valueB); // will get string ref #1 output.WriteObject(valueA); // will use string ref #0 output.WriteObject(xml); // XML contents are same as valueB, will use ref #1 output.WriteObject(array); // Array contains valueA and valueB and mixed values with key valueB and value valueA output.WriteObject(obj); // Object has class name valueB contains member with key valueC and value valueA dynamic property with key valueA and value valueB output.EndObjectStream(); CollectionAssert.AreElementsEqual( new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x61, // valueA (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x62, // valueB (byte)AMF3ObjectTypeCode.String, 0x00, // valueA (by ref) (byte)AMF3ObjectTypeCode.Xml, 0x02, // valueB (by ref) (byte)AMF3ObjectTypeCode.Array, 0x05, 0x02, (byte)AMF3ObjectTypeCode.String, 0x00, 0x01, (byte)AMF3ObjectTypeCode.String, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, // array (byte)AMF3ObjectTypeCode.Object, 0x1b, 0x02, 0x03, 0x63, (byte)AMF3ObjectTypeCode.String, 0x04, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, 0x01 // object }, stream.ToArray()); }
public void WriteObject_Objects_ReferenceCaching(AMFObjectEncoding objectEncoding, byte[] expected) { // Create an array with multiple copies of each kind of object and including a self-reference ASObject obj = new ASObject(); ASByteArray byteArray = new ASByteArray(new byte[0]); ASDate date = new ASDate(1, 0); ASArray array = new ASArray(6); array.IndexedValues[0] = obj; array.IndexedValues[1] = byteArray; array.IndexedValues[2] = date; array.IndexedValues[3] = obj; array.IndexedValues[4] = byteArray; array.IndexedValues[5] = date; array.DynamicProperties["a"] = array; output.ObjectEncoding = objectEncoding; output.BeginObjectStream(); output.WriteObject(array); output.EndObjectStream(); CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
public void SetPropertiesWithInitializedInstanceThrows() { ASArray array = new ASArray(1); array.SetProperties(EmptyArray<IASValue>.Instance, EmptyDictionary<string, IASValue>.Instance); }
public void IndexedValueGetIndexerThrowsIfOutOfRange(int index) { ASArray array = new ASArray(new IASValue[] { null, null, null }); GC.KeepAlive(array[index]); }
public void IndexedValueSetIndexerThrowsIfOutOfRange(int index) { ASArray array = new ASArray(new IASValue[] { null, null, null }); array[index] = new ASString("abc"); }
public void SetPropertiesWithInitializedInstanceThrows() { ASArray array = new ASArray(1); array.SetProperties(EmptyArray <IASValue> .Instance, EmptyDictionary <string, IASValue> .Instance); }
internal ArrayWrapper(ASArray instance) => this.instance = instance;
public void WriteObject_Arrays(AMFObjectEncoding objectEncoding, byte[] expected, string[] values, string[] mixedKeysAndValues) { ASArray array = new ASArray(WrapStrings(values)); for (int i = 0; i < mixedKeysAndValues.Length; i += 2) array.DynamicProperties[mixedKeysAndValues[i]] = new ASString(mixedKeysAndValues[i + 1]); output.ObjectEncoding = objectEncoding; output.BeginObjectStream(); output.WriteObject(array); output.EndObjectStream(); CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
private IASValue ReadArray() { int bits = input.ReadVWInt29(); int lengthOrReferenceId = bits >> 1; // Handle cached objects. if ((bits & 1) == 0) { return(GetObjectFromCache(AMF3ObjectTypeCode.Array, lengthOrReferenceId)); } // Read out the whole array. if (lengthOrReferenceId < 0) { throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Array token with invalid length '{0}'.", lengthOrReferenceId)); } // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(AMF3ObjectTypeCode.Array, result); // Read mixed values if any. IDictionary <string, IASValue> mixedValues; string key = ReadStringData(); if (key.Length != 0) { mixedValues = new Dictionary <string, IASValue>(); for (; ;) { IASValue value = ReadObject(); mixedValues.Add(key, value); key = ReadStringData(); if (key.Length == 0) { break; } } } else { mixedValues = EmptyDictionary <string, IASValue> .Instance; } // Read indexed values if any. IASValue[] indexedValues; if (lengthOrReferenceId != 0) { indexedValues = new IASValue[lengthOrReferenceId]; for (int i = 0; i < lengthOrReferenceId; i++) { indexedValues[i] = ReadObject(); } } else { indexedValues = EmptyArray <IASValue> .Instance; } result.SetProperties(indexedValues, mixedValues); return(result); }