1 stable release
1.0.0 | Sep 9, 2022 |
---|
#1550 in Data structures
334 downloads per month
22KB
400 lines
serde_single_or_vec
This crate provides the SingleOrVec
Type which allows
parsing either a single type T or a vector of type T using serde.
This is required when a server either returns an array
if there are multiple values or one value if there is only one.
Example
#[derive(Deserialize, Serialize)]
struct Response {
single: SingleOrVec<'static, u8>,
multiple: SingleOrVec<'static, u8>,
}
let json = r#"{
"single": 0,
"multiple": [
0,
1,
2
]
}"#;
let res: Response = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string_pretty(&res).unwrap());
Format
By default the SingleOrVec
Type deserializes its content either
to a single value or an array if it contains multiple values. To change
this behaviour, its possible to define the output format.
#[derive(Deserialize, Serialize)]
struct Response {
single: SingleOrVec<'static, u8>,
multiple: SingleOrVec<'static, u8>,
}
let json = "[0]";
let res: SingleOrVec<'_, u8, PreferSingle> = serde_json::from_str(json).unwrap();
assert_eq!("0", &serde_json::to_string(&res).unwrap());
let res: SingleOrVec<'_, u8, AlwaysVector> = serde_json::from_str(json).unwrap();
assert_eq!("[0]", &serde_json::to_string(&res).unwrap());
Storage Backend
The default Backend is a Vec<T>
and thus always results in an allocation.
An alternativ is to use a Cow<'_, T>
as backend which only requires an allocation
for a single value.
Note that this is only valid when using or serializing this value, deserialisation always allocates due to serde#1852
let json = "[0,1,2]";
let res: SingleOrVec<'_, u8, PreferSingle, Cow<'_, [u8]>> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
Custom Storage Type
Its also possible to implement Custom Storage Backends by using the Storage
Trait.
use arrayvec::ArrayVec;
struct ArrayVecStorage {}
impl<T> Storage<'_, T> for ArrayVecStorage {
type Backing = ArrayVec<[T; 4]>;
fn single(ty: T) -> Self::Backing {
let mut vec = ArrayVec::new();
vec.push(ty);
vec
}
fn get_first_with_len(b: &Self::Backing) -> Option<(&T, usize)> {
b.split_first().map(|(t, r)| (t, r.len()))
}
}
let json = "[0,1,2]";
let res: SingleOrVec<'_, u8, PreferSingle, ArrayVecStorage> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
let json = "0";
let res: SingleOrVec<'_, u8, PreferSingle, ArrayVecStorage> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
no_std
It is possible to use this crate with no_std
, however, like serde, either std
or
alloc
is required.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
License: MIT OR Apache-2.0
Dependencies
~0.3–1MB
~21K SLoC