pub struct ContainerShape { /* private fields */ }Expand description
Facts about a map or sequence.
The shape is carried by Event::MapStart and Event::SeqStart. It
holds information that formats can use to encode or decode a container,
all of which can be ignored:
order: how significant the order of the elements is.len: the number of elements (entries for maps) if known. Formats that can only estimate it give a hint instead (seeset_len_hint).is_multimap: the keys of the map can be given more than once.is_ambiguous_empty: the container is empty and could just as well be the other kind of container.
use deser::{ContainerShape, Order};
const SHAPE: ContainerShape =
ContainerShape::with_order(Order::Sorted);
assert_eq!(SHAPE.order(), Order::Sorted);
assert_eq!(SHAPE.len(), None);Implementations§
Source§impl ContainerShape
impl ContainerShape
Sourcepub const fn new() -> ContainerShape
pub const fn new() -> ContainerShape
Creates the default shape: unknown length and natural order.
Sourcepub const fn with_len(len: usize) -> ContainerShape
pub const fn with_len(len: usize) -> ContainerShape
Creates a shape with a number of elements (see
set_len).
Sourcepub const fn with_order(order: Order) -> ContainerShape
pub const fn with_order(order: Order) -> ContainerShape
Creates a shape with an order (see set_order).
Sourcepub const fn set_len(&mut self, len: usize)
pub const fn set_len(&mut self, len: usize)
Sets the number of elements.
Serializers can rely on it, for instance to write the length in front of the elements.
Sourcepub const fn set_len_hint(&mut self, len: usize)
pub const fn set_len_hint(&mut self, len: usize)
Sets an estimate of the number of elements.
The estimate is only used to preallocate containers (see
cautious_capacity), len
remains unknown. A format that cannot know the length of a
container before its end (like the number of records of a CSV file)
can give one so that the container does not grow element by element.
use deser::ContainerShape;
let mut shape = ContainerShape::new();
shape.set_len_hint(10);
assert_eq!(shape.len(), None);
assert_eq!(shape.cautious_capacity::<u64>(), 10);
// the length replaces the estimate once it's known
shape.set_len(3);
assert_eq!(shape.len(), Some(3));Sourcepub const fn len(&self) -> Option<usize>
pub const fn len(&self) -> Option<usize>
Returns the number of elements (entries for maps) if known.
During deserialization the length comes from the input and is not
trusted: a few bytes can declare a container with billions of
elements that are never sent. To preallocate a container use
cautious_capacity instead.
Sourcepub const fn cautious_capacity<T>(&self) -> usize
pub const fn cautious_capacity<T>(&self) -> usize
Returns the number of elements of type T to preallocate.
This is the len of the shape (or its estimate, see
set_len_hint), capped so that no more
than about a megabyte is preallocated, and 0 if the length is
unknown. As the length comes from the input it must not be trusted
for allocations: a container that is larger grows as its elements
arrive instead.
use deser::ContainerShape;
let shape = ContainerShape::with_len(10);
assert_eq!(shape.cautious_capacity::<u64>(), 10);
let shape = ContainerShape::with_len(usize::MAX - 1);
assert_eq!(shape.cautious_capacity::<u64>(), 1024 * 1024 / 8);
assert_eq!(ContainerShape::new().cautious_capacity::<u64>(), 0);Sourcepub const fn set_multimap(&mut self, yes: bool)
pub const fn set_multimap(&mut self, yes: bool)
Marks a map as a multimap: its keys can be given more than once.
Formats where keys can repeat (like query strings with a=1&a=2,
the elements of XML or the columns of CSV files) emit their maps
with this flag and pass on every occurrence of a key as an entry of
its own, in the order of the input. How repeated keys are resolved
is up to the type that receives the map:
- The fields of derived structs and the values of maps whose type is
a collection (like
Vec<T>orHashSet<T>) collect the values of all occurrences of their key. A key that is given once is a collection of one value and a key that is missing is an empty collection. - Other fields and values receive a single value,
DuplicateKeysin theStatedecides which one: the last one, the first one or an error (the default).
Types that do not know about multimaps receive the entries like
those of any other map. See State::is_multimap.
use deser::de::DeserializeDriver;
use deser::{Atom, ContainerShape, Deserialize, Event};
#[derive(Deserialize, Debug, PartialEq)]
struct Query {
tag: Vec<String>,
page: u32,
user: Vec<String>,
}
let mut out = None::<Query>;
let mut driver = DeserializeDriver::new(&mut out);
let mut shape = ContainerShape::new();
shape.set_multimap(true);
driver.emit(Event::MapStart(shape)).unwrap();
for (key, value) in [("tag", "a"), ("page", "1"), ("tag", "b")] {
driver.emit(key).unwrap();
driver.emit(Atom::Lexical(value.into())).unwrap();
}
driver.emit(Event::MapEnd).unwrap();
drop(driver);
assert_eq!(out, Some(Query {
tag: vec!["a".into(), "b".into()],
page: 1,
user: vec![],
}));Sourcepub const fn is_multimap(&self) -> bool
pub const fn is_multimap(&self) -> bool
Returns true if the keys of the map can be given more than once.
See set_multimap.
Sourcepub const fn set_ambiguous_empty(&mut self, yes: bool)
pub const fn set_ambiguous_empty(&mut self, yes: bool)
Marks an empty container as one that could also be the other kind.
Some formats cannot tell an empty sequence from an empty map: PHP
has a single array type for lists and maps, so the empty array is
both (and so is [] in JSON written by PHP). Formats like this
emit their best guess with this flag. If the value it’s delivered
to rejects the container, the value receives an empty container of
the other kind instead: an empty sequence becomes an empty map for
a struct or a map, an empty map an empty sequence for a Vec.
Values that accept the container (like dynamic values) receive it as
it is. If the other kind is rejected too, the error is the one of
the container that was emitted.
The flag only has an effect if the length is 0, so
formats have to know that the container is empty when they emit its
start. It’s only tried after a value rejected the container, so it
costs nothing otherwise. Serializers ignore it.
use std::collections::BTreeMap;
use deser::de::DeserializeDriver;
use deser::{ContainerShape, Event};
let mut shape = ContainerShape::with_len(0);
shape.set_ambiguous_empty(true);
let mut out = None::<BTreeMap<String, u32>>;
let mut driver = DeserializeDriver::new(&mut out);
driver.emit(Event::SeqStart(shape)).unwrap();
driver.emit(Event::SeqEnd).unwrap();
drop(driver);
assert_eq!(out, Some(BTreeMap::new()));Sourcepub const fn is_ambiguous_empty(&self) -> bool
pub const fn is_ambiguous_empty(&self) -> bool
Returns true if the container is empty and could also be the
other kind of container.
This requires the length to be 0. See
set_ambiguous_empty.
Trait Implementations§
Source§impl Clone for ContainerShape
impl Clone for ContainerShape
impl Copy for ContainerShape
Source§impl Debug for ContainerShape
impl Debug for ContainerShape
Source§impl Default for ContainerShape
impl Default for ContainerShape
Source§fn default() -> ContainerShape
fn default() -> ContainerShape
impl Eq for ContainerShape
Source§impl Hash for ContainerShape
impl Hash for ContainerShape
Source§impl PartialEq for ContainerShape
impl PartialEq for ContainerShape
impl StructuralPartialEq for ContainerShape
Auto Trait Implementations§
impl Freeze for ContainerShape
impl RefUnwindSafe for ContainerShape
impl Send for ContainerShape
impl Sync for ContainerShape
impl Unpin for ContainerShape
impl UnsafeUnpin for ContainerShape
impl UnwindSafe for ContainerShape
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.