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

[renderers-rust] Generated rust arrays longer than 32 do not serde Serialize #184

Open
wjthieme opened this issue Aug 21, 2024 · 7 comments
Assignees

Comments

@wjthieme
Copy link

Arrays longer than 32 cannot be Serialized with serde directly (catch-32). I suspect that is why the #[cfg_attr(feature = "serde", serde(with = "serde_with::As::<serde_with::Bytes>"))] proc macro is added to array fields longer than 32.

This however still fails with the following error:

the trait bound `serde_with::Bytes: SerializeAs<[T; N]>` is not satisfied

Example: The TickArray account in https://github.com/orca-so/whirlpools/tree/main/rust-sdk/client when compiled with serde feature enabled. This account has a field pub ticks: [Tick; 88] which it fails on.

@wjthieme wjthieme changed the title Arrays longer than 32 do not serde Serialize Generated rust arrays longer than 32 do not serde Serialize Aug 21, 2024
@wjthieme wjthieme changed the title Generated rust arrays longer than 32 do not serde Serialize [renderers-rust] Generated rust arrays longer than 32 do not serde Serialize Aug 21, 2024
@lorisleiva
Copy link
Member

Hey Will, thanks for raising this!

May I ask, do you need the serde feature/traits in your case?

@febo is the mastermind behind the Rust client and I know he's got some plans to make some of these traits configurables so you don't have to worry about them if you don't need them. He's OOO at the moment but might be able to help with this when he's back.

Otherwise, do you have an idea of what I could add to the generated Rust code to make this work?

@wjthieme
Copy link
Author

wjthieme commented Aug 21, 2024

Don't think we'd immediately need the 'serde' feature on the Codama generated code but would be nice to have for any consumer of our sdk (in case anyone needs it).

Since this is just a one-off case we currently have a custom (de)serializer for the field.

/// Serialize the fixed size tick array as a vector.
/// This is needed because Serde only supports fixed size arrays with <= 32 elements.
pub fn serialize_ticks<S>(value: &[Tick], serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let mut seq = serializer.serialize_seq(Some(TICK_ARRAY_SIZE_USIZE))?;

    for element in value {
        seq.serialize_element(element)?;
    }

    seq.end()
}

/// Deserialize the fixed size tick array from a vector.
/// This is needed because Serde only supports fixed size arrays with <= 32 elements.
pub fn deserialize_ticks<'de, D>(deserializer: D) -> Result<[Tick; TICK_ARRAY_SIZE_USIZE], D::Error>
where
    D: Deserializer<'de>,
{
    let vec = <Vec<Tick>>::deserialize(deserializer)?;

    vec.try_into().map_err(|_| de::Error::custom("wrong size"))
}

@wjthieme
Copy link
Author

Using #[cfg_attr(feature = "serde", serde(with = "BigArray"))] instead seems to work but it requires the serde-big-array crate.

Supposedly serde_with also has something for arrays larger than 32 but I couldn't get that to work: https://docs.rs/serde_with/latest/serde_with/#large-and-const-generic-arrays

@febo febo self-assigned this Sep 2, 2024
@lorisleiva
Copy link
Member

lorisleiva commented Oct 17, 2024

Hey @wjthieme, I think this PR maybe help with this issue.

Let me know what you think. 🙏

@wjthieme
Copy link
Author

@lorisleiva Awesome! Does this only work for Derive traits or can I also use it to add the serde(with = "BigArray") attribute?

Either way. the attribute that gets added to large arrays now (#[cfg_attr(feature = "serde", serde(with = "serde_with::As::<serde_with::Bytes>"))]) does not compile so that should probably be changed

@lorisleiva
Copy link
Member

It only works for Derive traits right now but we could extend the options to provide custom attributes if necessary. We tried to focus on the options that would have the most impact for people right now but let me know if there's anything else we can work on to unblock you.

@wjthieme
Copy link
Author

Probably the easiest fix would be to replace #[cfg_attr(feature = "serde", serde(with = "serde_with::As::<serde_with::Bytes>"))] with something that works. I kinda like serde(with = "BigArray") from serde-big-array crate but that would mean having to add an extra dependeny

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