libmir / mir-ion

Ion, JSON, YAML, CSV, CBOR and Msgpack serialization framework
Apache License 2.0
14 stars 6 forks source link

Unexpected IonTypeCode with deserializeIon!(Variant!T) #19

Closed WebFreak001 closed 2 years ago

WebFreak001 commented 2 years ago

Reproduction case: (I have SumType as custom type which defines serdeIgnoreOut)

import std.stdio;
import mir.ser.json : serializeJson;
import mir.deser.json : deserializeDynamicJson;

struct SumType(Types...)
{
    import std.sumtype : StdSumType = SumType, match;
    import mir.ion.exception;
    import mir.ion.value;

    StdSumType!Types value;
    alias value this;

    this(T)(T v)
    {
        value = typeof(value)(v);
    }

    void serialize(S)(ref S serializer) const
    {
        import mir.ser : serializeValue;

        value.match!(v => serializeValue(serializer, v));
    }

    IonException deserializeFromIon(scope const char[][] symbolTable, IonDescribedValue inputValue)
    {
        import mir.deser.ion : deserializeIon;
        import mir.algebraic : Variant, match;

        auto alg = deserializeIon!(Variant!Types)(symbolTable, inputValue);
        alg.match!(v => value = v);
        return null;
    }
}

struct Location
{
    string uri;
}

alias LocValue = SumType!(Location[], Location);

void main()
{
    auto v = LocValue(Location("file:///foo.d"));
    auto serialized = v.serializeJson;
    writeln(serialized);
    assert(deserializeDynamicJson!LocValue(serialized) == v);
}
Running a 
{"uri":"file:///foo.d"}
mir.ion.exception.IonException@/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/package.d(1230): Unexpected IonTypeCode for Algebraic!(Location[], Location)
----------------
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/ion.d:60 pure @safe void mir.deser.ion.deserializeIon!(mir.algebraic.Algebraic!(app.Location[], app.Location).Algebraic, false).deserializeIon!().deserializeIon(ref mir.algebraic.Algebraic!(app.Location[], app.Location).Algebraic, scope const(char[][]), mir.ion.value.IonDescribedValue) [0x557dd89137a1]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/ion.d:29 pure @safe mir.algebraic.Algebraic!(app.Location[], app.Location).Algebraic mir.deser.ion.deserializeIon!(mir.algebraic.Algebraic!(app.Location[], app.Location).Algebraic, false).deserializeIon!().deserializeIon(scope const(char[][]), mir.ion.value.IonDescribedValue) [0x557dd891364c]
source/app.d:31 pure mir.ion.exception.IonException app.SumType!(app.Location[], app.Location).SumType.deserializeFromIon(scope const(char[][]), mir.ion.value.IonDescribedValue) [0x557dd890ca51]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/package.d:479 pure mir.ion.exception.IonException mir.deser.deserializeValue!(null).deserializeValue!(app.SumType!(app.Location[], app.Location).SumType, 1, false).deserializeValue(mir.deser.DeserializationParams!(1, false).DeserializationParams, ref app.SumType!(app.Location[], app.Location).SumType) [0x557dd891319a]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/ion.d:59 pure void mir.deser.ion.deserializeIon!(app.SumType!(app.Location[], app.Location).SumType, false).deserializeIon!().deserializeIon(ref app.SumType!(app.Location[], app.Location).SumType, scope const(char[][]), mir.ion.value.IonDescribedValue) [0x557dd891187f]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/ion.d:126 pure int mir.deser.ion.deserializeIon!(app.SumType!(app.Location[], app.Location).SumType, false).deserializeIon!().deserializeIon(ref app.SumType!(app.Location[], app.Location).SumType, scope const(ubyte)[]).__foreachbody3(const(char[])[], mir.ion.value.IonDescribedValue) [0x557dd8911740]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/ion/stream.d:42 pure @nogc @safe int mir.ion.stream.IonValueStream.opApply(scope int delegate(const(char[])[], mir.ion.value.IonDescribedValue) pure @nogc @safe).__lambda2(mir.ion.exception.IonErrorCode, const(char[])[], mir.ion.value.IonDescribedValue) [0x557dd891ef70]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/ion/stream.d:233 const pure nothrow @nogc scope @trusted int mir.ion.stream.IonValueStream.opApply(scope int delegate(mir.ion.exception.IonErrorCode, const(char[])[], mir.ion.value.IonDescribedValue) pure nothrow @nogc @safe) [0x557dd891f3b6]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/ion/stream.d:247 const pure @nogc scope @trusted int mir.ion.stream.IonValueStream.opApply(scope int delegate(mir.ion.exception.IonErrorCode, const(char[])[], mir.ion.value.IonDescribedValue) pure @nogc @safe) [0x557dd891f737]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/ion/stream.d:39 const pure @nogc scope @safe int mir.ion.stream.IonValueStream.opApply(scope int delegate(const(char[])[], mir.ion.value.IonDescribedValue) pure @nogc @safe) [0x557dd891ef0a]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/ion/stream.d:74 const pure scope int mir.ion.stream.IonValueStream.opApply(scope int delegate(const(char[])[], mir.ion.value.IonDescribedValue) pure) [0x557dd891f093]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/ion.d:124 pure void mir.deser.ion.deserializeIon!(app.SumType!(app.Location[], app.Location).SumType, false).deserializeIon!().deserializeIon(ref app.SumType!(app.Location[], app.Location).SumType, scope const(ubyte)[]) [0x557dd89116e5]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/json.d:417 pure void mir.deser.json.deserializeDynamicJson!(app.SumType!(app.Location[], app.Location).SumType).deserializeDynamicJson(ref app.SumType!(app.Location[], app.Location).SumType, scope const(char)[]) [0x557dd89116a2]
/home/webfreak/.dub/packages/mir-ion-1.0.31/mir-ion/source/mir/deser/json.d:408 pure app.SumType!(app.Location[], app.Location).SumType mir.deser.json.deserializeDynamicJson!(app.SumType!(app.Location[], app.Location).SumType).deserializeDynamicJson(scope const(char)[]) [0x557dd891165f]
source/app.d:49 _Dmain [0x557dd890c9a1]
Program exited with code 1
9il commented 2 years ago

Fix:

import mir.serde : serdeFallbackStruct;
@serdeFallbackStruct
struct Location
{
    string uri;
}

BTW, find examples with @serdeProxy in source code. That will simplify you example a lot.

WebFreak001 commented 2 years ago

do I need to put @serdeFallbackStruct on all my structs?

9il commented 2 years ago

A required UDA is depends on how do you group them inside the Variant.

BTW, why do you need your own algebraic template?

9il commented 2 years ago

Or Std algebraic. Could you use Mir or something doesn't work for you?