Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SerializerGenerator should not generate Nullable(or other) type #104

Closed
neuecc opened this issue Aug 4, 2015 · 1 comment
Closed

SerializerGenerator should not generate Nullable(or other) type #104

neuecc opened this issue Aug 4, 2015 · 1 comment
Labels
bug Detected as bug

Comments

@neuecc
Copy link

neuecc commented Aug 4, 2015

My expected generator's behaviour is that doesn't generate if target type is in builtin serializer.
But several types, for example Nullable can generate by SerializerGenerator.
Resulting in, Packed by genereted serializer data can't unpack builtin serializer.

This come from Serializer.Get checks Array, Nullable, List, Dictionary
https://github.com/msgpack/msgpack-cli/blob/master/src/MsgPack/Serialization/DefaultSerializers/GenericSerializer.cs#L54-L92
But CodeComContext.BuildIntSerializerExists only see IsArray.
https://github.com/msgpack/msgpack-cli/blob/master/src/MsgPack/Serialization/CodeDomSerializers/CodeDomContext.cs#L149

The following is unexpected result.

var context = new SerializationContext
{
    EnumSerializationMethod = EnumSerializationMethod.ByUnderlyingValue,
    GeneratorOption = SerializationMethodGeneratorOption.Fast,
    SerializationMethod = SerializationMethod.Array
};

var dynamicNullableSerializer = context.GetSerializer<Nullable<int>>();
var preGeneratedSerializer = new System_Nullable_1_System_Int32_Serializer(context);

var v = dynamicNullableSerializer.PackSingleObject(new Nullable<int>(1000));
var result = preGeneratedSerializer.UnpackSingleObject(v);

Console.WriteLine(result.Value); // expected = 1000 but result = 2
[System.CodeDom.Compiler.GeneratedCodeAttribute("MsgPack.Serialization.CodeDomSerializers.CodeDomSerializerBuilder", "0.6.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public class System_Nullable_1_System_Int32_Serializer : MsgPack.Serialization.MessagePackSerializer<System.Nullable<int>>
{

    private MsgPack.Serialization.MessagePackSerializer<bool> _serializer0;

    private MsgPack.Serialization.MessagePackSerializer<int> _serializer1;

    public System_Nullable_1_System_Int32_Serializer(MsgPack.Serialization.SerializationContext context) :
            base(context)
    {
        MsgPack.Serialization.PolymorphismSchema schema0 = default(MsgPack.Serialization.PolymorphismSchema);
        schema0 = null;
        this._serializer0 = context.GetSerializer<bool>(schema0);
        MsgPack.Serialization.PolymorphismSchema schema1 = default(MsgPack.Serialization.PolymorphismSchema);
        schema1 = null;
        this._serializer1 = context.GetSerializer<int>(schema1);
    }

    protected override void PackToCore(MsgPack.Packer packer, System.Nullable<int> objectTree)
    {
        packer.PackArrayHeader(2);
        this._serializer0.PackTo(packer, objectTree.HasValue);
        this._serializer1.PackTo(packer, objectTree.Value);
    }

    protected override System.Nullable<int> UnpackFromCore(MsgPack.Unpacker unpacker)
    {
        System.Nullable<int> result = default(System.Nullable<int>);
        if (unpacker.IsArrayHeader)
        {
            int unpacked = default(int);
            int itemsCount = default(int);
            itemsCount = MsgPack.Serialization.UnpackHelpers.GetItemsCount(unpacker);
            int ctorArg0 = default(int);
            ctorArg0 = 0;
            unpacker.Read();
            System.Nullable<int> nullable = default(System.Nullable<int>);
            if ((unpacked < itemsCount))
            {
                nullable = MsgPack.Serialization.UnpackHelpers.UnpackNullableInt32Value(unpacker, typeof(System.Nullable<int>), "Int32 Value");
            }
            if (nullable.HasValue)
            {
                ctorArg0 = nullable.Value;
            }
            unpacked = (unpacked + 1);
            result = new System.Nullable<int>(ctorArg0);
        }
        else
        {
            int itemsCount0 = default(int);
            itemsCount0 = MsgPack.Serialization.UnpackHelpers.GetItemsCount(unpacker);
            int ctorArg00 = default(int);
            ctorArg00 = 0;
            for (int i = 0; (i < itemsCount0); i = (i + 1))
            {
                string key = default(string);
                string nullable0 = default(string);
                nullable0 = MsgPack.Serialization.UnpackHelpers.UnpackStringValue(unpacker, typeof(System.Nullable<int>), "MemberName");
                if (((nullable0 == null)
                            == false))
                {
                    key = nullable0;
                }
                else
                {
                    throw MsgPack.Serialization.SerializationExceptions.NewNullIsProhibited("MemberName");
                }
                if ((key == "Value"))
                {
                    System.Nullable<int> nullable1 = default(System.Nullable<int>);
                    nullable1 = MsgPack.Serialization.UnpackHelpers.UnpackNullableInt32Value(unpacker, typeof(System.Nullable<int>), "Int32 Value");
                    if (nullable1.HasValue)
                    {
                        ctorArg00 = nullable1.Value;
                    }
                }
                else
                {
                    unpacker.Skip();
                }
            }
            result = new System.Nullable<int>(ctorArg00);
        }
        return result;
    }

    private static T @__Conditional<T>(bool condition, T whenTrue, T whenFalse)
    {
        if (condition)
        {
            return whenTrue;
        }
        else
        {
            return whenFalse;
        }
    }
}
@yfakariya yfakariya added the bug Detected as bug label Aug 4, 2015
yfakariya added a commit that referenced this issue Aug 4, 2015
…s poor code generation for nullable types. Issue #104.

CodeDomContext and AssemblyBuilderCodeGenerationContext did not handle List<T>, Dictionary<TKey,TValue>, Immutable collections, and other collections in reflection based context correctly. So move determination to GenericSerializer itself with refactoring to avoid duplication for immutable collection determination logic.
This commit also add new API PreferReflectionBasedSerializer, which specifies that we prefer reflection based serializer than code-gen based serializer when we use generated serializer. This option is needed for generated serializers to work well in iOS environments.
@yfakariya
Copy link
Member

Fixed in 0.6.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Detected as bug
Projects
None yet
Development

No branches or pull requests

2 participants