Giter Site home page Giter Site logo

lawliet89 / unicase_serde Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 0.0 555 KB

serde Serialization and Deserialization for UniCase crate

Home Page: https://lawliet89.github.io/unicase_serde

License: Apache License 2.0

Rust 100.00%
rust serde deserialization serialization serde-serialization unicase-serde unicase

unicase_serde's Introduction

unicase_serde

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>>,
}

# fn main() {
# }

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>>,
}

unicase_serde's People

Contributors

lawliet89 avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

unicase_serde's Issues

Inquiry: does this make deserializing HashMap<Unicase, ...> possible?

(note: I'm new to Rust)

I think this is related to serde-rs/serde#723 which seems to not be resolved yet.

I have a JSON response I want to deserialize, but I want the keys of a particular hashmap to be case-insensitive.

The following throws an error (mismatched types, expected vec etc), and I think I understand why:

    #[serde(default, with = "unicase_serde::unicase")]
    results: Vec<HashMap<UniCase<String>, Option<String>>>

I don't think I can use that "with" line unless the following type is a straight-up UniCase, which it is not, though it contains one.

Is what I'm attempting possible right now? My fallback is to do some slow upper/lower casing over the whole structure after the initial deserialization to String. Not ideal, but I'll survive.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.