public static void WriteTypeCodeIfTrue(this Protocol16Stream output, Protocol16Type type, bool writeTypeCode) { if (writeTypeCode) { output.WriteByte((byte)type); } }
private static void SerializeDictionaryHeader(Protocol16Stream output, Type dictionaryType, out bool writeKeyCode, out bool writeValueCode) { Type[] genericArguments = dictionaryType.GetGenericArguments(); writeKeyCode = (genericArguments[0] == typeof(object)); writeValueCode = (genericArguments[1] == typeof(object)); if (writeKeyCode) { output.WriteTypeCodeIfTrue(Protocol16Type.Unknown, true); } else { Protocol16Type typeOfKey = TypeCodeToProtocol16Type(genericArguments[0]); if (typeOfKey == Protocol16Type.Unknown || typeOfKey == Protocol16Type.Dictionary) { throw new Exception("Unexpected - cannot serialize Dictionary with key type: " + genericArguments[0]); } output.WriteTypeCodeIfTrue(typeOfKey, true); } if (writeValueCode) { output.WriteTypeCodeIfTrue(Protocol16Type.Unknown, true); } else { Protocol16Type typeOfValue = TypeCodeToProtocol16Type(genericArguments[1]); if (typeOfValue == Protocol16Type.Unknown) { throw new Exception("Unexpected - cannot serialize Dictionary with value type: " + genericArguments[0]); } output.WriteTypeCodeIfTrue(typeOfValue, true); if (typeOfValue == Protocol16Type.Dictionary) { throw new Exception("TODO: Nested Dictionaries"); } } }
private static void SerializeArrayWithSameElements(Protocol16Stream output, Array array, bool writeTypeCode) { if (array.Length > short.MaxValue) { throw new NotSupportedException($"Arrays can only have a maximum size of {short.MaxValue} (short.MaxValue). Yours is: {array.Length}"); } output.WriteTypeCodeIfTrue(Protocol16Type.Array, writeTypeCode); SerializeShort(output, (short)array.Length, false); Type elementType = array.GetType().GetElementType(); Protocol16Type protocol16Type = TypeCodeToProtocol16Type(elementType); if (protocol16Type == Protocol16Type.Unknown) { throw new Exception("Custom types are currently not supported"); } output.WriteTypeCodeIfTrue(protocol16Type, true); if (protocol16Type == Protocol16Type.Dictionary) { // WTF ExitGames, why are you trying to get GetGenericArguments() of an array..?! // I think what you wanted to do is just give the element type to SerializeDictionaryHeader not the array type SerializeDictionaryHeader(output, elementType, out var writeKeyCode, out var writeValueCode); foreach (var o in array) { SerializeDictionaryElements(output, (IDictionary)o, writeKeyCode, writeValueCode); } } else { foreach (object o in array) { Serialize(output, o, false); } } }
private static void SerializeAnyArray(Protocol16Stream output, Array array, bool writeTypeCode, Protocol16Type arrayType) { if (arrayType == Protocol16Type.ObjectArray) { SerializeObjectArray(output, (object[])array, writeTypeCode); return; } // Fallback to object array if null is included var containsNull = false; foreach (var element in array) { if (element == null) { containsNull = true; break; } } if (containsNull) { SerializeObjectArray(output, (object[])array, writeTypeCode); return; } switch (arrayType) { case Protocol16Type.StringArray: SerializeStringArray(output, (string[])array, writeTypeCode); return; case Protocol16Type.IntegerArray: SerializeIntArray(output, (int[])array, writeTypeCode); break; case Protocol16Type.ByteArray: SerializeByteArray(output, (byte[])array, writeTypeCode); break; case Protocol16Type.Array: SerializeArrayWithSameElements(output, array, writeTypeCode); break; default: throw new Exception("Unknown array type"); } }
public static void Serialize(Protocol16Stream output, object obj, bool writeTypeCode) { if (obj == null) { output.WriteTypeCodeIfTrue(Protocol16Type.Null, writeTypeCode); return; } Protocol16Type type = TypeCodeToProtocol16Type(obj.GetType()); switch (type) { case Protocol16Type.Boolean: SerializeBoolean(output, (bool)obj, writeTypeCode); return; case Protocol16Type.Byte: SerializeByte(output, (byte)obj, writeTypeCode); return; case Protocol16Type.Short: SerializeShort(output, (short)obj, writeTypeCode); return; case Protocol16Type.Integer: SerializeInteger(output, (int)obj, writeTypeCode); return; case Protocol16Type.Long: SerializeLong(output, (long)obj, writeTypeCode); return; case Protocol16Type.Float: SerializeFloat(output, (float)obj, writeTypeCode); return; case Protocol16Type.Double: SerializeDouble(output, (double)obj, writeTypeCode); return; case Protocol16Type.String: SerializeString(output, (string)obj, writeTypeCode); return; case Protocol16Type.EventData: SerializeEventData(output, (EventData)obj, writeTypeCode); return; case Protocol16Type.Hashtable: SerializeHashtable(output, (Hashtable)obj, writeTypeCode); return; case Protocol16Type.Dictionary: SerializeDictionary(output, (IDictionary)obj, writeTypeCode); return; case Protocol16Type.OperationResponse: SerializeOperationResponse(output, (OperationResponse)obj, writeTypeCode); return; case Protocol16Type.OperationRequest: SerializeOperationRequest(output, (OperationRequest)obj, writeTypeCode); return; case Protocol16Type.IntegerArray: case Protocol16Type.StringArray: case Protocol16Type.ByteArray: case Protocol16Type.ObjectArray: case Protocol16Type.Array: SerializeAnyArray(output, (Array)obj, writeTypeCode, type); return; } // Special case if (obj is ArraySegment <byte> arraySegment) { SerializeArraySegment(output, arraySegment, writeTypeCode); return; } throw new ArgumentException($"Cannot serialize objects of type {obj.GetType()} / System.TypeCode: {Type.GetTypeCode(obj.GetType())}"); }