Skip to main content

CovenHandle

Struct CovenHandle 

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

The handle over one coven store.

Open it once with Coven::builder, then call methods. Cheap to clone — every field is shared (an Arc, a Clone handle, or a reference-counted lock), so a clone drives the same database, sync manager, and storage as the original.

§Using the handle

The host builds the handle once at startup and then only calls methods on it — it never assembles coven’s internals by hand or hands them back to coven on every call. Rows go through the connection coven owns; blobs go through the handle’s read/store methods; sync is optional.

// Rows: run app SQL on the connection coven owns.
let note_count = handle
    .sql(|sql| {
        sql.query_row("SELECT count(*) FROM notes", [], |row| row.get(0))
            .map_err(coven::CovenError::from)
    })
    .await?;
let note_count: i64 = note_count.value;

// Blobs: read an exact row version. coven resolves locality — the user's own
// file, its local store, the cache, or a cloud fetch — and returns plaintext.
let bytes: Vec<u8> = handle.read_blob(cover).await?;

// Sync is optional. Connect a provider, then drive it; a store with no
// cloud home never calls these and stays fully usable on-device.
handle.connect_sync().await?;
handle.sync_now();

Implementations§

Source§

impl CovenHandle

Source

pub async fn sql<F, R>(&self, f: F) -> CovenResult<WriteReceipt<R>>
where F: for<'ctx, 'conn> FnOnce(SqlContext<'ctx, 'conn>) -> CovenResult<R> + Send + 'static, R: Send + 'static,

Source

pub async fn discard_pending_branch( &self, branch_id: PendingBranchId, ) -> CovenResult<()>

Source

pub async fn replace_pending_branch<F, R>( &self, branch_id: PendingBranchId, f: F, ) -> CovenResult<WriteReceipt<R>>
where F: for<'ctx, 'conn> FnOnce(SqlContext<'ctx, 'conn>) -> CovenResult<R> + Send + 'static, R: Send + 'static,

Source

pub async fn sql_read<F, R>(&self, f: F) -> CovenResult<R>
where F: FnOnce(&Connection) -> CovenResult<R> + Send + 'static, R: Send + 'static,

Run a pure read against this handle’s read-only companion connection and await the result.

Unlike sql, this attaches no changeset session and opens no journaled transaction: a read pays nothing for capture it would produce nothing for, and runs on a separate SQLITE_OPEN_READONLY connection thread (concurrent with the writer, not queued behind it). The connection is read-only, so an INSERT/UPDATE/DELETE/DDL in the closure is refused by SQLite — a read cannot silently escape the sync journal because it cannot write at all. The closure receives the &Connection directly, so a host closure written against CovenReadHandle::sql_read runs unchanged here.

Read-your-writes holds for committed writes: a sql_read issued after an awaited sql or write sees that data (the WAL reader reads the last committed state). It may not see another task’s write that has not yet committed.

Source

pub async fn write<F, S, R>(&self, f: F, sql: S) -> CovenResult<WriteReceipt<R>>
where F: FnOnce(&mut WriteBatch) -> CovenResult<()> + Send + 'static, S: for<'ctx, 'conn> FnOnce(SqlContext<'ctx, 'conn>) -> CovenResult<R> + Send + 'static, R: Send + 'static,

Source§

impl CovenHandle

Source

pub fn subscribe_sync_status(&self) -> Receiver<SyncLoopStatus>

Subscribe to the sync loop’s SyncLoopStatus stream. The channel is owned by this handle, not the loop, so the receiver keeps working across a reconnect and may be created before any provider is connected (it starts receiving once a loop runs). Infallible for that reason — there is no loop state to check.

The receiver immediately contains the current value. Intermediate values may be coalesced; Synchronized.row_changes is a refresh hint rather than a complete change stream.

Source

pub async fn pending_writes(&self) -> Result<Vec<PendingWrite>, CovenError>

Writes that have shared rows and have not reached a published position.

Source

pub async fn blocked_writes(&self) -> Result<Vec<PendingWrite>, CovenError>

Writes stopped by a semantic publication fault and awaiting an explicit retry or discard decision.

Source

pub async fn retry_blocked_write( &self, write_id: &WriteId, ) -> Result<Vec<WriteId>, CovenError>

Requeue one blocked write for full production validation. Serial writes requeue their whole ordered branch. A connected sync loop is woken after the durable transition.

Source

pub async fn discard_blocked_write( &self, write_id: &WriteId, ) -> Result<Vec<WriteId>, CovenError>

Atomically discard a blocked write and reverse every later unpublished shared write whose working-row state depends on it.

Source

pub async fn pending_branches( &self, ) -> Result<Option<PendingBranch>, CovenError>

Source

pub async fn write_status( &self, write_id: &WriteId, ) -> Result<WriteStatus, CovenError>

Read the current durable status of one write.

Source

pub async fn subscribe_write_status( &self, write_id: &WriteId, ) -> Result<Receiver<WriteStatus>, CovenError>

Subscribe to one write’s current durable status. The initial value is reconstructed from SQLite before the receiver is returned.

Source

pub async fn connect_sync(&self) -> Result<(), SyncError>

Build the [SyncManager] for a connected cloud provider, start its sync loop, and install it. Returns the started manager, or an error if the cloud home fails to build — in which case nothing is installed, so the handle never holds a manager that reports success with nothing started.

The at-rest cipher is resolved from the handle’s custody per start: an opaque home unlocks the master keyring (failing with SyncError::MasterKeyNotEstablished if none is established), a browsable one never consults custody. Reconnecting a provider rebuilds the manager — the [Database] keeps the seeded register clock across the rebuild, so only the cloud home + loop are replaced.

Source

pub async fn connect_sync_with_cloudkit( &self, cloudkit_ops: Arc<dyn CloudKitOps>, ) -> Result<(), SyncError>

Source

pub async fn connect_sync_with_test_home( &self, home: Arc<dyn CloudHome>, cipher: CloudCipher, ) -> Result<(), SyncError>

Test-only: connect a started [SyncManager] over an injected CloudHome instead of one built from Config, so a host’s integration tests drive the real make-Remote / make-Local / upload-drain and read paths over a mock cloud with no live provider.

The test counterpart of connect_sync: it stands the manager over home/cipher through [SyncManager::start_sync_with_home], starts the loop, and installs it with the same start-before-install discipline — a failed connect leaves the handle home-less rather than holding a manager whose loop never started. The injected cipher is the at-rest protection directly — the manager’s custody is never consulted on this path.

The read path needs no separate hook: blob_storage serves reads from the connected loop’s own [CloudSyncStorage], which here wraps the injected home, so read_blob / pin resolve a Remote miss against the same test home the drain writes to.

Source

pub async fn connect_sync_with_test_home_and_coordination( &self, home: Arc<dyn CloudHome>, coordination: Arc<dyn CloudHeadStorage>, cipher: CloudCipher, ) -> Result<(), SyncError>

Source

pub async fn connect_sync_with_test_home_custody( &self, home: Arc<dyn CloudHome>, ) -> Result<(), SyncError>

Test-only: connect over an injected CloudHome while resolving the at-rest cipher from custody the way production connect_sync does, instead of taking an explicit cipher like connect_sync_with_test_home.

Where that method injects the cipher and never touches custody, this drives [SyncManager::start_sync_with_test_home_custody], which unlocks the master keyring through the store’s custody exactly as start_sync would — so a test can establish a key, connect over a mock home, and prove the traffic is sealed under that key. An opaque home with no key established fails SyncError::MasterKeyNotEstablished before the loop starts.

Source

pub async fn start_sync(&self) -> Result<(), SyncError>

Start (or restart) the sync loop of the installed [SyncManager]. A no-op when no provider is connected — a home-less store has nothing to start. Errors if the installed manager’s cloud home fails to build.

Source

pub fn stop_sync(&self)

Stop the sync loop after the in-flight cycle, keeping the installed manager so start_sync can resume it. A no-op when no provider is connected.

The material a running loop resolved from custody (the master keyring, the device signing identity) is cached only inside that loop for as long as it runs — nowhere else in the handle — and this is where it is purged. A subsequent start_sync/ connect_sync re-resolves fresh from whatever custody now serves, so a host’s lock flow that stops sync as part of locking, then later reconnects, never resumes on stale material.

Source

pub fn disconnect_sync(&self)

Disconnect the provider entirely: stop the loop and drop the installed [SyncManager]. The store becomes home-less until the next connect_sync.

Carries the same purge as stop_sync (dropping the manager cannot leave more behind than stopping its loop already cleared) and additionally drops the manager itself, so nothing about the previous connection — including which custody it resolved material from — survives into the next connect.

Source

pub fn sync_now(&self)

Wake the sync loop to run a cycle now rather than at the next idle tick. A no-op when no provider is connected.

Source

pub fn is_syncing(&self) -> bool

Whether the sync loop is running. false for a home-less store.

Source

pub fn is_connected(&self) -> bool

Whether a [SyncManager] is installed — a provider is connected. Distinct from is_syncing, which additionally requires the loop to be running: this is the predicate a host uses for “has a cloud home” without the loop-ready condition.

Source

pub fn initialize_master_key(&self) -> Result<String, MasterKeyError>

Generate this store’s master key and establish it under the handle’s custody. Errors with MasterKeyError::AlreadyEstablished if custody already unlocks one — coven never generates over an existing key, so a corrupt (present-but-unreadable) entry is never silently overwritten either, since custody’s unlock surfaces that as Err, not None. The only place coven ever generates a master key. Returns its fingerprint for the host to record in its own config.

Source

pub fn import_master_key( &self, serialized: &str, ) -> Result<String, MasterKeyError>

Import a serialized master keyring a host already holds and establish it under the handle’s custody, replacing whatever custody already holds. Returns its fingerprint for the host to record in its own config.

Source

pub fn forget_master_key(&self) -> Result<(), KeyError>

Remove the master key from custody — a host’s lock/sign-out flow. Ok whether or not one was established.

Source

pub fn master_key_fingerprint(&self) -> Result<Option<String>, KeyError>

The established master key’s fingerprint, or None if custody has never had one established (or is locked, for a policy where that’s representable).

Source

pub fn initialize_identity(&self) -> Result<String, IdentityError>

Generate this store’s signing identity and establish it under the handle’s identity custody. Errors with IdentityError::AlreadyEstablished if custody already unlocks one — coven never generates over an existing identity. The counterpart of initialize_master_key for a store a host is creating fresh (not joining or restoring, which each establish their own identity as part of what they do). Returns the established public key, hex-encoded.

Source

pub fn set_host_secret(&self, name: &str, value: &str) -> Result<(), KeyError>

Set a host’s own store-scoped secret — an API token, a service credential — under the same platform keyring, and the same access policy, as coven’s own key material. name identifies the secret within the store; coven owns the account rendering and the entry’s protection class. KeyError::InvalidSecretName if name collides with one of coven’s own reserved slot names, is empty, or contains :.

Source

pub fn host_secret(&self, name: &str) -> Result<Option<String>, KeyError>

Read a host secret set by set_host_secret, None if never set. A present-but-empty entry is corrupt, not absent — the same discipline coven’s own key reads apply.

Source

pub fn delete_host_secret(&self, name: &str) -> Result<(), KeyError>

Remove a host secret. Ok whether or not one was set.

Source

pub fn seal_app_data( &self, plaintext: &[u8], aad: &[u8], ) -> Result<Vec<u8>, SealError>

Seal plaintext under the store’s current master-key generation, for a host to store in its own rows — a password entry’s payload, an API token. coven’s at-rest encryption is cloud-side; the local database is plaintext SQLite, so a host with a secret to keep in a row seals it here first.

The output records the generation it was sealed under, so it stays openable after any number of key rotations. aad binds the ciphertext to its context — the owning row’s primary key, say — and open_app_data with a different aad fails, so a payload moved to another row does not silently open there.

SealError::Locked if the store has no established master key, the same gate connect_sync applies before it seals cloud traffic.

Source

pub fn open_app_data( &self, sealed: &[u8], aad: &[u8], ) -> Result<Vec<u8>, SealError>

Open a payload seal_app_data produced, under whichever generation it names — a rotated keyring still opens everything it sealed before rotating.

SealError::Locked if the store is locked; a wrong aad, a tampered payload, an unreadable version, or a generation this store’s keyring lacks each surface their own typed error.

Source

pub async fn row_blob_ref( &self, table: &str, row_id: &str, ) -> Result<RowBlobRef, DbError>

Capture the exact current blob-bearing row version. Blob operations use this row-bound value so a later row replacement cannot redirect a read.

Source

pub async fn read_blob( &self, blob: &RowBlobRef, ) -> Result<Vec<u8>, BlobCacheError>

Read a blob’s whole plaintext through coven’s locality-aware read: served from the user’s file (Local user-provided), coven’s local store (Local host-provided), the pinned/evictable cache on a Remote hit, or fetched from the cloud (into the cache) on a Remote miss. The host passes the RowBlobRef captured from row_blob_ref; coven holds the database, directory, and storage.

Source

pub async fn open_blob_stream( &self, blob: &RowBlobRef, offset: u64, len: u64, ) -> Result<Vec<u8>, BlobCacheError>

Serve len plaintext bytes of an exact row blob starting at offset, for streaming or seeking without loading the whole file. The RowBlobRef carries the plaintext length used to bound the range. The ranged sibling of read_blob.

Source

pub async fn pin(&self, blobs: &[RowBlobRef]) -> Result<(), BlobCacheError>

Pin a Remote blob set for offline: coven fetches each into the protected cache (storage/pinned/) — from the evictable cache if already there, else the cloud — exempt from the size budget. Idempotent.

Source

pub async fn unpin(&self, blobs: &[RowBlobRef]) -> Result<(), BlobCacheError>

Unpin a Remote blob set: coven moves each from storage/pinned/ to the evictable storage/cache/ (still readable, now droppable). No cloud read.

Source

pub fn blob_cloud_key(&self, blob: &BlobRef) -> Result<String, StorageError>

The cloud object key a blob’s bytes live at, derived under the connected home’s path scheme (Hashed{namespace}/{ab}/{cd}/{id}, Plain{namespace}/{cloud_path}). coven owns this derivation — the host passes a BlobRef and never reconstructs the cloud layout. The host enqueues a blob’s cloud removal under this key (its delete drains to a tombstone; see [crate::blob::delete]), and a test asserts an upload’s key matches the read key with it. A Plain home whose cloud_path is absent, or does not name the blob it carries, is a surfaced error — see [CloudSyncStorage::blob_key].

Source

pub async fn is_pinned(&self, blobs: &[BlobRef]) -> Result<bool, BlobCacheError>

Whether every blob in blobs is pinned for offline — present in coven’s kept cache folder (storage/pinned/). The host answers “is this release kept offline” through this instead of stat-ing coven’s cache layout itself. An empty set is vacuously pinned. A blob not pinned (in the evictable cache or absent) makes the whole set unpinned; an existence-check failure is surfaced, never read as “not pinned”.

Source

pub async fn evict_blob(&self, blob: &BlobRef) -> Result<(), BlobCacheError>

Remove one Remote blob’s re-fetchable on-device cache copies from both storage/pinned/ and storage/cache/. This never touches the local store, whose bytes may be the only usable copy owned by an unpublished write. It does not delete the cloud blob or its carrying row; a later read can fetch the bytes again.

Source

pub async fn make_remote( &self, root_table: &str, root_id: &str, pin: bool, ) -> Result<(), MakeRemoteError>

Make (root_table, root_id) Remote (Local → Remote): enqueue an upload per user-provided blob from its external file and record the make_remote intent, then return. The drain uploads each and flips the gate true on the last; the gate flip re-emits the subtree and the cycle’s inline push uploads host-provided blobs. pin keeps the uploaded blobs in the cache as pinned offline copies. Errors with MakeRemoteError::SyncNotReady when no provider is connected.

Source

pub async fn cancel_make_remote( &self, root_table: &str, root_id: &str, ) -> Result<(), MakeRemoteError>

Cancel an in-flight make_remote of (root_table, root_id): clear its intent and pending uploads and tombstone any blob already in the cloud. The gate never flips, so the root stays Local. Errors with MakeRemoteError::SyncNotReady when no provider is connected.

Source

pub async fn make_local( &self, root_table: &str, root_id: &str, dest: &HashMap<String, PathBuf>, cancel: &Receiver<bool>, ) -> Result<(), MakeLocalError>

Make (root_table, root_id) Local (Remote → Local): bring each blob back to a local file durability-first — a user-provided blob to the path named in dest (blob id → destination path), a host-provided blob to coven’s local store (no dest) — then flip the gate false, register the external refs, and enqueue the cloud deletes in one atomic commit. cancel aborts before the commit (the root stays Remote). Errors with MakeLocalError::SyncNotReady when no provider is connected.

Source

pub async fn drain_uploads(&self) -> Result<DrainOutcome, SyncError>

Drain pending blob uploads now: read each local file, seal it under its scope, write it to the cloud, and keep a retain_pinned entry’s plaintext in the protected cache. Returns the [DrainOutcome].

The sync loop drains each cycle; this drives a drain directly off the connected home, against coven’s own register clock and the handle’s observer. Errors when no provider is connected (there is no cloud to write to).

Source

pub async fn get_cache_budget( &self, namespace: &str, ) -> Result<Option<u64>, DbError>

Source

pub async fn set_cache_budget( &self, namespace: &str, max_bytes: u64, ) -> Result<(), DbError>

Source

pub fn get_user_pubkey(&self) -> Result<Option<String>, SyncError>

Source

pub async fn generate_restore_code(&self) -> Result<String, SyncError>

Generate a restore code, seeded with the store’s current membership-head floor read from the cloud. Requires a connected provider: unlike the old, storage-free version of this call, minting a trustworthy floor is a network read, not a pure function of local config and keyring state — a restore code minted without one would carry no protection against a storage provider replaying an older, otherwise validly signed membership state to the device that redeems it.

Source

pub async fn get_members(&self) -> Result<Vec<MemberInfo>, SyncError>

Source

pub async fn begin_device_join( &self, member_pubkey: &str, provider_administrator: ProviderAdminGrantId, ) -> Result<DeviceJoinOffer, SyncError>

Source

pub async fn authorize_device_provider_access( &self, request: DeviceProviderAccessRequest, access_administrator: Option<&dyn DeviceProviderAccessAdministrator>, ) -> Result<DeviceProviderAdmissionApproval, SyncError>

Source

pub async fn accept_device_registration_request( &self, request: DeviceRegistrationRequest, ) -> Result<ProvisionalDeviceBootstrap, SyncError>

Source

pub async fn publish_device_provider_challenge( &self, bootstrap: ProvisionalDeviceBootstrap, ) -> Result<ProviderReadyDeviceBootstrap, SyncError>

Source

pub async fn complete_device_provider_admission( &self, readiness: DeviceJoinReadiness, ) -> Result<DeviceProviderAdmissionCompletion, SyncError>

Source

pub async fn finalize_device_join( &self, completion: DeviceProviderAdmissionCompletion, ) -> Result<DeviceJoinActivation, SyncError>

Source

pub async fn cancel_device_join( &self, attempt: DeviceJoinAttemptRef, ) -> Result<DeviceJoinCancellation, SyncError>

Source

pub async fn device_join_status( &self, attempt_id: DeviceJoinAttemptId, role: DeviceJoinRole, ) -> Result<Option<DeviceJoinStatus>, SyncError>

Source

pub async fn invite_member( &self, public_key_hex: &str, invitee_email: Option<&str>, role: MemberRole, ) -> Result<String, SyncError>

Source

pub async fn remove_member( &self, public_key_hex: &str, ) -> Result<String, SyncError>

Source

pub async fn create_circle(&self, name: &str) -> Result<CircleId, SyncError>

Create and activate a circle whose founder is this Store identity. Returns only after the signed roster, metadata, access set, control, Store commit, activation head, and local materialization are durable.

Source

pub async fn get_circles(&self) -> Result<Vec<CircleInfo>, SyncError>

Return circles with a locally verified active access record.

Source

pub async fn get_circle_operations( &self, ) -> Result<Vec<CircleOperationInfo>, SyncError>

Return durable circle commands that have not activated.

Source

pub async fn discard_circle_operation( &self, circle_id: CircleId, ) -> Result<(), SyncError>

Discard a blocked circle command. Repeating the discard is a no-op; pending commands must finish or become blocked before they can be discarded.

Trait Implementations§

Source§

impl Clone for CovenHandle

Source§

fn clone(&self) -> CovenHandle

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. 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.

§

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

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

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

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,