Search code examples
rustdeserializationtoml

Deserialize String to MacAddr6 in toml file


I have a toml file with pairs id and mac like this:

[[component]]
id = 1
mac = "d4:d7:04:c9:85:a4"
[[component]]
id = 3
mac = "3c:21:ee:b4:0d:ab"
[[component]]
id = 6
mac = "ea:f3:23:8c:b8:c1"

The goal is to deserialize this file to a Vec of this struct (MacAddr6 belongs to the macaddr crate:

#[derive(Deserialize, Debug)]
pub struct Component {
    pub id: u16,
    pub mac: MacAddr6,
}

When I try to deserialize, this error is shown:

inner: TomlError { message: "invalid type: string "d4:d7:04:c9:85:a4", expected an array of length 6"

If I change MacAddr6 to String in the struct definition and everything worked fine, so I have a workaround. Nevertheless, since MacAddr6 implements serde::Deserialize and core::str::FromStr I was expecting to retrieve the full struct in one time. What am I doing wrong?


Solution

  • What am I doing wrong?

    Assuming things for no reason? MacAddr6 derives Deserializable and is defined like this:

    pub struct MacAddr6([u8; 6]);
    

    In most serialization schemes, that means it's going to be encoded to and decoded from a 6-wide array of integers. Not a string.

    FromStr does not enter the equation either, serde has no support for it, and even if it did you'd need to tell serde to use it, especially since MacAddr6 has a Deserialize (so there would be no way for serde to provide a default implementation even if it were possible).

    What you can do is either hand-roll this conversion via a custom deserialization function (and the deserialize_with attribute) or use the relevant helper from serde_with.