Skip to main content

Store

Struct Store 

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

The store instance — the public facade above the tier engines (ADR-011 §1’s vocabulary: one running instantiation of the store facade — one engine set per the constructor mode, plus dispatch and GC state; the GC arbitration domain for single-instance topologies).

Engine-blind by construction: the engines are held in crate-internal enums dispatched statically (see the module’s engine-representation design point); consumers name modes only. The GC state home (GcHome, crate-internal) rides as a field — the store instance owns all GC state (ADR-010 §2), which the gc-protocol task fills.

Implementations§

Source§

impl Store

Source

pub fn mem_only() -> Store

mem-only mode (ADR-011 §4): the mem engine alone, no dispatch threshold in effect — a testing/embedder-ephemeral posture, never production. Every length routes to the (sole) mem engine; there is no large tier and nothing to reject.

Source

pub fn kv_only_mem(threshold: u64) -> Store

kv-only mode (ADR-011 §4; ADR-012 §6.2) with the mem kv engine: no large tier; threshold is the put-time rejection point — known-length puts over it reject immediately, unknown-length puts at mid-stream threshold overflow (the put seam’s behavior; zero residue on either rejection). Routing in this mode is kv for every length.

Source

pub async fn dual_tier_mem_local( root: impl Into<PathBuf>, threshold: u64, ) -> Result<Store, Error>

dual-tier mode (the default, ADR-011 §4) in the wave-2 constructible shape — kv = mem + large = local, the dispatch-coverage test shape ADR-012 §6.3 names: both tiers load-bearing, routed by size-threshold dispatch at threshold (constructor-tunable; crate::dispatch::DEFAULT_DISPATCH_THRESHOLD is the shipped default).

Constructing the large engine creates the root directory — fallible I/O, hence a fallible constructor. The mem kv engine cannot fail.

Not fleet-anything: mem is never fleet-valid (ADR-011 §4).

Source

pub async fn kv_only_sqlite( database: impl Into<PathBuf>, threshold: u64, window_delay: Duration, ) -> Result<Store, Error>

kv-only mode (ADR-011 §4; ADR-012 §6.2) with the sqlite kv engine — the durable single-node kv-only shape: no large tier; threshold is the put-time rejection point (known-length puts over it reject immediately, unknown-length puts at mid-stream threshold overflow — the put seam’s behavior, identical to the mem kv-only wiring; zero residue on either rejection). Routing in this mode is kv for every length.

Opening (or creating) the database file is fallible I/O; the constructor also runs the GC schema’s engine-neutral call (ensure_gc_schema — sqlite’s body creates gc_window only, ADR-012 §5), so a construction failure is Err(Error::Io) per the fallible-constructor pattern dual_tier_mem_local set.

window_delay (ADR-008 §2) is the durable window’s cadence knob — DEFAULT_DELETE_WINDOW_DELAY is the shipped default, Duration::ZERO the legal degenerate tuning. Not fleet- anything: a sqlite fleet is a recorded non-option (ADR-010 §3).

Source

pub async fn dual_tier_sqlite_local( database: impl Into<PathBuf>, root: impl Into<PathBuf>, threshold: u64, window_delay: Duration, ) -> Result<Store, Error>

dual-tier mode (the default, ADR-011 §4) in the default-build production shape — kv = sqlite + large = local (feature sqlite is default-on, ADR-013 §4): size-threshold dispatch at threshold (constructor-tunable; crate::dispatch::DEFAULT_DISPATCH_THRESHOLD is the shipped default), at-or-below on the kv tier, over-threshold staged into the large tier.

Fallible on two accounts (file I/O): opening/creating the pool database — which also runs the GC schema’s engine-neutral call (ensure_gc_schema; sqlite’s body creates gc_window only, ADR-012 §5’s one-window-host rule: the durable window is the kv engine’s when the kv engine is SQL-backed) — and creating the local root. A construction failure is Err(Error::Io) per the fallible-constructor pattern dual_tier_mem_local set.

window_delay (ADR-008 §2) is the durable window’s cadence knob — DEFAULT_DELETE_WINDOW_DELAY is the shipped default, Duration::ZERO the legal degenerate tuning. Not fleet- anything: a sqlite fleet is a recorded non-option (ADR-010 §3).

Source

pub fn mode(&self) -> StoreMode

The constructor mode (ADR-011 §4’s vocabulary) — introspection for embedders and tests; the dispatch/put/read paths branch on it crate-internally.

Source§

impl Store

The write path (store-api.md §Write path): put_as — the two internal paths behind one signature, the Batch batching seam, and the kv-only rejection point (ADR-012 §6.2), on the pin-before-publish ordering (ADR-005). The named design points (stream shape, len mismatch, kv-only carrier, key-at-commit amendment) are recorded in the module doc; their behaviors are pinned by the tests below.

Source

pub async fn put_as( &self, algorithm: Algorithm, len: Option<u64>, stream: impl AsyncRead + Unpin + Send, ) -> Result<(Key, Pin), Error>

put_as(algorithm, len, stream) → (Key, Pin) — the one derivation-explicit put seam (store-api.md §Write path; ADR-020 §Decision 5): the caller names the derivation. The same bytes have multiple equally valid addresses, one per registry member, so the crate never picks a derivation for its caller — the caller that cannot name an algorithm cannot form an address (the ADR-020 §Decision 1 invariant). Every registered algorithm writes through this one signature: no matches! restriction, no canonical default, no family-named sibling method. Two arms behind one signature:

Known-length (Some(len)) — the encouraged path (covers git objects, stat-derived files, Content-Length-bearing uploads, network offers): one pass, no staging needed for hashing — the preamble ("blob <len>\0") initializes the derivation before content flows. Preamble-carrying members (the blob family) hash preamble-then-content; identity-family members (Algorithm::GitObjectSha1/Algorithm::GitObjectSha256, ADR-018) take the preimage verbatim — git’s loose-object form, the caller provides "<type> <len>\0" + content — with len as the stored-length check; the derivation is the plain hash over the preimage, so the resulting key’s digest is the object’s git oid, byte-identical, every kind included. Verification-on-get re-derives with the key’s algorithm byte-identically. ≤ the threshold → the kv tier’s whole-value put; > the threshold → the large tier’s staged put (content streams into the staging cursor while hashing; the derivation completes at stream end; commit-rename publishes). A stream that yields fewer or more bytes than the declared len rejects with Error::Verification — zero residue either side (the module doc’s named design point).

Unknown-length (None) — retained on the facade (ADR-020 §Decision 3: “stream in, get the key back” is a legitimate in-process posture for edge producers, and the hard part is the crash-safe staging hygiene every outer-layer workaround re-implements): content buffers in memory up to the dispatch threshold, ADR-003’s option (d) semantics pinned in the three numbered rules:

  1. Mid-stream threshold overflow (non-restartable sources are normal): the buffered prefix flushes into a fresh stage file and the stream continues appending into it — there is no “restart the stream” requirement anywhere.
  2. Verification runs over the eventual stored artifact as a whole: the memory buffer for the sub-threshold kv commit; the complete staged bytes for the large commit — the derivation pass restarts over preamble + staged bytes for preamble-carrying members (the preamble is inside the hashed input, ADR-002); identity-family members restart over the staged bytes — the permitted simple implementation, single-pass capable if ever measured worth it. Reading the staged artifact back goes through the staging cursor’s ReadCursor seam.
  3. Stream error before commit: no entry lands and no stage file remains — buffer discard on the failure path, exactly like stage discard (the stage-hygiene invariant extended to the buffered case).

Error mapping is uniform across both arms and all algorithms: length mismatch Error::Verification (zero residue), media failure Error::Io.

Pin-before-publish (ADR-005): the pin refcount is minted under the arbitration lock before the entry becomes visible — an entry cannot appear in a sweep’s list() without already carrying its pin. A dedup re-put acquires no new pool entry; the returned Pin refcounts the existing one under the same lock.

kv-only mode (ADR-012 §6.2): a known-length put over the threshold rejects immediately; an unknown-length put rejects at mid-stream threshold overflow — lengths are not known at construction, so put time is the only possible rejection point. Zero residue on either rejection.

Fleet puts (ADR-012 §3/§4; ADR-018 §Decision 7): under a fleet: true declaration the same signature routes the fleet forms — the kv tier through the joint entry+pin tx (the joint-tx driver’s named design points, the termination design included, are recorded on this module’s fleet impl block), the pg-lo tier through the one-tx consolidation form, the local tier pin-first/publish-second; the named derivation threads through them (derivation-parameterized sites, not family-branching copies), and the returned guard carries the pin row’s TTL/3 renewal duty. Under fleet: false (every pre-existing constructor) this doc applies verbatim and nothing of the fleet machinery runs.

stat semantic (ADR-018 §Decision 3): for a family entry, stat’s EntryMeta.len is the length of the stored value — the loose-object form, git’s header included — not the content length. Deliberate and per-family; see store-api.md §Read path.

Source

pub fn batch(&self) -> Batch

The batch-scoped pin group (store-api.md §Write path; ADR-005 §Marks 2). Multi-put writes — manifest writes are exactly this — group under one batch-scoped pin: Store::put_in_batch runs each member’s lone-put flow and contributes its pin to the group; the group’s pins drop together on Batch::commit or drop (no early single-pin release; member liveness never outlives the batch — batch drop is the failure path).

Source

pub async fn put_in_batch( &self, batch: &mut Batch, algorithm: Algorithm, len: Option<u64>, stream: impl AsyncRead + Unpin + Send, ) -> Result<Key, Error>

A member put inside a Batch — the batching put seam (store-api.md §Write path). Member puts publish pin-before- publish exactly as lone puts do: the two paths behind Store::put_as’s one signature run, and the minted guard is contributed to the group instead of returned; the algorithm is named like every other write (ADR-020 §Decision 5). The batch’s pins drop together on Batch::commit or batch drop.

Foreign-Batch refusal (review-001 N-5): the batch must have been minted by this store — the seam opens with a debug_assert!(Arc::ptr_eq) on the batch’s registry Arc against the store’s, before any pin is minted. The debug-assert point is the recorded choice over a named error: the mis-use is developer-error territory, and the error family is ADR-pinned (ADR-012 §6.5 — new variants are new ADRs). Release builds run on: a foreign batch’s members would carry their pins in the other store’s in-process registry, where the group release is a silently no-op — the leak the assert’s window exists to catch.

Source§

impl Store

The read path (store-api.md §Read path): get, stat, read_range, has, list — every key-addressed op falling through kv first, then large (ADR-012 §6.1’s general rule), typed key conversion at the facade boundary, and the module-doc design points (the Blob stream shape, verification-on-get, the Vec<Key> list shape) carried in their implementations.

Source

pub async fn get(&self, key: &[u8]) -> Result<Option<(u64, Blob)>, Error>

get(key) → Option<(len, stream)>. Falls through kv → large; a both-tier miss is Ok(None) — never Error::Missing (ADR-012 §6.5 ruling 5). On a kv hit the materialized read is whole-blob-verified against the key at get time (mismatch: Err(Error::Verification), never a further fall-through) and the returned length is the verified materialized byte length; the large tier’s hit opens streaming (metadata + handle, no canonical re-derivation — see the module doc), its length the cursor’s metadata-only probe. Both hits return the same (len, stream) shape: the stream is Blob over the tier’s cursor body.

Source

pub async fn stat(&self, key: &[u8]) -> Result<Option<EntryMeta>, Error>

stat(key) → Option<EntryMeta> — the cheap probe riding the trait’s size method (ADR-008): length plus the key’s hash algorithm, never a content load, falling through kv → large. A both-tier miss is Ok(None).

Source

pub async fn read_range( &self, key: &[u8], offset: u64, len: u64, ) -> Result<(Vec<u8>, [u8; 32]), Error>

read_range(key, offset, len) → (slice, slice_digest) — the slice plus the out-of-band SHA-256 slice digest (ADR-006, fixed by convention), composed through the cursor’s read_range seam. Falls through kv → large exactly as Store::get does; no canonical verification rides a range (the slice digest is the whole answer, ADR-006 decision 2). A both-tier miss is Err(Error::Missing) — the pinned shape difference vs get’s None (ADR-012 §6.5 ruling 5).

Source

pub async fn has(&self, key: &[u8]) -> Result<bool, Error>

has(key) → bool — the pure existence probe (ADR-008’s has discipline: an existence probe per tier, local’s body being the literal size-probe), falling through kv → large. Absent on both tiers: false. Virgin-store reads are no-ops.

Source

pub async fn list(&self) -> Result<Vec<Key>, Error>

list() → Vec<Key> — whole-pool enumeration of every tier, complete by contract (ADR-003), returned materialized and sorted in the keys’ total order (the recorded Vec-vs-stream design point; see the module doc). Malformed pool bytes are fatal: Err(Error::KeyInvalid), never a silent skip.

Degenerate duplicates are not deduped on the public form: a key resident in both tiers (reachable only through the staged shapes that write a second home directly) lists once per home — the sweep’s mark side dedups its candidate set, the public enumeration simply reflects each engine’s contents.

Source§

impl Store

The GC protocol’s facade surface (ADR-005; gc-and-namespaces.md; store-api.md §Lifecycle, §Invariants 4/5): the liveness registration verbs, the direct delete with its arbitration-then- delete refusal, and the sweep() delete-window protocol. This is the architecture’s most intricate state machine in its single-node form — the fleet extension (DB-backed pins, sweep lease, SQL arbitration) extends it without changing its invariants.

The state machine, one instance at a time. All shared GC state rides the crate-internal GcHome behind the crate-internal Store::gc accessor: one arbitration lock over per-key pin refcounts, in-flight delete markers, and the registered source lists (crate::gc’s module doc carries the named design points — the marker mechanism that closes the sweep-vs-put race without engine I/O under the lock, and the single-node sweep lease).

Abort-as-data (ADR-012 §1): every sweep returns Ok(SweepReport); aborts are GcAbortCause values in the report, never errors. Error::GcRefuse is the direct-delete refusal alone, decided here at the facade — it never fires below the facade (the error module’s altitude discipline). The full protection set (ADR-012 §6.4): pinned, re-observed live via a registered source, or named by a protect callback.

Source

pub fn register_liveness_source( &self, source: LivenessRegistration, ) -> Result<Registration, Error>

Register a LivenessRegistration — the live-shared GC seam (ADR-005 §Marks 1; register_liveness_source verbatim; POC #1 finding 7’s finding is the verb’s pinning reason). ADR-012 §6.6’s fleet-shaped argument: the same verb carries both forms —

  • LivenessRegistration::InProcess — the original form (an Arc<dyn LivenessSource>); consulted live at mark time and at delete-time arbitration, never a snapshot at registration. Legal under every topology; under fleet: true its protection is instance-local only (the allow-and- document posture: the in-process callback view is not a fleet liveness form — ADR-008 §2 — so this instance’s sweeps and direct deletes see it, other instances’ SQL arbitration does not; the embedder’s fleet-wide protection materializes into its liveness table or pin rows before the fleet’s other instances sweep).
  • LivenessRegistration::FleetTable — the fleet form: a named (schema-qualified) table reference registered into the shared engine, read by the delete-time SQL arbitration and never owned by the store (the schema-ownership rule — the engine never creates the table). Malformed references error here; re-registering the same reference is idempotent. Only legal on a fleet store — the verb errors under fleet: false (the fleet machinery is dormant there by declaration, ADR-012 §3).

The verb returns Result<Registration, Error>: the fleet form validates the reference and forwards to the shared engine (both fallible); the in-process form never errors in practice — the pre-fleet signature’s infallibility was the in-process form’s accident, retired by the unified surface (the recorded verb-shape design point). The returned Registration token deregisters via Store::unregister_liveness_source (ADR-012 §6.4’s correction flow). Zero registered liveness registrations — in-process sources and fleet tables counted together — make every sweep abort with GcAbortCause::NoLivenessSources — the safe default.

The protect callback’s fleet posture (recorded here where the liveness verbs live): ProtectCallback is single-node-only (ADR-008 §2) — a fleet sweeper cannot consult another node’s in-process callback. A registered callback remains consultable by this instance’s sweeps (its protection is instance-local), and the embedder materializes its fleet-wide protect set into its liveness table (or pin rows) before invoking sweep; no new machinery, the posture only.

Source

pub fn unregister_liveness_source(&self, registration: Registration) -> bool

Deregister a liveness registration previously registered on this store — the in-process sources and the fleet tables’ correction flow (ADR-012 §6.4): a fleet-table token removes the store-side record and the engine-side reference (the SQL arbitration stops consulting it). false when the token was already consumed, was never a liveness token (a protect token), or — fleet form — the reference was not registered.

Source

pub fn register_protect_callback( &self, callback: Arc<dyn ProtectCallback>, ) -> Registration

Register a ProtectCallback — ADR-005 §Marks 3’s protection source. Consulted pre-sweep (it may add externally-known hashes or fail the sweep into GcAbortCause::ProtectFailed report data) and at direct-delete arbitration, where a protect-callback-named key is refused (Error::GcRefuse, ADR-012 §6.4’s full protection set). Registration replaces nothing and composes: each callback’s set unions into the protection.

Source

pub fn unregister_protect_callback(&self, registration: Registration) -> bool

Deregister a protect callback previously registered on this store. false when the token was already consumed or never came from Store::register_protect_callback.

Source

pub async fn delete(&self, key: &[u8]) -> Result<(), Error>

Direct delete(key) — fall-through consult (kv first, then large; ADR-012 §6.4’s “arbitration-then-delete where the entry lives”), then the full protection set arbitration at delete time: a key that is pinned, re-observed live via a registered source, or named by a protect callback is refused with Error::GcRefuse — nothing deleted. Unprotected keys delete (across both homes when a degenerate pool holds the key twice); absent keys carry Error::Missing; malformed key bytes Error::KeyInvalid. A failed protect callback is refused conservatively (GcRefuse, nothing deleted) — the direct-path reading of abort-as-data’s safe side, recorded in the facade module doc.

Outside-of-sweep deletion is unusual by posture — most deletion flows through sweeps (ADR-005); an embedder’s correction flow deregisters/re-registers around the delete (ADR-012 §6.4).

Source

pub async fn sweep(&self) -> Result<SweepReport, Error>

sweep() — the explicit mark-and-sweep with the delete window (ADR-005 §Sweep), in two forms under one signature: the durable form runs on the delete window’s SQL-backed host (ADR-012 §5’s one-window-host rule — the SQL-backed kv engine when it is SQL-backed: sqlite and postgres; the pg-lo large host otherwise: kv = mem + large = pg-lo; the branch keys off the engine representation, never a flag), and the inline form (ADR-012 §5: local/mem stage candidates in-process and execute the window protocol inline in the same sweep) runs verbatim elsewhere. Sweeps are never errors: every abort is report data in SweepReport.aborted (Ok(SweepReport)), and a completed sweep’s counts are exact relative to its form’s schedule — the inline form reports candidates_staged == deleted + cancelled_by_arbitration over its same-sweep staged set; the durable form reports candidates_staged as the candidates staged this sweep and deleted/cancelled as the overdue set executed this sweep (staged and executed are different sets there — the delay separates them, ADR-012 §6.7; deleted/cancelled are both 0 on any abort).

The protocol, as run here:

  1. Single-flight: the in-process sweep lease (ADR-013 §2’s single-node analog); a contended second sweeper aborts with GcAbortCause::SweeperLock, nothing deleted, nothing staged or executed. Under fleet: true the SQL lease composes — both held for the whole sweep (sweep_under_leases, ADR-013 §2’s named exclusive semantics at the fleet host: atomic test-and-set, one sweeper per pool across instances, holdership ends at release, owner death, or engine-session loss; contention — at either domain — is the SweeperLock report abort with nothing deleted). Both releases ride their Drop guards (review-001 N-6): a panic or cancellation inside the sweep body releases the lease(s), never a stuck single-flight state.
  2. Zero registered liveness sources aborts with GcAbortCause::NoLivenessSources before anything is marked — the safe default (nothing deleted).
  3. Protect: each registered ProtectCallback is consulted pre-sweep; its keys union into the live set; a callback that fails to answer aborts with GcAbortCause::ProtectFailed — a flaky protection source skips the sweep rather than risk deletion (iroh’s ProtectOutcome::Abort conclusion). On the durable form this consult’s coverage extends to the executor phase, so an abort here precedes any overdue execution too.
  4. Durable form (SQL-backed kv engine), per sweep under the lease: execute overdue first (the bounded WINDOW_TAKE_BATCH take looped until drained — window_take re-arbitrates each overdue candidate at execution time — pin-before-publish during the window delay cancels the candidate — and deletes), then mark (unchanged), then stage the fresh candidate-dead set at visible_after = mark_end + window (the constructor-tunable delay, ADR-008 §2). The executor of the staged rows is the next sweep (ADR-008 §2; ADR-012 §6.7). Inline form: the mark phase enumerates the whole pool (both tiers’ complete list(), ADR-003 — a malformed pool list is fatal Err(KeyInvalid)); the live set computed from all three sources (registered sources, pins, protect callbacks); the candidate-dead set staged (sorted, in-process).
  5. Delete window: per candidate, arbitration at delete time (not once upfront) under the arbitration lock — pinned or re-observed-live cancels the candidate (counted in cancelled_by_arbitration); otherwise the candidate deletes (counted in deleted) — on the durable form over the bounded take’s drained batches. Under fleet: true the SQL arbitration composes behind the in-process domain (arbitrated_delete’s recorded two-domain composition: in-process first — cheap, local; SQL second — fleet-authoritative), on the direct-delete path and at execution time alike; a foreign instance’s un-expired pin row or a liveness-table row cancels the candidate.

The fleet sweep body (under fleet: true — sweep_window_fleet, the store-fleet-sweep shape, ADR-008 §2’s mechanism as ADR-010 §2/ADR-012 shaped it): the protect consult (instance-local, ProtectFailed abort precedes everything in the body) → the maintenance step (pin_reap: the expired pin rows are reaped — ADR-008 §2’s GC-of-GC cleanup, before the overdue execution; the ordering recorded there) → execute overdue (window_take on the kv host — every fleet-valid configuration’s window hosts there, the one-window-host rule — each candidate re-arbitrated at execution time through the two-domain composition and deleted where it lives, the fall-through across both tiers) → mark (the pool enumerated; the live set from the in-process sources — the SQL liveness tables are consulted at arbitration time, never enumerated into the mark set) → stage at visible_after = mark_end + window → release the lease. Under fleet: false every form above is byte-unchanged.

The test-asserted property (ADR-005): a visible pool entry is never deleted while liveness protects it, and an in-flight put is never deleted by a sweep started before it committed — the in-flight delete markers plus the blocked pin mint are the mechanism (crate::gc’s module doc), and the concurrency tests below assert it (the durable form’s race holds across the window delay — a put landing during the delay pins in-process and the execution-time re-arbitration cancels the candidate). The single-flight, two-domain (ADR-013 §2; the fleet extension): the in-process flag composes with the SQL lease under fleet: true — both held for the whole sweep, the instance-local guard staying cheap and uniform beside the fleet-authoritative lease. The contended second sweeper aborts with GcAbortCause::SweeperLock at either domain, nothing deleted, nothing staged or executed.

The lease’s hold across the sweep body (named design point): the SQL lease holds one pooled checkout for the sweep’s duration (the session-scoped advisory lock’s same-session acquire/release discipline), and the sweep body’s other engine clauses — the maintenance step, window_take, the mark’s list enumeration, window_stage — ride further checkouts under the held lease. The pool therefore must size ≥ 2 for a fleet sweep not to acquire-wait against itself: the fleet constructors enforce max_size >= 2 at entry, and the shipped default (8) provides headroom (a sequential sweep body holds exactly two concurrent checkouts — the lease’s and the current clause’s).

Auto Trait Implementations§

§

impl !RefUnwindSafe for Store

§

impl !UnwindSafe for Store

§

impl Freeze for Store

§

impl Send for Store

§

impl Sync for Store

§

impl Unpin for Store

§

impl UnsafeUnpin for Store

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> 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> Same for T

Source§

type Output = T

Should always be Self
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.