Crate unicase_serde

Source
Expand description

Build Status Crates.io Repository Documentation

serde Serialization and Deserialization for UniCase crate

Support for serialization and deserialization using serde.

§Installation

Add the following to Cargo.toml:

serde = "1.0"
serde_derive = "1.0"
unicase="2.0"
unicase_serde = "0.1.0"

§Usage

You will have to use the serde with field attribute to annotate any UniCase or Ascii fields with the appropriate module. See examples below.

§Serialization

Serialization for any UniCase<S> and Ascii<S> where S: AsRef<str> is implemented. Examples for S include &str, Cow<'a, str>, and String.

The same Serialize implementation is provided in all the modules.

§Deserialization

You can deserialize strings into UniCase<S> and Ascii<S> where

  • S: FromStr + AsRef<str>
  • S: From<&'de str> + AsRef<str> + 'de

§S: FromStr + AsRef<str>

The Deserialize implementation is provided in the unicase_serde::unicase and unicase_serde::ascii modules. Conversion is done using the FromStr::from_str function.

Typically, you will use the this implementation for any Rust built in type that owns the data and does not borrow anything. Example include String.

You will know when you need to use the second case when you get trait bound errors such “as the trait bound &'a str: std::convert::From<&str> is not satisfied”.

§S: From<&'de str> + AsRef<str> + 'de

The Deserialize implementation is provided in the unicase_serde::unicase::borrowed and unicase_serde::ascii::borrowed modules.

The second case is meant for usage with Rust built in types that borrow data. Conversion is done using the Into::into function.

If you use the second case with any type that owns data, you will get an error at runtime.

§Example Serialization and Deserialization

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate unicase;
extern crate unicase_serde;

use std::borrow::Cow;
use unicase::{UniCase, Ascii};

#[derive(Serialize, Deserialize)]
struct TestUniCase<'a> {
    #[serde(with = "unicase_serde::unicase")]
    owned: UniCase<String>,
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    borrowed_str: UniCase<&'a str>,
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    cow_str: UniCase<Cow<'a, str>>,
}

#[derive(Serialize, Deserialize)]
struct TestAscii<'a> {
    #[serde(with = "unicase_serde::ascii")]
    owned: Ascii<String>,
    #[serde(borrow, with = "unicase_serde::ascii::borrowed")]
    borrowed_str: Ascii<&'a str>,
    #[serde(borrow, with = "unicase_serde::ascii::borrowed")]
    cow_str: Ascii<Cow<'a, str>>,
}

§Example with Custom “string” types

This example will demonstrate how you can use a “custom” string type and still use serialization and deserialization when wrapped inside a UniCase or Ascii. This is particularly useful for types like UniCase<Cow<'a, String>> or UniCase<&'a String> because &String does not implement From::<&str>.

As you can see from the example below, you can use the direct Deserialize implementation to deserialize borrowed data. This usually does not work with Rust built in types due to missing trait implementation. However, because the conversion is done using the FromStr::from_str function, and the function signature indicates that the &str passed in might have an ephemeral lifetime, implementors will have to convert the &str into an owned version. So you are better off using the borrowed deserializer.

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate unicase;
extern crate unicase_serde;

use std::borrow::Cow;
use std::str::FromStr;
use unicase::UniCase;

#[derive(Eq, PartialEq, Debug)]
struct CustomStr<'a>(Cow<'a, str>);

impl<'a> AsRef<str> for CustomStr<'a> {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

impl<'a> FromStr for CustomStr<'a> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(CustomStr(Cow::from(s.to_string())))
    }
}

impl<'a> From<&'a str> for CustomStr<'a> {
    fn from(s: &'a str) -> Self {
        CustomStr(Cow::from(s))
    }
}

#[derive(Eq, PartialEq, Debug)]
struct CustomString<'a>(Cow<'a, String>);

impl<'a> AsRef<str> for CustomString<'a> {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

impl<'a> FromStr for CustomString<'a> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(CustomString(Cow::Owned(s.to_string())))
    }
}

impl<'a> From<&'a str> for CustomString<'a> {
    fn from(s: &'a str) -> Self {
        CustomString(Cow::Owned(s.to_string()))
    }
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
struct TestCustomStruct<'a> {
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    test_str: UniCase<CustomStr<'a>>,
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    test_string: UniCase<CustomString<'a>>,
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    test_str_borrowed: UniCase<CustomStr<'a>>,
    #[serde(borrow, with = "unicase_serde::unicase::borrowed")]
    test_string_borrowed: UniCase<CustomString<'a>>,
}

Modules§

  • Serialization and Deserialization Implementation for Ascii that owns data
  • Serialization and Deserialization Implementation for UniCase that owns data