near / borsh-rs

Rust implementation of Binary Object Representation Serializer for Hashing
https://borsh.io/
Apache License 2.0
302 stars 66 forks source link

Ser de type parameter bounds attr on fields #179

Closed dj8yfo closed 1 year ago

dj8yfo commented 1 year ago

This is logical continuation/conclusion of #178 .

It's overriding bounds for BorshSerialize and BorshDeserialize in order to allow not to keep bounds on type parameters in struct definition itself and fix complex cases, when derive hasn't figured the right bounds on type parameters automatically, while still not having to implement the traits manually.

/// `T: PartialOrd` is injected here via field bound to avoid having this restriction on
/// the struct itself
#[cfg(hash_collections)]
#[derive(BorshSerialize)]
struct C1<T, U> {
    a: String,
    #[borsh(bound(serialize = 
        "T: borsh::ser::BorshSerialize + PartialOrd,
         U: borsh::ser::BorshSerialize"))]
    b: HashMap<T, U>,
}

/// `T: PartialOrd + Hash + Eq` is injected here via field bound to avoid having this restriction on
/// the struct itself
#[allow(unused)]
#[cfg(hash_collections)]
#[derive(BorshDeserialize)]
struct C2<T, U> {
    a: String,
    #[borsh(bound(
        deserialize = 
        "T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize,
         U: borsh::de::BorshDeserialize"
    ))]
    b: HashMap<T, U>,
}

/// implicit derived `core::default::Default` bounds on `K` and `V` are dropped by empty bound
/// specified, as `HashMap` has its own `Default` implementation
#[cfg(hash_collections)]
#[derive(BorshDeserialize)]
struct G3<K, V, U>(
    #[borsh_skip]
    #[borsh(bound(deserialize = ""))]
    HashMap<K, V>,
    U,
);
// derive here figures the bound erroneously as `T: borsh::ser::BorshSerialize`
#[derive(BorshSerialize)]
struct ParametrizedWronDerive<T, V>
where
    T: TraitName,
{
    #[borsh(bound(serialize = "<T as TraitName>::Associated: borsh::ser::BorshSerialize"))]
    field: <T as TraitName>::Associated,
    another: V,
}