deserr 0.6.4

Deserialization library with focus on error handling
Documentation
# Field attributes

### `#[deserr(rename = "...")]`

Deserialize this field with the given name instead of its Rust name.

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    query: String,
    #[deserr(rename = "atr")]
    attributes_to_retrieve: Vec<String>,
}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "atr": ["age", "name"] }),
)
.unwrap();
assert_eq!(data, Search {
    query: String::from("doggo"),
    attributes_to_retrieve: vec![String::from("age"), String::from("name")],
});
```

[Also available as a variant attribute.](variant.md#deserrrename)

### `#[deserr(from)]`

Deserializing a type from a function instead of a `Value`.
You need to provide the following information;
1. The input type of the function (here `&String`)
2. The path of the function (here, we're simply using the std `FromStr` implementation)

deserr will first try to deserialize the given type using its `Deserr<E>` implementation.
That means the input type of the `from` can be complex. Then deserr will call your
function.

- [If your function can fail, consider using `try_from` instead]#deserrtryfrom
- [The container attribute may interests you as well]container.md#deserrfrom

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
#[deserr(from(String) = From::from)]
enum Wildcard {
    Wildcard,
    Value(String),
}

impl From<String> for Wildcard {
    fn from(s: String) -> Self {
        if s == "*" {
            Wildcard::Wildcard
        } else {
            Wildcard::Value(s)
        }
    }
}

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    query: String,
    #[deserr(from(String) = From::from)]
    field: Wildcard,
}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "field": "catto" }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), field: Wildcard::Value(String::from("catto")) });

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "field": "*" }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), field: Wildcard::Wildcard });
```

### `#[deserr(try_from)]`

Try deserializing a type from a function instead of a `Value`.
You need to provide the following information;
1. The input type of the function (here `&String`)
2. The path of the function (here, we're simply using the std `FromStr` implementation)
3. The error type that this function can return (here `ParseIntError`)

deserr will first try to deserialize the given type using its `Deserr<E>` implementation.
That means the input type of the `try_from` can be complex. Then deserr will call your
function and accumulate the specified error against the error type of the caller.

- [If your function cannot fail, consider using `from` instead]#deserrfrom
- [The container attribute may interests you as well]container.md#deserrtryfrom

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;
use std::convert::Infallible;
use std::str::FromStr;
use std::num::ParseIntError;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    query: String,
    #[deserr(try_from(&String) = FromStr::from_str -> ParseIntError)]
    limit: usize,

}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "limit": "12" }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), limit: 12 });

let error = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "limit": 12 }),
)
.unwrap_err();
assert_eq!(error.to_string(), "Invalid value type at `.limit`: expected a string, but found a positive integer: `12`");
```

### `#[deserr(default)]`

Allows you to specify a default value for a field.

Note that, unlike serde, by default, `Option` doesn't automatically use this attribute.
Here you need to explicitly define whether your type can get a default value.
This makes it less error-prone and easier to make an optional field mandatory.

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    #[deserr(default)]
    query: Option<String>,
    #[deserr(default = 20)]
    limit: usize,
}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "limit": 4 }),
)
.unwrap();
assert_eq!(data, Search { query: Some(String::from("doggo")), limit: 4 });

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo" }),
)
.unwrap();
assert_eq!(data, Search { query: Some(String::from("doggo")), limit: 20 });
```

### `#[deserr(skip)]`

Allows you to skip the deserialization of a field.
It won't show up in the list of fields generated by `deny_unknown_fields` or in the
`UnknownKey` variant of the `ErrorKind` type.

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    query: String,
    // A field can be skipped if it implements `Default` or if the `default` attribute is specified.
    #[deserr(skip)]
    hidden: usize,
}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo" }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), hidden: 0 });

// if you try to specify the field, it is ignored
let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "hidden": 2 }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), hidden: 0 });

// Here, we're going to see how skip interacts with `deny_unknown_fields`

#[derive(Deserr, Debug, PartialEq, Eq)]
#[deserr(deny_unknown_fields)]
struct Search2 {
    query: String,
    // A field can be skipped if it implements `Default`.
    #[deserr(skip)]
    hidden: usize,
}

let error = deserialize::<Search2, _, JsonError>(
    json!({ "query": "doggo", "hidden": 1 }),
)
.unwrap_err();
// NOTE: `hidden` isn't in the list of expected fields + `hidden` is effectively considered as a non-existing field.
assert_eq!(error.to_string(), "Unknown field `hidden`: expected one of `query`");
```

### `#[deserr(map)]`

Map a field **after** it has been deserialized.

```rust
use deserr::{Deserr, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    query: String,
    #[deserr(map = add_one)]
    limit: usize,
}

fn add_one(n: usize) -> usize {
    n.saturating_add(1)
}

let data = deserialize::<Search, _, JsonError>(
    json!({ "query": "doggo", "limit": 0 }),
)
.unwrap();
assert_eq!(data, Search { query: String::from("doggo"), limit: 1 });

// Let's see how `map` interacts with the `default` attributes.
#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search2 {
    query: String,
    #[deserr(default, map = add_one)]
    limit: usize,
}

let data = deserialize::<Search2, _, JsonError>(
    json!({ "query": "doggo" }),
)
.unwrap();
// As we can see, the `map` attribute is applied AFTER the `default`.
assert_eq!(data, Search2 { query: String::from("doggo"), limit: 1 });
```

### `#[deserr(missing_field_error)]`

Gives you the opportunity to customize the error message if this specific field
is missing.

```rust
use deserr::{Deserr, DeserializeError, ValuePointerRef, ErrorKind, deserialize, errors::JsonError};
use serde_json::json;
use std::convert::Infallible;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search {
    #[deserr(missing_field_error = missing_query_field)]
    query: String,
    limit: usize,
}

fn missing_query_field<E: DeserializeError>(_field_name: &str, location: ValuePointerRef) -> E {
    deserr::take_cf_content(E::error::<Infallible>(
        None,
        ErrorKind::Unexpected {
            msg: String::from("I really need the query field, please give it to me uwu"),
        },
        location,
    ))
}

let error = deserialize::<Search, _, JsonError>(
    json!({ "limit": 0 }),
)
.unwrap_err();
assert_eq!(error.to_string(), "Invalid value: I really need the query field, please give it to me uwu");
```

### `#[deserr(error)]`

Customize the error type that can be returned when deserializing this structure
instead of keeping it generic.

```rust
use deserr::{Deserr, DeserializeError, ValuePointerRef, ErrorKind, deserialize, errors::JsonError};
use serde_json::json;

// Since the error returned by the `Search` structure needs to implements `MergeWithError<JsonError>`
// we also need to specify the `error` attribute as a `JsonError`. But as you will see later there are
// other solutions.
#[derive(Deserr, Debug, PartialEq, Eq)]
#[deserr(error = JsonError)]
struct Search<A> {
    #[deserr(error = JsonError)]
    query: A,
    limit: usize,
}
```

### `#[deserr(needs_predicate)]`

Automatically adds `where_predicate = FieldType: Deserr<ErrType>` for each field with this attribute.

```rust
use deserr::{Deserr, DeserializeError, MergeWithError, deserialize, errors::JsonError};
use serde_json::json;

#[derive(Deserr, Debug, PartialEq, Eq)]
struct Search<A> {
    #[deserr(needs_predicate)]
    query: A,
    limit: usize,
}
```

Is strictly equivalent to the following:

```rust
use deserr::{Deserr, DeserializeError, MergeWithError, deserialize, errors::JsonError};
use serde_json::json;

// `__Deserr_E` represents the Error returned by the generated `Deserr` implementation.
#[derive(Deserr, Debug, PartialEq, Eq)]
#[deserr(where_predicate = A: Deserr<__Deserr_E>)]
struct Search<A> {
    query: A,
    limit: usize,
}
```