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

How to handle Vec<Vec<u8>> #29

Open
ghost opened this issue May 14, 2022 · 1 comment
Open

How to handle Vec<Vec<u8>> #29

ghost opened this issue May 14, 2022 · 1 comment

Comments

@ghost
Copy link

ghost commented May 14, 2022

Hi,
i have a message to send in the form of:

type PubKey = Vec<u8>;

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag="kind")]
pub enum Envelope<T> {
    Greeting {
        #[serde(with="serde_bytes")]
        id: PubKey,
        #[serde(with="serde_bytes")]
        shared: PubKey,
        thin: bool
    },
    AllKnown { 
        all_known: Vec<PubKey>
    },
}

As you can see, PubKey is only a Vec<u8>, what is the most idiomatic way to pack this. I do not want to put the Vec<u8> in a struct to use serde_bytes.
Is there something i am missing?
It would be really neat to annotated all_known just with #[serde(with="serde_bytes")].
It seems a pretty common problem to be to have an array of byte arrays.

@jonasbb
Copy link

jonasbb commented May 15, 2022

serde_bytes only supports a few types and cannot support arbitrary data structures. You can use the serde_with::Bytes type, which is more powerful than what serde_bytes offers and can be used with more collections. The crate documentation shows how you can use it in nested situations.

#[serde_with::serde_as]
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag="kind")]
pub enum Envelope<T> {
    AllKnown { 
        #[serde_as(as = "Vec<serde_with::Bytes>")]
        all_known: Vec<PubKey>
    },
}

If you want to use serde_bytes, you will either need to write the deserialization logic for Vec<PubKey> yourself, for example by deserializing into a Vec<ByteBuf> and turning that into a Vec<PubKey>, or aliasing PubKey to ByteBuf, which already has the serialization behavior you want.
Something like this should work:

pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<PubKey>, D::Error>
where
	D: Deserializer,
{
	let tmp: Vec<serde_bytes::ByteBuf> = Vec::deserialize(deserializer)?;
    Ok(tmp.into_iter().map(|x| x.into_vec()).collect())
}

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

No branches or pull requests

1 participant