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

add @serdeProxyCast, @serdeEnumProxy UDAs #408

Merged
merged 1 commit into from
Jun 24, 2022
Merged

Conversation

WebFreak001
Copy link
Contributor

@WebFreak001 WebFreak001 commented May 26, 2022

PR on the mir-ion side will follow shortly.

Idea is that you can do this:

@serdeEnumProxy!uint
// equivalent to @serdeProxyCast @serdeEnumProxy!uint
enum Foo
{
    a = 1,
    b = 2
}

and Foo will be

  1. serialized by int (as usual with serdeProxy)
  2. allows other values than 1 and 2 to be (de)serialized

@9il
Copy link
Member

9il commented May 26, 2022

Why it is needed? The following code works:

    import mir.ser.text;
    import mir.deser.text;

    @serdeProxy!int
    enum Foo
    {
        a = 1,
        b = 2
    }

    assert(Foo.b.serializeText == "2");
    assert("2".deserializeText!Foo == Foo.b);

@9il
Copy link
Member

9il commented May 26, 2022

Ah, got it.

@9il
Copy link
Member

9il commented May 26, 2022

But that works as well:

    import mir.ser.text;
    import mir.deser.text;

    @serdeProxy!int
    enum Foo
    {
        a = 1,
        b = 2
    }

    assert((cast(Foo)6).serializeText == "6", Foo.b.serializeText);
    assert("6".deserializeText!Foo == 6);

@WebFreak001
Copy link
Contributor Author

But that works as well:

    import mir.ser.text;
    import mir.deser.text;

    @serdeProxy!int
    enum Foo
    {
        a = 1,
        b = 2
    }

    assert((cast(Foo)6).serializeText == "6", Foo.b.serializeText);
    assert("6".deserializeText!Foo == 6);

there is no change in how serialization works here, it partly worked before and was kind of inconsistent, that's why I added a new UDA instead of trying to change behavior in one way or the other.

The mir-ion unittest also checks for this for known currently broken/valid cases:
https://github.com/libmir/mir-ion/pull/22/files#diff-b21fe8bb968514207405f1eb867afb267ce2c6faaa9e8d0ffd9579795f4cdfb8R1270-R1273

https://github.com/libmir/mir-ion/pull/22/files#diff-b21fe8bb968514207405f1eb867afb267ce2c6faaa9e8d0ffd9579795f4cdfb8R1270-R1273

@9il
Copy link
Member

9il commented May 26, 2022

A special user-defined conversion logic can be done using serdeProxy:

template MyEnumProxyImpl(T)
{
    @serdeProxy!T
    struct MyEnumProxyImpl
    {
        T value;
        // implement conversion To/From Enum's of T types AND base T
    }
}

alias MyEnumProxy(T) = serdeProxy!(MyEnumProxyImpl!T))

@MyEnumProxy!int
enum E { a, b }

Can this work for you?

@WebFreak001
Copy link
Contributor Author

ok this worked, but imo this is something worth adding to mir:

template MyEnumProxyImpl(T)
{
	@serdeProxy!T
	struct MyEnumProxyImpl
	{
		T value;
		alias value this;

		this(T value)
		{
			this.value = value;
		}
	}
}

alias serdeEnumProxy(T) = serdeProxy!(MyEnumProxyImpl!T);

@WebFreak001
Copy link
Contributor Author

WebFreak001 commented Jun 15, 2022

nvm that serdeEnumProxy implementation breaks with variants as it's a struct and doesn't get matched. I can't add serdeFallbackStruct as I already have it on another thing. serdeFallbackStruct also doesn't fix it.

I still think the addition with this PR (and the one in mir-ion) would be the most stable and most efficient.

at least this is an example exception I get from this:

mir.ion.exception.IonException@../../.dub/packages/mir-ion-1.0.50/mir-ion/source/mir/deser/package.d(1211): Unexpected IonTypeCode for MirAlgebraic!(NoneType, FailureHandlingKind)

Implementation is needed on the mir-ion side for use though
@WebFreak001
Copy link
Contributor Author

@9il can we get this in? The user defined struct breaks Mir's Algebraic and fixing that is hard, while the proxy cast has a super simple implementation (just using cast instead of to) which allows for better enum control.

I currently need this for my serve-d mir-ion port where I have a bunch of Algebraic!(void, T) and T being a string enum that might also contain unknown values due to protocol upgrades.

@9il 9il merged commit 5818b5a into libmir:master Jun 24, 2022
WebFreak001 added a commit to WebFreak001/mir-ion that referenced this pull request Jun 24, 2022
WebFreak001 added a commit to WebFreak001/mir-ion that referenced this pull request Sep 26, 2022
9il pushed a commit to libmir/mir-ion that referenced this pull request Oct 2, 2022
* Support `@serdeEnumProxy` (`@serdeProxyCast`) UDA

See libmir/mir-algorithm#408

* adjust to review
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants