Why does Vec<u8> give an error when used as a Type in a Trait

For example, when i use the following:

trait Deserialize<String, E>: Sized {
    fn deserialize(data: Vec<u8>, key_chain: Option<DefaultKeyChain>, chain_path: Option<ChainPath>) -> Result<Self, E>;
}

or 

trait Deserialize<T, E>: Sized {
    fn deserialize(data: Vec<u8>, key_chain: Option<DefaultKeyChain>, chain_path: Option<ChainPath>) -> Result<Self, E>;
}

I don't get any error, but when I try to do something like this:

trait Deserialize<Vec<u8>, E>: Sized {
    fn deserialize(data: Vec<u8>, key_chain: Option<DefaultKeyChain>, chain_path: Option<ChainPath>) -> Result<Self, E>;
}

I get this error

error: expected one of `,`, `:`, `=`, or `>`, found `<`
   |
18 | trait Deserialize<Vec<u8>, E>: Sized {
   |                      ^ expected one of `,`, `:`, `=`, or `>`

This creates two generic parameters, String and E. The String generic parameter there has no relation to the standard library std::string::String type.

Therefore when you write trait Deserialize<Vec<u8>, E> that is equivalent to trait Deserialize<A<B>, E> which of course is invalid syntax.

2 Likes

Thank you!

Please, how do you implement the Deserialize trait for single type conversion?

For example

For only when converting specifically String types.
trait Deserialize<T, E>: Sized {
    fn deserialize(data: Vec<u8>) -> Result<Self, E>;
}

and

For only when converting specifically Vec<u8> types.
trait Deserialize<T, E>: Sized {
    fn deserialize(data: Vec<u8>,  key_chain: DefaultKeyChain, chain_path: ChainPath) -> Result<Self, E>;
}

So different types have a set of function parameters.

impl Deserialize<String, Error> for PrivKey {
    fn deserialize(data: String) -> Result<PrivKey, Error> {
    }
}
impl Deserialize<Vec<u8>, Error> for PrivKey {
    fn deserialize(data: String, key_chain: DefaultKeyChain>, chain_path: ChainPath) -> Result<PrivKey, Error> {
    }
}

Rust doesn't have trait specialisation, at least yet (and if it did you would near certainly hit the orphan rule here, and you don't own either the trait or argument)

You should be able to get pretty close with a new blanket implemented trait, though (untested, I'm on a phone):

trait MyDeserialize<E>: Deserialize<Vec<u8>, E> {}

impl<E> MyDeserialize<E> for Deserialize<Vec<u8>, E> {
  // default implementations here
}

This would be error in Rust 2021 and not what the asker wants anyway, since it's equivalent to impl<E> MyDeserialize<E> for dyn Deserialize<Vec<u8>, E>. One might want this instead:

impl<E, T: Deserialize<Vec<u8>, E>> MyDeserialize<E> for T {
  // default implementations here
}
2 Likes

Damnit, I knew it was screwey! Thanks for the correction.

1 Like

Thanks for your help @simonbuchan, @Cerber-Ursi and @SabrinaJewson.

@Cerber-Ursi I noticed you are implementing the trait on a generic type called T, How would I go about the same approach but for a specified struct.

It's just one struct I need to be able to use the MyDeserialize trait.

For example:

impl <Error, PrivKey: Deserialize<Vec<u8>, Error>> MyDeserialize<Error> for PrivKey {
    fn deserialize(data: Vec<u8>, key_chain: DefaultKeyChain, chain_path: ChainPath) -> Result<PrivKey, Error> {
        let derivation = decode_derivation(&data)?;
        let chain_code = data[9..41].to_vec();
        let private_key = Sk::from_bytes(&data[42..74])?;

        Ok(PrivKey {
            derivation,
            extended_key: PrivateKey {
                private_key: private_key,
                chain_code,
            },
        })
    }
}

In this case, you know that PrivKey: Deserialize<Vec<u8>, Error> for some Error, so you simply do impl MyDeserialize<Error> for PrivKey while having this Error in scope.