pub struct Doc { /* private fields */ }Implementations§
Source§impl Doc
impl Doc
Sourcepub fn atomic() -> Self
pub fn atomic() -> Self
Creates a new empty atomic document.
The atomic flag means “this data is a complete replacement — take all of it.” During merge (left ⊕ right):
right.atomic→ LWW: return right (always replaces left entirely)left.atomic,!right.atomic→ structural field merge, result stays atomic (the flag is contagious)- Neither atomic → structural field merge, result non-atomic
The contagious property preserves associativity: in a chain 1⊕2⊕3⊕4
where 3 is atomic and 4 edits subfields, 3⊕4 produces an atomic
result, so (1⊕2) ⊕ (3⊕4) correctly overwrites everything before 3.
Use this for config or metadata that must always be written as a
consistent whole. Types that need atomicity should convert into
Doc::atomic() (e.g., via impl From<MyType> for Doc) to declare
replacement semantics.
§Examples
let mut doc1 = Doc::atomic();
doc1.set("x", 1);
doc1.set("y", 2);
let mut doc2 = Doc::atomic();
doc2.set("x", 10);
doc2.set("z", 30);
// Atomic merge replaces entirely (LWW), no field-level merge
let merged = doc1.merge(&doc2).unwrap();
assert_eq!(merged.get_as::<i64>("x"), Some(10));
assert_eq!(merged.get_as::<i64>("z"), Some(30));
assert_eq!(merged.get_as::<i64>("y"), None); // Not carried from doc1Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if this document has no data (excluding tombstones).
Sourcepub fn contains_key(&self, key: impl AsRef<Path>) -> bool
pub fn contains_key(&self, key: impl AsRef<Path>) -> bool
Returns true if the document contains the given key.
Sourcepub fn is_tombstone(&self, key: impl AsRef<Path>) -> bool
pub fn is_tombstone(&self, key: impl AsRef<Path>) -> bool
Returns true if the exact path points to a tombstone (Value::Deleted).
This method checks if the specific key has been deleted. Note that this only returns true if the exact path is a tombstone - it does not check if an ancestor was deleted (which would make the path inaccessible).
To check if a path is inaccessible (either deleted or has a deleted ancestor),
use get(path).is_none() instead.
§Examples
let mut doc = Doc::new();
doc.set("user.profile.name", "Alice");
doc.remove("user.profile.name");
assert!(doc.is_tombstone("user.profile.name"));
assert!(!doc.is_tombstone("user.profile")); // parent is not tombstoned
// Deleting a parent makes children inaccessible but not directly tombstoned
doc.set("settings.theme.color", "blue");
doc.remove("settings.theme");
assert!(doc.is_tombstone("settings.theme")); // exact path is tombstoned
assert!(!doc.is_tombstone("settings.theme.color")); // child path is NOT a tombstone
assert!(doc.get("settings.theme.color").is_none()); // but it's still inaccessibleSourcepub fn get(&self, key: impl AsRef<Path>) -> Option<&Value>
pub fn get(&self, key: impl AsRef<Path>) -> Option<&Value>
Gets a value by key or path (immutable reference).
Supports both simple keys and dot-separated paths for nested access.
Returns None if the key doesn’t exist or has been deleted (tombstone).
§Examples
let mut doc = Doc::new();
doc.set("name", "Alice");
doc.set("user.profile.age", 30);
assert!(doc.get("name").is_some());
assert!(doc.get("user.profile.age").is_some());
assert!(doc.get("nonexistent").is_none());
// Deleted keys return None
doc.remove("name");
assert!(doc.get("name").is_none());Sourcepub fn get_mut(&mut self, key: impl AsRef<Path>) -> Option<&mut Value>
pub fn get_mut(&mut self, key: impl AsRef<Path>) -> Option<&mut Value>
Gets a mutable reference to a value by key or path
Sourcepub fn get_as<'a, T>(&'a self, key: impl AsRef<Path>) -> Option<T>
pub fn get_as<'a, T>(&'a self, key: impl AsRef<Path>) -> Option<T>
Gets a value by key with automatic type conversion using TryFrom
Returns Some(T) if the value exists and can be converted to type T. Returns None if the key doesn’t exist or type conversion fails.
This is the recommended method for type-safe value retrieval as it provides
a cleaner Option-based interface compared to the Result-based get_as() method.
§Examples
let mut doc = Doc::new();
doc.set("name", "Alice");
doc.set("age", 30);
doc.set("active", true);
// Returns Some when value exists and type matches
assert_eq!(doc.get_as::<&str>("name"), Some("Alice"));
assert_eq!(doc.get_as::<i64>("age"), Some(30));
assert_eq!(doc.get_as::<bool>("active"), Some(true));
// Returns None when key doesn't exist
assert_eq!(doc.get_as::<String>("missing"), None);
// Returns None when type doesn't match
assert_eq!(doc.get_as::<i64>("name"), None);Sourcepub fn set(
&mut self,
key: impl AsRef<Path>,
value: impl Into<Value>,
) -> Option<Value>
pub fn set( &mut self, key: impl AsRef<Path>, value: impl Into<Value>, ) -> Option<Value>
Sets a value at the given key or path, returns the old value if present.
This method automatically creates intermediate Doc nodes for nested paths.
For example, doc.set("a.b.c", value) will create a and b as Doc nodes
if they don’t exist.
§Examples
let mut doc = Doc::new();
// Simple key
doc.set("name", "Alice");
// Nested path - creates intermediate nodes automatically
doc.set("user.profile.age", 30);
assert_eq!(doc.get_as("name"), Some("Alice"));
assert_eq!(doc.get_as("user.profile.age"), Some(30));Sourcepub fn remove(&mut self, key: impl AsRef<Path>) -> Option<Value>
pub fn remove(&mut self, key: impl AsRef<Path>) -> Option<Value>
Removes a value by key or path, returns the old value if present.
This method implements CRDT semantics by always creating a tombstone marker. For nested paths, intermediate Doc nodes are created if they don’t exist.
§Examples
let mut doc = Doc::new();
doc.set("user.profile.name", "Alice");
let old = doc.remove("user.profile.name");
assert_eq!(old.and_then(|v| v.as_text().map(|s| s.to_string())), Some("Alice".to_string()));
assert!(doc.get("user.profile.name").is_none());Sourcepub fn iter(&self) -> impl Iterator<Item = (&String, &Value)>
pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)>
Returns an iterator over all key-value pairs (excluding tombstones)
Sourcepub fn keys(&self) -> impl Iterator<Item = &String>
pub fn keys(&self) -> impl Iterator<Item = &String>
Returns an iterator over all keys (excluding tombstones)
Sourcepub fn values(&self) -> impl Iterator<Item = &Value>
pub fn values(&self) -> impl Iterator<Item = &Value>
Returns an iterator over all values (excluding tombstones)
Sourcepub fn to_json_string(&self) -> String
pub fn to_json_string(&self) -> String
Converts this Doc to a JSON string representation.
This produces a valid JSON object string from the document’s contents, excluding tombstones.
Source§impl Doc
impl Doc
Sourcepub fn set_json<T>(
&mut self,
key: impl AsRef<Path>,
value: T,
) -> Result<&mut Self>where
T: Serialize,
pub fn set_json<T>(
&mut self,
key: impl AsRef<Path>,
value: T,
) -> Result<&mut Self>where
T: Serialize,
Set a key-value pair with automatic JSON serialization for any Serialize type.
The value is serialized to a JSON string and stored as Value::Text.
§Examples
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct User { name: String, age: i32 }
let mut doc = Doc::new();
doc.set_json("user", User { name: "Alice".into(), age: 30 })?;
let user: User = doc.get_json("user")?;
assert_eq!(user, User { name: "Alice".into(), age: 30 });Sourcepub fn get_json<T>(&self, key: impl AsRef<Path>) -> Result<T>where
T: for<'de> Deserialize<'de>,
pub fn get_json<T>(&self, key: impl AsRef<Path>) -> Result<T>where
T: for<'de> Deserialize<'de>,
Get a value by key with automatic JSON deserialization for any Deserialize type.
The value must be a Value::Text containing valid JSON.
§Errors
Returns an error if:
- The key doesn’t exist
- The value is not a
Value::Text - The JSON deserialization fails
Sourcepub fn get_or_insert(
&mut self,
key: impl AsRef<Path> + Clone,
default: impl Into<Value>,
) -> &mut Value
pub fn get_or_insert( &mut self, key: impl AsRef<Path> + Clone, default: impl Into<Value>, ) -> &mut Value
Gets or inserts a value with a default, returns a mutable reference.
If the key doesn’t exist, the default value is inserted. Returns a mutable reference to the value (existing or newly inserted).
§Examples
let mut doc = Doc::new();
// Key doesn't exist - will insert default
doc.get_or_insert("counter", 0);
assert_eq!(doc.get_as::<i64>("counter"), Some(0));
// Key exists - will keep existing value
doc.set("counter", 5);
doc.get_or_insert("counter", 100);
assert_eq!(doc.get_as::<i64>("counter"), Some(5));Trait Implementations§
Source§impl CRDT for Doc
impl CRDT for Doc
Source§fn merge(&self, other: &Self) -> Result<Self>
fn merge(&self, other: &Self) -> Result<Self>
Merges another document into this one using CRDT semantics.
This implements the core CRDT merge operation at the document level, providing deterministic conflict resolution following CRDT semantics.
Merge combines the key-value pairs from both documents, resolving conflicts deterministically using CRDT rules.
Source§impl<'de> Deserialize<'de> for Doc
impl<'de> Deserialize<'de> for Doc
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl From<AuthSettings> for Doc
impl From<AuthSettings> for Doc
Source§fn from(settings: AuthSettings) -> Doc
fn from(settings: AuthSettings) -> Doc
Source§impl From<DelegatedTreeRef> for Doc
impl From<DelegatedTreeRef> for Doc
Source§fn from(dtref: DelegatedTreeRef) -> Doc
fn from(dtref: DelegatedTreeRef) -> Doc
Source§impl From<Doc> for AuthSettings
impl From<Doc> for AuthSettings
Source§impl From<EncryptedFragment> for Doc
impl From<EncryptedFragment> for Doc
Source§fn from(frag: EncryptedFragment) -> Doc
fn from(frag: EncryptedFragment) -> Doc
Source§impl From<EncryptionInfo> for Doc
impl From<EncryptionInfo> for Doc
Source§fn from(info: EncryptionInfo) -> Doc
fn from(info: EncryptionInfo) -> Doc
Source§impl From<PasswordStoreConfig> for Doc
impl From<PasswordStoreConfig> for Doc
Source§fn from(config: PasswordStoreConfig) -> Doc
fn from(config: PasswordStoreConfig) -> Doc
Source§impl From<Permission> for Doc
impl From<Permission> for Doc
Source§fn from(perm: Permission) -> Doc
fn from(perm: Permission) -> Doc
Source§impl From<PermissionBounds> for Doc
impl From<PermissionBounds> for Doc
Source§fn from(bounds: PermissionBounds) -> Doc
fn from(bounds: PermissionBounds) -> Doc
Source§impl From<TreeReference> for Doc
impl From<TreeReference> for Doc
Source§fn from(tree_ref: TreeReference) -> Doc
fn from(tree_ref: TreeReference) -> Doc
Source§impl TryFrom<&Doc> for DelegatedTreeRef
impl TryFrom<&Doc> for DelegatedTreeRef
Source§impl TryFrom<&Doc> for EncryptedFragment
impl TryFrom<&Doc> for EncryptedFragment
Source§impl TryFrom<&Doc> for EncryptionInfo
impl TryFrom<&Doc> for EncryptionInfo
Source§impl TryFrom<&Doc> for PasswordStoreConfig
impl TryFrom<&Doc> for PasswordStoreConfig
Source§impl TryFrom<&Doc> for Permission
impl TryFrom<&Doc> for Permission
Source§impl TryFrom<&Doc> for PermissionBounds
impl TryFrom<&Doc> for PermissionBounds
Source§impl TryFrom<&Doc> for TreeReference
impl TryFrom<&Doc> for TreeReference
Source§impl TryFrom<Doc> for PasswordStoreConfig
impl TryFrom<Doc> for PasswordStoreConfig
impl Data for Doc
impl Eq for Doc
impl StructuralPartialEq for Doc
Auto Trait Implementations§
impl Freeze for Doc
impl RefUnwindSafe for Doc
impl Send for Doc
impl Sync for Doc
impl Unpin for Doc
impl UnwindSafe for Doc
Blanket Implementations§
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<T> CompatExt for T
impl<T> CompatExt 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<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.