Skip to main content

ContainerShape

Struct ContainerShape 

Source
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 (see set_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

Source

pub const fn new() -> ContainerShape

Creates the default shape: unknown length and natural order.

Source

pub const fn with_len(len: usize) -> ContainerShape

Creates a shape with a number of elements (see set_len).

Source

pub const fn with_order(order: Order) -> ContainerShape

Creates a shape with an order (see set_order).

Source

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.

Source

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));
Source

pub const fn set_order(&mut self, order: Order)

Sets the order.

Source

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.

Source

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);
Source

pub const fn order(&self) -> Order

Returns how significant the order of the elements is.

Source

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> or HashSet<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, DuplicateKeys in the State decides 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![],
}));
Source

pub const fn is_multimap(&self) -> bool

Returns true if the keys of the map can be given more than once.

See set_multimap.

Source

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()));
Source

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

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ContainerShape

Source§

impl Debug for ContainerShape

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ContainerShape

Source§

fn default() -> ContainerShape

Returns the “default value” for a type. Read more
Source§

impl Eq for ContainerShape

Source§

impl Hash for ContainerShape

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for ContainerShape

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ContainerShape

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.