Custom deserialization

Our Color type has to be convertible from a string. We can do this by implementing the FromStr trait, which makes it possible to call the parse method of str to parse the struct from a string:

impl FromStr for Color {
type Err = ColorError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"white" => Ok(WHITE.to_owned()),
"black" => Ok(BLACK.to_owned()),
s if s.starts_with("#") && s.len() == 7 => {
let red = u8::from_str_radix(&s[1..3], 16)?;
let green = u8::from_str_radix(&s[3..5], 16)?;
let blue = u8::from_str_radix(&s[5..7], 16)?;
Ok(Color { red, green, blue })
},
other => {
Err(ColorError::InvalidValue { value: other.to_owned() })
},
}
}
}

In this implementation, we use a match expression with four branches to check the cases. We indicate that the expression should have a textual value of either "white" or "black", or that it can start with a #, and that it should contain exactly seven characters. Otherwise, an error should be returned to indicate that an unsupported format has been provided.

To implement the Deserialization trait, we need to add the ColorVisitor struct, which implements the Visitor trait of the serde crate. The Visitor trait is used to extract a value of a specific type from different input values. For example, we can use the u32 and str input types to deserialize decimal values. The ColorVisitor in the following example tries to parse the incoming strings to a color. It has the following implementation:

struct ColorVisitor;

impl<'de> Visitor<'de> for ColorVisitor {
type Value = Color;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a color value expected")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: de::Error {
value.parse::<Color>().map_err(|err| de::Error::custom(err.to_string()))
}

fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: de::Error {
self.visit_str(value.as_ref())
}
}

As you can see, we use the parse method of str, which works with types that implement the FromStr trait to convert a string to a Color instance. We implemented two methods to extract values from different types of strings  the first for String instances and the second for str references. We can now add the Color type as a field in the other deserializable struct. Let's take a closer look at the ColorError type before we look closer at working with binary data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.241.250