extern crate serde as serdelib;
extern crate unicase as unicase_lib;
#[cfg(test)]
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate serde_test;
pub mod unicase {
use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use unicase_lib::UniCase;
use serdelib::{Serializer, Deserializer};
use serdelib::de;
pub fn serialize<S, Ser>(value: &UniCase<S>, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where
S: AsRef<str>,
Ser: Serializer,
{
serializer.serialize_str(value.as_ref())
}
pub fn deserialize<'de, S, D>(deserializer: D) -> Result<UniCase<S>, D::Error>
where
S: FromStr + AsRef<str>,
D: Deserializer<'de>,
{
struct UniCaseVisitor<S>(PhantomData<S>);
impl<'de, S: FromStr + AsRef<str>> de::Visitor<'de> for UniCaseVisitor<S> {
type Value = UniCase<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
FromStr::from_str(s).map_err(|_| E::custom("FromStr conversion failed"))
}
}
deserializer.deserialize_str(UniCaseVisitor(PhantomData))
}
pub mod borrowed {
use super::*;
pub use super::serialize;
pub fn deserialize<'de, S, D>(deserializer: D) -> Result<UniCase<S>, D::Error>
where
S: From<&'de str> + AsRef<str> + 'de,
D: Deserializer<'de>,
{
struct UniCaseVisitor<S>(PhantomData<S>);
impl<'de, S: From<&'de str> + AsRef<str>> de::Visitor<'de> for UniCaseVisitor<S> {
type Value = UniCase<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(UniCase::unicode(s.into()))
}
}
deserializer.deserialize_str(UniCaseVisitor(PhantomData))
}
}
}
pub mod ascii {
use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use unicase_lib::Ascii;
use serdelib::{Serializer, Deserializer};
use serdelib::de;
pub fn serialize<S, Ser>(value: &Ascii<S>, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where
S: AsRef<str>,
Ser: Serializer,
{
serializer.serialize_str(value.as_ref())
}
pub fn deserialize<'de, S, D>(deserializer: D) -> Result<Ascii<S>, D::Error>
where
S: FromStr + AsRef<str>,
D: Deserializer<'de>,
{
struct AsciiVisitor<S>(PhantomData<S>);
impl<'de, S: FromStr + AsRef<str>> de::Visitor<'de> for AsciiVisitor<S> {
type Value = Ascii<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
FromStr::from_str(s).map_err(|_| E::custom("FromStr conversion failed"))
}
}
deserializer.deserialize_str(AsciiVisitor(PhantomData))
}
pub mod borrowed {
use super::*;
pub use super::serialize;
pub fn deserialize<'de, S, D>(deserializer: D) -> Result<Ascii<S>, D::Error>
where
S: From<&'de str> + AsRef<str> + 'de,
D: Deserializer<'de>,
{
struct AsciiVisitor<S>(PhantomData<S>);
impl<'de, S: From<&'de str> + AsRef<str>> de::Visitor<'de> for AsciiVisitor<S> {
type Value = Ascii<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Ascii::new(s.into()))
}
}
deserializer.deserialize_str(AsciiVisitor(PhantomData))
}
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use serde_test::{Token, assert_tokens};
use unicase_lib::{UniCase, Ascii};
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
struct TestUniCase<'a> {
#[serde(with = "::unicase")]
owned: UniCase<String>,
#[serde(borrow, with = "::unicase::borrowed")]
borrowed_str: UniCase<&'a str>,
#[serde(borrow, with = "::unicase::borrowed")]
cow_str: UniCase<Cow<'a, str>>,
}
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
struct TestAscii<'a> {
#[serde(with = "::ascii")]
owned: Ascii<String>,
#[serde(borrow, with = "::ascii::borrowed")]
borrowed_str: Ascii<&'a str>,
#[serde(borrow, with = "::ascii::borrowed")]
cow_str: Ascii<Cow<'a, str>>,
}
#[test]
fn test_unicase_serde() {
let test = TestUniCase {
owned: UniCase::unicode("owned string".to_string()),
borrowed_str: UniCase::unicode("borrowed str"),
cow_str: UniCase::unicode(Cow::from("Cow str")),
};
assert_tokens(
&test,
&[
Token::Struct {
name: "TestUniCase",
len: 3,
},
Token::Str("owned"),
Token::String("owned string"),
Token::Str("borrowed_str"),
Token::BorrowedStr("borrowed str"),
Token::Str("cow_str"),
Token::BorrowedStr("Cow str"),
Token::StructEnd,
],
);
}
#[test]
fn test_ascii_serde() {
let test = TestAscii {
owned: Ascii::new("owned string".to_string()),
borrowed_str: Ascii::new("borrowed str"),
cow_str: Ascii::new(Cow::from("Cow str")),
};
assert_tokens(
&test,
&[
Token::Struct {
name: "TestAscii",
len: 3,
},
Token::Str("owned"),
Token::String("owned string"),
Token::Str("borrowed_str"),
Token::BorrowedStr("borrowed str"),
Token::Str("cow_str"),
Token::BorrowedStr("Cow str"),
Token::StructEnd,
],
);
}
use std::str::FromStr;
#[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::borrowed")]
test_str: UniCase<CustomStr<'a>>,
#[serde(borrow, with = "::unicase::borrowed")]
test_string: UniCase<CustomString<'a>>,
#[serde(borrow, with = "::unicase::borrowed")]
test_str_borrowed: UniCase<CustomStr<'a>>,
#[serde(borrow, with = "::unicase::borrowed")]
test_string_borrowed: UniCase<CustomString<'a>>,
}
}