Struct RecordId
pub struct RecordId(/* private fields */);Expand description
The stable identity of a record. Encoded by prefix:
file-record:<uuid> (a file, by the durable id its filesystem record
carries — see RecordId::identify_file), file:<absolute path> (a
file known only by where it is: a not-yet-written Save As target, or a
filesystem that can’t hold the durable id), uuid:<uuid> (minted, for a
record with no natural name), tab:<tab id> (a window’s scratch document
until a file names it, see RecordId::for_tab) and
derived:<role>@<id> (see RecordId::derived).
§Files
A file’s identity is its file record, never its path or its bytes:
- Rename and move keep it. The collaborative filesystem keys files by
a
FileRecordIdthat survives rename and move and serves it as theuser.tilo.record-idattribute; elsewhere the same attribute is written once on first open and travels with the inode. - A copy is a new file. The filesystem mints a new record for a
created file, and a plain local copy does not carry the attribute, so a
copy starts with its own records. That is deliberate: copying is how a
person forks a document — to send a clean version, or to try different
edits — and mirroring every note into the copy would surprise them and
leak notes into what they hand on. Tools asked to preserve extended
attributes (
cp -a,rsync -X) are an explicit request to keep the identity, and do. - Identical bytes are not the same file. Nothing here is derived from
content, so two files with the same bytes never share edits by accident.
Content that should be shared by bytes is a blob reference instead
([
add_blob_reference]).
The prefix is part of the id, not a tag beside it: the id travels on the wire and names a file on disk, so it must be self-describing.
Implementations§
§impl RecordId
impl RecordId
pub fn package_primary() -> RecordId
pub fn package_primary() -> RecordId
Internal custody key for a package’s existing workspace-primary document. It never travels as a record id on the collaboration wire.
pub fn is_package_primary(&self) -> bool
pub fn from_route(record: &str) -> Option<RecordId>
pub fn from_route(record: &str) -> Option<RecordId>
The record a collaboration route’s record id names: the empty id is the package primary, anything else must be a record id. The package primary’s custody key is not a route, so a route spelling it names nothing: one record never has two routes.
pub fn route(&self) -> &str
pub fn route(&self) -> &str
The record id this record travels under on the collaboration wire,
what Self::from_route reads back.
pub fn for_file(path: impl AsRef<Path>) -> RecordId
pub fn for_file(path: impl AsRef<Path>) -> RecordId
The record a file is. Relative paths resolve against the cwd, so two spellings of one file are one record.
The id embeds the absolute path, so two peers reach one record only if the file sits at the same path on both. Don’t use this for content embedded in a document (a dropped image) — that needs a content-addressed record, not a path-addressed one.
pub fn for_file_record(id: Uuid) -> RecordId
pub fn for_file_record(id: Uuid) -> RecordId
The record of the file whose filesystem record id is id — the
collaborative filesystem’s FileRecordId, or the id
Self::identify_file wrote for a file elsewhere.
pub fn identify_file(path: impl AsRef<Path>) -> RecordId
pub fn identify_file(path: impl AsRef<Path>) -> RecordId
The durable identity of the file at path, so reopening it after a
rename or move reaches the same records.
Reads the file’s user.tilo.record-id attribute (16 raw bytes — the
collaborative filesystem serves its FileRecordId there; on macOS,
where every copy inherits the attribute, the id is followed by the
inode it belongs to so a copy is told apart). A file
without one, on a filesystem that accepts user attributes, gets a
freshly minted id written with create-only semantics (a concurrent
opener that wins the race is re-read, so both agree). Anything else —
no attribute support, a read-only file, not a regular file — falls
back to the path identity Self::for_file: the best identity the
file can carry.
Two system calls at most besides the metadata lookup; call it off the UI thread when the file might be on a network filesystem.
pub fn minted() -> RecordId
pub fn for_tab(tab: u64) -> RecordId
pub fn for_tab(tab: u64) -> RecordId
Reuses the tab id rather than minting a new one: it’s already unique per machine and persisted with the window tree, so a separate id beside it could only drift.
pub fn workspace_default() -> RecordId
pub fn workspace_default() -> RecordId
The record an app opens in a workspace when nothing names another one: the first window of the app on any device of the workspace, native or browser, so they all meet on one document. Constant, so every device derives the same id without asking; the workspace scopes it.
pub fn window_default(instance: u64) -> RecordId
pub fn window_default(instance: u64) -> RecordId
The record a fresh window (instance, the launcher’s tab id) of an
app that keeps a record per window opens when nothing names another
one. Window 0 is Self::workspace_default, what a launch outside the
launcher opens. See NativeProcessHost for which apps get one.
pub fn window_default_of_storage_key(storage_key: &str) -> Option<RecordId>
pub fn window_default_of_storage_key(storage_key: &str) -> Option<RecordId>
The window whose default record is stored
under storage_key (Self::storage_key), if that is what it is.
Exact: the whole key, hash included, must be that record’s.
pub fn of_member(person: &str, kind: &str) -> Option<RecordId>
pub fn of_member(person: &str, kind: &str) -> Option<RecordId>
person’s own record of kind in a workspace
(collab_types::member_record): only that person’s devices read
or change it. None when person is not the hex of a user root key
or kind is not a label.
pub fn of_direct(pair: &str) -> Option<RecordId>
pub fn of_direct(pair: &str) -> Option<RecordId>
The record of the pair two people share in a workspace
([collab_types::direct_pair_id]): an ordinary record of the
workspace, named by the two people so either derives it. None for a
key that names no pair.
pub fn derived(role: &str, of: &RecordId) -> RecordId
pub fn derived(role: &str, of: &RecordId) -> RecordId
Identity of the record that plays role for of — “the annotations
of this document”. Distinct from its target so the two can be
shared separately: handing over the document doesn’t hand the notes.
pub fn part(&self, index: u64) -> RecordId
pub fn part(&self, index: u64) -> RecordId
Part index of the chained record self: a record that grows
without end is kept as numbered parts, each a record of its own. A
workspace’s host replays a joining device only the chain’s head, the
highest part it holds; every earlier part is sent to a device when
it opens it. Two writers that start part n + 1 start the same
record. The wire form is neighbour_wire::record_part’s.
pub fn chain_part(&self) -> Option<(RecordId, u64)>
pub fn chain_part(&self) -> Option<(RecordId, u64)>
The chain and number of a Self::part, or None for any other
record.
pub fn chunk(&self, number: u64) -> RecordId
pub fn chunk(&self, number: u64) -> RecordId
Chunk number of the record self: the platform keeps a large
record’s resources in several documents, each a record of its own, so
that a write reaches only the chunk it changed. Chunk 0 is the
record itself — read in place, never copied — so self.chunk(0) is
self. Like a Self::part, a workspace’s host sends a joining
device only the chunks it opens, and two writers that start chunk
n + 1 start the same record. The number says nothing about what a
chunk holds: the platform picks it by measured size, never the app.
pub fn chunk_of(&self) -> Option<(RecordId, u64)>
pub fn chunk_of(&self) -> Option<(RecordId, u64)>
The base record and number of a Self::chunk, or None for the
record itself and for any other record.
pub fn part_of_storage_key(&self, storage_key: &str) -> Option<u64>
pub fn part_of_storage_key(&self, storage_key: &str) -> Option<u64>
The number of the part of the chain self whose document is kept
under storage_key (Self::storage_key), or None for any other
record’s: what a store lists of a chain it holds parts of without
having opened them.
pub fn chunk_of_storage_key(&self, storage_key: &str) -> Option<u64>
pub fn chunk_of_storage_key(&self, storage_key: &str) -> Option<u64>
The number of the chunk of the record self whose document is kept
under storage_key (Self::storage_key), or None for any other
record’s: what a store lists of a record’s chunks it holds without
having opened the record’s manifest.
pub fn child(&self, id: &str) -> Option<RecordId>
pub fn child(&self, id: &str) -> Option<RecordId>
The child record id of self: a resource kept as a record of its
own inside its parent (a chat’s channel), its id minted once and
never changed, wherever its parent lists it
(tilo_resource::children). None for an id that cannot name a
record (empty, too long, or with characters other than letters,
digits, ., _ and -).
pub fn child_of(&self) -> Option<(RecordId, String)>
pub fn child_of(&self) -> Option<(RecordId, String)>
The parent and id of a Self::child, or None for any other
record.
pub fn tree(&self) -> Option<RecordId>
pub fn tree(&self) -> Option<RecordId>
The record whose tree self belongs to: the chain of a
Self::part, the parent of a Self::child; None for a record
of its own. Such a record lives and syncs with its tree: whatever
holds the tree holds it, whether or not a view shows it.
pub fn on_demand(&self) -> RecordId
pub fn on_demand(&self) -> RecordId
self declared on-demand: a workspace’s host does not replay it to a
joining device, and sends it to a device when it opens it. The wire
form is neighbour_wire::on_demand_record’s.
pub fn parse(s: &str) -> Option<RecordId>
pub fn parse(s: &str) -> Option<RecordId>
Adopt an id read back from a document, a workspace index, or the wire. Invalid, oversized, or non-canonical names fail closed: IDs name collaboration routes and storage directories, so accepting arbitrary strings here would turn a workspace index into an allocation oracle.
pub fn uri(&self) -> String
pub fn uri(&self) -> String
The URI asking an app to open this record
([collab_types::RECORD_URI_SCHEME]).
pub fn as_str(&self) -> &str
pub fn file_record(&self) -> Option<Uuid>
pub fn file_record(&self) -> Option<Uuid>
The filesystem record id of a file-record: identity.
pub fn storage_key(&self) -> String
pub fn storage_key(&self) -> String
A filesystem-safe directory name for this record’s document. Must be stable (same record → same directory next launch, or data is silently orphaned) and collision-free (two records sharing a directory merge their documents) — hence a readable sanitised prefix plus a hash of the whole id, which is what actually distinguishes them.
§impl RecordId
impl RecordId
pub fn arrives_on_demand(&self) -> bool
pub fn arrives_on_demand(&self) -> bool
Whether a workspace’s hosts send this record to a device only once it
asks for it: a Self::part of a chain (the head too, which a
device that joined before it started asks for) or an
Self::on_demand record. Opening one reads what this device holds
or asks for it, and never waits for it to arrive
(ui::record::RecordOpenError::Arriving).
Trait Implementations§
§impl Ord for RecordId
impl Ord for RecordId
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
§impl PartialOrd for RecordId
impl PartialOrd for RecordId
impl Eq for RecordId
impl StructuralPartialEq for RecordId
Auto Trait Implementations§
impl Freeze for RecordId
impl RefUnwindSafe for RecordId
impl Send for RecordId
impl Sync for RecordId
impl Unpin for RecordId
impl UnsafeUnpin for RecordId
impl UnwindSafe for RecordId
Blanket Implementations§
§impl<T> AnyEq for T
impl<T> AnyEq for T
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,
§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<F, T, S> SimdInto<T, S> for Fwhere
T: SimdFrom<F, S>,
S: Simd,
impl<F, T, S> SimdInto<T, S> for Fwhere
T: SimdFrom<F, S>,
S: Simd,
§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.