///|
/// Encode integrated changes only. Pending blocks and early deletions are omitted.
pub fn Doc::encode_diff_v1(self : Doc, remote : StateVector) -> Bytes {
self.encode_document(remote, false)
}
///|
// Keep the public fallible signature for source compatibility.
#warnings("-unused_error_type")
pub fn Doc::encode_diff_v2(
self : Doc,
remote : StateVector,
) -> Bytes raise DecodeError {
self.encode_document(remote, false, v2=true)
}
///|
/// Remove unresolved blocks and deletions, returning an update that can be saved
/// and applied later. Already integrated changes, including sparse ones, remain.
pub fn Doc::prune_pending(self : Doc) -> Update? {
self.with_mutation(fn() {
let known = self.integrated_ids()
let all_deletions = []
for client, ranges in self.deletes {
for (start, end) in ranges {
all_deletions.push((client, start, end))
}
}
let pending_deletions = IdSet(ranges=all_deletions).diff(known)
if self.pending.is_empty() && pending_deletions.is_empty() {
return None
}
let result = Update::from_blocks(self.pending, pending_deletions)
self.pending.clear()
let retained = IdSet(ranges=all_deletions).intersect(known)
self.deletes.clear()
for (client, start, end) in retained.ranges() {
self.add_delete(client, start, end)
}
Some(result)
})
}
///|
fn Doc::integrated_ids(self : Doc) -> IdSet {
let ranges = []
for client, blocks in self.clients {
for item in blocks {
ranges.push(
(
client,
item.id.clock,
item.id.clock + item.content.length().reinterpret_as_uint(),
),
)
}
}
IdSet(ranges~)
}
///|
/// Whether unresolved blocks or early deletions are queued, matching Yrs's
/// pending-store check. has_missing_updates additionally detects clock gaps.
pub fn Doc::has_pending_updates(self : Doc) -> Bool {
if !self.pending.is_empty() {
return true
}
let deleted = []
for client, ranges in self.deletes {
for (start, end) in ranges {
deleted.push((client, start, end))
}
}
!IdSet(ranges=deleted).diff(self.integrated_ids()).is_empty()
}
///|
/// Inspect unresolved item blocks without draining or retrying them. Pending
/// deletions are exposed separately by pending_delete_set, as in Yrs Store.
pub fn Doc::pending_update(self : Doc) -> Update? {
if self.pending.is_empty() {
return None
}
Some(Update::from_blocks(self.pending, IdSet()))
}
///|
/// Return an owned copy of deletion ranges whose items have not arrived yet.
/// Reading this metadata does not start a transaction or notify observers.
pub fn Doc::pending_delete_set(self : Doc) -> IdSet? {
let ranges = []
for client, entries in self.deletes {
for (start, end) in entries {
ranges.push((client, start, end))
}
}
let pending = IdSet(ranges~).diff(self.integrated_ids())
if pending.is_empty() {
None
} else {
Some(pending)
}
}