private static void WriteGenericTypeArgument(BinaryWriter writer, Type type)
        {
            var objTypeCode = SerializerUtil.GetObjectTypeCode(type, null);

            writer.Write((byte)objTypeCode);

            switch (objTypeCode)
            {
            case ObjectTypeCode.Serializable:
                writer.Write(type.AssemblyQualifiedName);
                break;

            case ObjectTypeCode.Primitive: {
                var primitiveCode = SerializerUtil.GetPrimitiveCode(type);
                writer.Write(SerializerUtil.IsNullable(type));
                writer.Write((byte)primitiveCode);
                break;
            }

            case ObjectTypeCode.Object:
                break;

            default:
                throw new SerializationException($"The type {type} is not a supported generic agument type");
            }
        }
        private static void WriteArray(BinaryWriter writer, Type objectType, object obj)
        {
            var elementType  = objectType.GetElementType();
            var elemTypeCode = SerializerUtil.GetObjectTypeCode(elementType, obj);

            writer.Write((byte)elemTypeCode);

            switch (elemTypeCode)
            {
            case ObjectTypeCode.Primitive:
                var primitiveTypeCode = SerializerUtil.GetPrimitiveCode(elementType);
                writer.Write((byte)primitiveTypeCode);
                break;

            case ObjectTypeCode.Serializable:
                var name = elementType.AssemblyQualifiedName;

                writer.Write(name);
                break;

            case ObjectTypeCode.Object:
                break;

            default:
                throw new NotSupportedException($"Array of type {elementType} is not supported");
            }

            if (obj == null)
            {
                return;
            }

            var array = (Array)obj;

            if (array.Rank > 1)
            {
                throw new NotSupportedException("Multi-dimensional arrays not supported");
            }

            writer.Write(array.Length);

            for (int i = 0; i < array.Length; i++)
            {
                var value = array.GetValue(i);
                WriteObject(writer, elementType, value);
            }
        }
        private static void WritePrimitive(BinaryWriter writer, Type objectType, object value)
        {
            var code     = SerializerUtil.GetPrimitiveCode(objectType);
            var nullable = SerializerUtil.IsNullable(objectType);

            writer.Write(nullable);
            writer.Write((byte)code);

            if (value == null)
            {
                return;
            }

            switch (code)
            {
            case PrimitiveTypeCode.Boolean:
                writer.Write((bool)value);
                break;

            case PrimitiveTypeCode.Byte:
                writer.Write((byte)value);
                break;

            case PrimitiveTypeCode.SByte:
                writer.Write((sbyte)value);
                break;

            case PrimitiveTypeCode.Int16:
                writer.Write((short)value);
                break;

            case PrimitiveTypeCode.UInt16:
                writer.Write((ushort)value);
                break;

            case PrimitiveTypeCode.Int32:
                writer.Write((int)value);
                break;

            case PrimitiveTypeCode.UInt32:
                writer.Write((uint)value);
                break;

            case PrimitiveTypeCode.Int64:
                writer.Write((long)value);
                break;

            case PrimitiveTypeCode.UInt64:
                writer.Write((ulong)value);
                break;

            case PrimitiveTypeCode.Single:
                writer.Write((float)value);
                break;

            case PrimitiveTypeCode.Double:
                writer.Write((double)value);
                break;

            case PrimitiveTypeCode.Char:
                writer.Write((char)value);
                break;

            case PrimitiveTypeCode.String:
                writer.Write((string)value);
                break;
            }
        }