Skip to main content

Snapshot

Struct Snapshot 

Source
pub struct Snapshot { /* private fields */ }
Expand description

What one request may read: one Arc per section, taken together.

Built by Sections::take when the request begins, and read by an adapter’s extractor. Two reads of the same section answer the same Arc, however far apart in the handler they are and whatever lands in between.

Implementations§

Source§

impl Snapshot

Source

pub fn get<T: Any + Send + Sync>(&self) -> Option<Arc<T>>

The section of type T this request began with.

None when T was not among the sections, or was among them and had not loaded yet. require tells those apart.

Source

pub fn require<T: Any + Send + Sync>(&self) -> Result<Arc<T>, NotInScope>

The section of type T, or why it is not here.

§Errors

NotInScope::NotListed when T was never registered — a wiring mistake, fixed where the layer is built. NotInScope::NotLoaded when it was registered and nothing has installed a value yet — a startup-order mistake, fixed by loading before serving. The two have different fixes, which is why they are different variants.

Examples found in repository?
examples/core_snapshot.rs (line 74)
62fn main() {
63    let sections = Sections::new()
64        .section(|| Some(state().lock().expect("not poisoned").0.clone()))
65        .section(|| Some(state().lock().expect("not poisoned").1.clone()));
66
67    println!("sections: {:?}\n", sections.names());
68
69    // One `take()` is one reading of every section. Everything read
70    // *through the snapshot* afterwards is from that instant — a reload
71    // in between cannot tear it.
72    let snapshot = sections.take();
73
74    let server = snapshot.require::<Server>().expect("in scope");
75
76    reload(2); // ← a deployment lands mid-request
77
78    let features = snapshot.require::<Features>().expect("in scope");
79
80    println!("through one snapshot, across a reload:");
81    println!(
82        "  server   = port {}, generation {}",
83        server.port, server.generation
84    );
85    println!(
86        "  features = cache {}, generation {} (same instant)\n",
87        features.cache, features.generation
88    );
89    assert_eq!(server.generation, features.generation);
90
91    // The next request's snapshot sees the new state — this is
92    // per-request pinning, not staleness.
93    let next = sections.take();
94
95    println!("the next snapshot:");
96    println!(
97        "  features = {:?}\n",
98        next.require::<Features>().expect("in scope")
99    );
100
101    // And the error half: a type nobody declared answers by name.
102    let missing = snapshot.require::<String>().unwrap_err();
103
104    println!("asking for an undeclared section:\n  {missing}");
105}
Source

pub fn len(&self) -> usize

How many sections this request may read.

Source

pub fn is_empty(&self) -> bool

Whether it carries nothing at all.

Source

pub fn names(&self) -> Vec<&'static str>

The type names registered, whether or not each had loaded.

Source

pub fn merged_with(self, inner: Self) -> Self

This snapshot with inner’s sections laid over it.

What an adapter uses when layers nest and each carries its own list. The inner one wins where both registered a type, because it is the more specific of the two — and nothing is lost, which is the point: a handler under both layers can read either’s sections.

Trait Implementations§

Source§

impl Clone for Snapshot

Source§

fn clone(&self) -> Snapshot

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 Debug for Snapshot

Source§

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

The section names, never their contents.

A configuration section holds credentials, and {:?} on a request is the kind of thing that reaches a log line.

Source§

impl Default for Snapshot

Source§

fn default() -> Snapshot

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

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<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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.