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

Serde_json arbitrary precision #480

Closed
717a56e1 opened this issue Sep 20, 2021 · 15 comments
Closed

Serde_json arbitrary precision #480

717a56e1 opened this issue Sep 20, 2021 · 15 comments

Comments

@717a56e1
Copy link

jsonrpc had a feature flag to allow arbitrary_precision, this library currently breaks if it is built with it. Could be we open to adding a similar serde_from_str override?

@dvdplm
Copy link
Contributor

dvdplm commented Sep 21, 2021

Yes, I think we need to add that. It's not pretty but I don't see a better way at the moment.

For other readers, here's some context:

@717a56e1 Are you open to contributing a PR?

@niklasad1
Copy link
Member

I agree but IIRC this affects mainly u128/i128 and floats but comes with extra costs.

@717a56e1
Copy link
Author

Yup, got it running with a patched from_slice, should get up PR up. Any place we'd like to put the function? I've got it in types/lib.rs.

@dvdplm
Copy link
Contributor

dvdplm commented Sep 21, 2021

Probably better off in jsonrpsee-utils I think. @niklasad1 wdyt?

@niklasad1
Copy link
Member

I don't know really because we re-export serde stuff from types so a utility function in types probably makes most sense but I need to see to code first before saying yes or no :)

Either should be fine I think...

@dvdplm dvdplm mentioned this issue Oct 1, 2021
10 tasks
@dvdplm dvdplm mentioned this issue Nov 23, 2021
7 tasks
@niklasad1
Copy link
Member

niklasad1 commented Nov 29, 2021

Hey, I have investigated arbitrary precision feature in serde. It defeats our zero-alloc parsing of RpcParams and it's really inefficient in practice one would have to do json_str -> serde_json::Value -> T

Further, as the Request/Response types in jsonrpsee doesn't use #[serde(untagged/flatten)] those will work anyway but there are two cases where arbitrary precision are needed at to moment:

  1. custom types as "JSON-RPC params" or "JSON-RPC result" that have #[serde(untagged/flatten)] with u128/u128 as field (no way to mitigate those)
  2. ParamsSer that is currently only used by the client but could be fixed.

Thus, the server supports plain u128/u128 but not in combination with #[serde(untagged/flatten)]. I regard this as a serde issue and I prefer not support it because it's so much slower but if more people show interest of this I'm willing to add it behind a feature flag.

@niklasad1
Copy link
Member

@717a56e1 you can explain your use-case it would help us to understand the motivation behind this?

@717a56e1
Copy link
Author

I've been using custom types with u128 and serde untagged, performance isn't too critical in my use case. I've been running a branch with the custom headers and the double deserialization hack (behind a feature gate).

It has been working fine on websockets (haven't really used http side of the crate but assume the deserialization logic is common).

I'm still fine opening a pull request for this, we had run into some strange behavior with serde untagged (specifically with u128) and was hoping to sort that out before opening the PR.

Realistically at this point I see my use case moving away from untagged towards custom Deserialize impls until untagged is stabilized upstream.

@717a56e1
Copy link
Author

717a56e1 commented Nov 29, 2021

Perhaps a bit more context, I've rebased and applied the changes more consistently. jsonrpsee tests break quite broadly because of the induced allocations, i.e.
thread 'v2::request::test::deserialize_valid_notif_works' panicked at 'called Result::unwrap() on an Err value: Error("invalid type: string \"say_hello\", expected a borrowed string", line: 0, column: 0)', types/src/v2/request.rs:149:71

Also, ID deserialization fails with arbitrary_precision enabled (since it's an untagged enum) without the deserializing to value first, even though none of the types are u128/i128.

@niklasad1
Copy link
Member

ah, I see

thread 'v2::request::test::deserialize_valid_notif_works' panicked at 'called Result::unwrap() on an Err value: Error("invalid type: string "say_hello", expected a borrowed string", line: 0, column: 0)', types/src/v2/request.rs:149:71

I think we need put the method names in Cow<'a, str> instead of &'a str for that to work, similar to what we did in #578. I can fix that for in master.

Also, ID deserialization fails with arbitrary_precision enabled (since it's an untagged enum) without the deserializing to value first, even though none of the types are u128/i128.

can you share the error? I think it might a similar reason.

@717a56e1
Copy link
Author

717a56e1 commented Nov 30, 2021

Sure thing. Let me park this on a branch as well: https://github.com/717a56e1/jsonrpsee

thread 'v2::params::test::id_deserialization' panicked at 'called `Result::unwrap()` on an `Err` value: Error("data did not match any variant of untagged enum Id", line: 0, column: 0)', types/src/v2/params.rs:376:56

@niklasad1
Copy link
Member

niklasad1 commented Nov 30, 2021

alright that is expected I realize now with arbitrary_precision serde can't deduce that Number variant is u64.

We might consider to a handwritten deserialize impl for Id and SubscriptionId instead then.

@niklasad1
Copy link
Member

Hey @717a56e1 again,

We have been discussing this internally and came to the conclusion not support this because it's really a "serde-json bug" and defeats the zero-alloc serialization/deserialization with serde_json::RawValue, "we" (parity) tried to get serde-rs/json#586 merged but got rejected so please work with serde to get this fixed properly.

In addition it can break things because it's a feature flag so it will be enabled for anything that depends on serde (note if anyone enabled --feature arbritary-precision on serde-json this might end up with weird scenarios but nothing we can do in this crate to protect against that)

We might revisit this in the future but it's not really anything we will work on to support any time soon so closing this.

@717a56e1
Copy link
Author

@niklasad1 Any interest in getting arbitrary-precision working without serde flatten/untagged? I see you've gotten rid of most of the uses of untagged besides ParamsSer, and for my use-case I've given up on those macros until they're fixed upstream.

If so I can open another issue/PR.

@niklasad1
Copy link
Member

Go ahead and open a PR so I understand what you mean, so it depends how clean it will be :)

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

No branches or pull requests

3 participants