private async Task <object> ReadEnumerable(Type type, Stream stream)
        {
            var elementType = TypeUtils.GetEnumerableItemType(type);

            var supportedElementType = true;

            if (elementType != null)
            {
                supportedElementType = TypeUtils.IsSupportedElementType(elementType);
            }

            if (elementType != null && supportedElementType)
            {
                var isNull = await ReadNullFlag(stream).ConfigureAwait(false);

                if (!isNull)
                {
                    var result = TypeUtils.CreateList(elementType);

                    var count = (int) await ReadPrimitive(typeof(int), stream).ConfigureAwait(false);

                    if (count > 0)
                    {
                        TraceUtils.WriteLineFormatted("Begin reading enumerable");

                        for (var i = 0; i < count; i++)
                        {
                            var item = await ReadPlainObject(elementType, stream).ConfigureAwait(false);

                            result.Add(item);
                            TraceUtils.WriteLineFormatted("Read #{0}/{1} of enumerable", i + 1, count);
                        }

                        TraceUtils.WriteLineFormatted("End reading enumerable");
                    }
                    else
                    {
                        TraceUtils.WriteLineFormatted("Enumerable is empty");
                    }

                    if (!type.IsArray)
                    {
                        return(result);
                    }

                    return(ConvertionUtils.ConvertListToArray(result));
                }
            }
            else if (elementType != null)
            {
                TraceUtils.WriteLineFormatted("Unable to read Enumerable of type \"{0}\": Unsupported element type \"{1}\"", type, elementType);
            }
            else
            {
                TraceUtils.WriteLineFormatted("Unable to read Enumerable of type \"{0}\": Unsupported", type);
            }


            return(null);
        }
Beispiel #2
0
        private Task WriteBytes(byte[] bytes, int length, Stream stream)
        {
            Debug.Assert(length <= bytes.Length);
            TraceUtils.WriteLineFormatted("Written {0} bytes", length);

            return(stream.WriteAsync(bytes, 0, length));
        }
Beispiel #3
0
        public async Task <object> Deserialize(Type objectType, Stream stream)
        {
            var targetTypeFullName = objectType.AssemblyQualifiedName;

            TraceUtils.WriteLineFormatted("Read object type...");
            var typeFullNameBytes = (byte[])await _reader.ReadObject(typeof(byte[]), stream).ConfigureAwait(false);

            byte[] targetTypeFullNameBytes;
            using (var md5 = MD5.Create())
            {
                // ReSharper disable once AssignNullToNotNullAttribute
                targetTypeFullNameBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(targetTypeFullName));
            }

            if (targetTypeFullNameBytes.SequenceEqual(typeFullNameBytes))
            {
                TraceUtils.WriteLineFormatted("Read object...");
                return(await _reader.ReadObject(objectType, stream));
            }

            var targetTypeBinaryString = string.Join("", targetTypeFullNameBytes.Select(x => Convert.ToString(x, 16).PadLeft(2, '0')));
            var typeBinaryString       = string.Join("", typeFullNameBytes.Select(x => Convert.ToString(x, 16).PadLeft(2, '0')));

            throw new ArgumentException($"Unable to deserialize object: Wrong type hash \"{typeBinaryString}\" expected \"{targetTypeBinaryString}\"");
        }
Beispiel #4
0
        public async Task WriteObject(object obj, Stream stream)
        {
            Debug.Assert(obj != null);
            Debug.Assert(stream != null);

            TraceUtils.WriteLineFormatted("*** BEGIN WRITING ***");

            await WriteObjectInternal(obj, stream).ConfigureAwait(false);

            TraceUtils.WriteLineFormatted("*** END WRITING ***");
        }
        public async Task <object> ReadObject(Type type, Stream stream)
        {
            Debug.Assert(stream != null);

            TraceUtils.WriteLineFormatted("*** BEGIN READING ***");
            try
            {
                return(await ReadObjectInternal(type, stream).ConfigureAwait(false));
            }
            finally
            {
                TraceUtils.WriteLineFormatted("*** END READING ***");
            }
        }
Beispiel #6
0
        public async Task Serialize(object obj, Stream stream)
        {
            var typeFullName = obj.GetType().AssemblyQualifiedName;

            byte[] typeFullNameBytes;
            using (var md5 = MD5.Create())
            {
                // ReSharper disable once AssignNullToNotNullAttribute
                typeFullNameBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(typeFullName));
            }

            TraceUtils.WriteLineFormatted("Write object type...");
            await _writer.WriteObject(typeFullNameBytes, stream).ConfigureAwait(false);

            TraceUtils.WriteLineFormatted("Write object...");
            await _writer.WriteObject(obj, stream).ConfigureAwait(false);
        }
        private async Task ReadStream(Stream stream, byte[] dst, int length)
        {
            TraceUtils.WriteLineFormatted("Read from stream {0}", length);

            int readBytes = 0, lastRead;

            do
            {
                lastRead = await stream.ReadAsync(dst, readBytes, length - readBytes);

                readBytes += lastRead;
            } while(readBytes < length && lastRead != 0);

            if (readBytes != length)
            {
                throw new SerializationException($"Unable to read data from stream. Except {length} but found only {readBytes} bytes");
            }
        }
Beispiel #8
0
        private async Task WriteCompositeObject(object obj, Type type, Stream stream)
        {
            TraceUtils.WriteLineFormatted("Writing composite object of type: {0}", type.FullName);

            var props = obj.GetProperties();

            if (props.Any())
            {
                foreach (var prop in props)
                {
                    var value = prop.GetValue(obj);

                    TraceUtils.WriteLineFormatted("Writing sub-object of property {0} with type: {1}", prop.Name, prop.PropertyType.FullName);
                    await WritePlainObject(value, prop.PropertyType, stream).ConfigureAwait(false);
                }
            }
            else
            {
                TraceUtils.WriteLineFormatted("Composite object hasn't any read\\write properties");
            }
        }
        private async Task <object> ReadObjectInternal(Type type, Stream stream)
        {
            if (type != typeof(object))
            {
                object resultObject;

                var objectType = TypeUtils.DetermineObjectType(type);
                if (objectType == ObjectType.Class || objectType == ObjectType.Struct)
                {
                    resultObject = await ReadCompositeObject(type, stream);
                }
                else
                {
                    TraceUtils.WriteLineFormatted("Reading plain object of type: {0}", type.FullName);
                    resultObject = await ReadPlainObject(type, stream);
                }

                return(resultObject);
            }

            TraceUtils.WriteLineFormatted("Unable to read object of type \"{0}\": Unsupported", type.FullName);
            return(null);
        }
Beispiel #10
0
        private async Task WriteObjectInternal(object obj, Stream stream)
        {
            Debug.Assert(obj != null);

            var type = obj.GetType();

            if (type != typeof(object))
            {
                var objectType = TypeUtils.DetermineObjectType(type);
                if (objectType == ObjectType.Class || objectType == ObjectType.Struct)
                {
                    await WriteCompositeObject(obj, type, stream).ConfigureAwait(false);
                }
                else
                {
                    TraceUtils.WriteLineFormatted("Writing plain object of type: {0}", type.FullName);
                    await WritePlainObject(obj, type, stream).ConfigureAwait(false);
                }
            }
            else
            {
                TraceUtils.WriteLineFormatted("Unable to write object of type \"{0}\": Unsupported", type.FullName);
            }
        }
        private async Task <object> ReadCompositeObject(Type type, Stream stream)
        {
            TraceUtils.WriteLineFormatted("Reading composite object of type: {0}", type.FullName);
            var resultingObject = Activator.CreateInstance(type);

            var props = resultingObject.GetProperties();

            if (props.Any())
            {
                foreach (var prop in props)
                {
                    TraceUtils.WriteLineFormatted("Reading sub-object of property {0} with type: {1}", prop.Name, prop.PropertyType.FullName);
                    var value = await ReadPlainObject(prop.PropertyType, stream).ConfigureAwait(false);

                    prop.SetValue(resultingObject, value);
                }
            }
            else
            {
                TraceUtils.WriteLineFormatted("Composite object hasn't any read\\write properties");
            }

            return(resultingObject);
        }
Beispiel #12
0
        private async Task WritePlainObject(object value, Type type, Stream stream)
        {
            Debug.Assert(type != null);
            Debug.Assert(stream != null);

            if (value != null)
            {
                var objectType = TypeUtils.DetermineObjectType(type);

                switch (objectType)
                {
                case ObjectType.Primitive:
                    await WritePrimitive(value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.Nullable:
                    await WriteNullableValueType(value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.String:
                    await WriteString((string)value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.DateTime:
                    await WriteDateTime((DateTime)value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.Class:
                    await WriteClass(value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.Struct:
                    await WriteStruct(value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.Enumerable:
                    if (value is byte[] bytes)
                    {
                        await WriteByteArray(bytes, stream);
                    }
                    else
                    {
                        await WriteEnumerable(value, type, stream).ConfigureAwait(false);
                    }
                    break;

                case ObjectType.Enum:
                    await WriteEnum(value, stream).ConfigureAwait(false);

                    break;

                case ObjectType.Unsupported:
                    TraceUtils.WriteLineFormatted("Unsupported value of type: \"{0}\"", type.FullName);
                    break;
                }
            }
            else
            {
                await WriteNullFlag(true, stream).ConfigureAwait(false);
            }
        }
Beispiel #13
0
        private async Task WriteEnumerable(object value, Type type, Stream stream)
        {
            var elementType = TypeUtils.GetEnumerableItemType(type);

            var supportedElementType = true;

            if (elementType != null)
            {
                supportedElementType = TypeUtils.IsSupportedElementType(elementType);
            }

            if (elementType != null && supportedElementType)
            {
                var enumerable = (IEnumerable)value;

                // ReSharper disable PossibleMultipleEnumeration
                var supportedEnumerable = enumerable.Cast <object>().All(item => item == null || item.GetType() == elementType);

                if (supportedEnumerable)
                {
                    TraceUtils.WriteLineFormatted("Begin writing enumerable");
                    await WriteNullFlag(false, stream).ConfigureAwait(false);

                    using (var internalStream = new MemoryStream())
                    {
                        var count = 0;
                        foreach (var item in enumerable)
                        {
                            await WritePlainObject(item, elementType, internalStream).ConfigureAwait(false);

                            ++count;
                        }

                        await WriteBytes(TemporaryBuffer, ConvertionUtils.Convert(count, TemporaryBuffer), stream).ConfigureAwait(false);

                        if (count > 0)
                        {
                            internalStream.Seek(0, SeekOrigin.Begin);
                            await internalStream.CopyToAsync(stream).ConfigureAwait(false);
                        }
                    }
                    // ReSharper restore PossibleMultipleEnumeration

                    TraceUtils.WriteLineFormatted("End writing enumerable");
                }
                else
                {
                    await WriteNullFlag(true, stream).ConfigureAwait(false);

                    TraceUtils.WriteLineFormatted("Unable to write Enumerable of type \"{0}\": All elements must be of one type", type);
                }
            }
            else if (elementType != null)
            {
                TraceUtils.WriteLineFormatted("Unable to write Enumerable of type \"{0}\": Unsupported element type \"{1}\"", type, elementType);
            }
            else
            {
                TraceUtils.WriteLineFormatted("Unable to write Enumerable of type \"{0}\": Unsupported", type);
            }
        }
        private async Task <object> ReadPlainObject(Type type, Stream stream)
        {
            Debug.Assert(type != null);
            Debug.Assert(stream != null);

            object result = null;

            var objectType = TypeUtils.DetermineObjectType(type);

            switch (objectType)
            {
            case ObjectType.Primitive:
                result = await ReadPrimitive(type, stream);

                break;

            case ObjectType.Nullable:
                result = await ReadNullable(type, stream);

                break;

            case ObjectType.String:
                result = await ReadString(stream);

                break;

            case ObjectType.DateTime:
                result = await ReadDateTime(stream);

                break;

            case ObjectType.Class:
                result = await ReadClass(type, stream);

                break;

            case ObjectType.Struct:
                result = await ReadStruct(type, stream);

                break;

            case ObjectType.Enumerable:
                if (type.IsEquivalentTo(typeof(byte[])))
                {
                    result = await ReadByteArray(stream);
                }
                else
                {
                    result = await ReadEnumerable(type, stream);
                }
                break;

            case ObjectType.Enum:
                result = await ReadEnum(type, stream);

                break;

            case ObjectType.Unsupported:
                TraceUtils.WriteLineFormatted("Unsupported value of type: \"{0}\"", type.FullName);
                result = Task.FromResult <object>(null);
                break;
            }

            return(result);
        }