using ln.type; using System; using System.IO; using System.Reflection; using System.Runtime.Serialization; using System.Text; namespace ln.objects.serialization.binary { public class BinaryDeserializer : Deserializer { public override bool DeserializeObject(byte[] serializedBytes, ref object o) { MemoryStream ms = new MemoryStream(serializedBytes); if (!Object.ReferenceEquals(null,o) && (serializedBytes[0] == 'S')) { ms.ReadByte(); String typeName = (string)Deserialize(ms); DeserializeStructured(ms, o.GetType(), o); } else { o = Deserialize(ms); } return true; } public override bool TryGetType(byte[] serializedBytes, out Type type) => TryGetType(new MemoryStream(serializedBytes), out type); public bool TryGetType(Stream stream, out Type type) { int tc; switch (tc = stream.ReadByte()) { case -1: throw new EndOfStreamException(); case '0': type = null; break; case 'P': return TryGetPrimitiveType(stream, out type); case 'R': case 'S': case 'E': type = Type.GetType(Deserialize(stream) as string); break; case 'A': type = Type.GetType(Deserialize(stream) as string).MakeArrayType(); break; case 'B': type = typeof(byte[]); break; case 'G': type = typeof(Guid); break; default: type = null; return false; } return true; } public bool TryGetPrimitiveType(Stream stream, out Type type) { int tc; switch (tc = stream.ReadByte()) { case -1: throw new EndOfStreamException(); case 'I': type = typeof(int); break; case 'i': type = typeof(uint); break; case 'B': type = typeof(byte); break; case 'C': type = typeof(char); break; case 'S': type = typeof(short); break; case 's': type = typeof(ushort); break; case 'L': type = typeof(long); break; case 'l': type = typeof(ulong); break; case 'F': type = typeof(float); break; case 'D': type = typeof(double); break; case 'b': type = typeof(bool); break; case 'T': type = typeof(string); break; default: type = null; return false; } return true; } object Deserialize(Stream stream) { int tc; switch (tc = stream.ReadByte()) { case -1: throw new EndOfStreamException(); case '0': return null; case 'P': return DeserializePrimitive(stream); case 'R': return DeserializeReference(stream); case 'S': return DeserializeStructured(stream); case 'E': return DeserializeEnum(stream); case 'A': return DeserializeArray(stream); case 'B': return DeserializeByteArray(stream); case 'G': return DeserializeGuid(stream); default: throw new NotSupportedException(String.Format("Unsupported type code: {0}", (char)tc)); } } object DeserializePrimitive(Stream stream) { int tc; switch (tc = stream.ReadByte()) { case -1: throw new EndOfStreamException(); case 'I': return stream.ReadInteger(); case 'i': return stream.ReadUInteger(); case 'B': return (byte)stream.ReadByte(); case 'C': return (char)stream.ReadShort(); case 'S': return stream.ReadShort(); case 's': return stream.ReadUShort(); case 'L': return stream.ReadLong(); case 'l': return stream.ReadULong(); case 'F': return stream.ReadFloat(); case 'D': return stream.ReadDouble(); case 'b': return stream.ReadByte() != 0; case 'T': int tl = stream.ReadInteger(); byte[] tbytes = stream.ReadBytes(tl); return Encoding.UTF8.GetString(tbytes); default: throw new NotSupportedException(String.Format("Unsupported primitive type code: {0}", (char)tc)); } } object DeserializeGuid(Stream stream) => new Guid(stream.ReadBytes(16)); object DeserializeEnum(Stream stream) { Type eType = Type.GetType(Deserialize(stream) as string); object value = Deserialize(stream); if (value is int nvalue) return Enum.ToObject(eType, nvalue); else if (value is string svalue) return Enum.Parse(eType, svalue); else throw new NotSupportedException("Unsupported ENUM repressentation found"); } object DeserializeByteArray(Stream stream) { int length = stream.ReadInteger(); return stream.ReadBytes(length); } object DeserializeArray(Stream stream) { Type etype = Type.GetType(Deserialize(stream) as string); int length = stream.ReadInteger(); Array array = Array.CreateInstance(etype, length); for (int n = 0; n < array.Length; n++) array.SetValue(Deserialize(stream), n); return array; } object DeserializeStructured(Stream stream) { String typeName = (string)Deserialize(stream); Type type = Type.GetType(typeName); object o = type.IsValueType ? Activator.CreateInstance(type) : Activator.CreateInstance(type, true); DeserializeStructured(stream, type, o); return o; } void DeserializeStructured(Stream stream, Type type, object o) { int nFields = stream.ReadInteger(); for (int n=0;n