automerge/
read.rs

1use crate::{
2    cursor::{CursorPosition, MoveCursor},
3    error::AutomergeError,
4    exid::ExId,
5    hydrate,
6    iter::{Keys, ListRange, MapRange, Spans, Values},
7    marks::{Mark, MarkSet},
8    parents::Parents,
9    Change, ChangeHash, Cursor, ObjType, Prop, TextEncoding, Value,
10};
11
12use std::{collections::HashMap, ops::RangeBounds};
13
14/// Methods for reading values from an automerge document
15///
16/// Many of the methods on this trait have an alternate `*_at` version which
17/// takes an additional argument of `&[ChangeHash]`. This allows you to retrieve
18/// the value at a particular point in the document history identified by the
19/// given change hashes.
20pub trait ReadDoc {
21    /// Get the parents of an object in the document tree.
22    ///
23    /// See the documentation for [`Parents`] for more details.
24    ///
25    /// ### Errors
26    ///
27    /// Returns an error when the id given is not the id of an object in this document.
28    /// This function does not get the parents of scalar values contained within objects.
29    ///
30    /// ### Experimental
31    ///
32    /// This function may in future be changed to allow getting the parents from the id of a scalar
33    /// value.
34    fn parents<O: AsRef<ExId>>(&self, obj: O) -> Result<Parents<'_>, AutomergeError>;
35
36    /// Get the parents of the object `obj` as at `heads`
37    ///
38    /// See [`Self::parents()`]
39    fn parents_at<O: AsRef<ExId>>(
40        &self,
41        obj: O,
42        heads: &[ChangeHash],
43    ) -> Result<Parents<'_>, AutomergeError>;
44
45    /// Get the keys of the object `obj`.
46    ///
47    /// For a map this returns the keys of the map.
48    /// For a list this returns the element ids (opids) encoded as strings.
49    fn keys<O: AsRef<ExId>>(&self, obj: O) -> Keys<'_>;
50
51    /// Get the keys of the object `obj` as at `heads`
52    ///
53    /// See [`Self::keys()`]
54    fn keys_at<O: AsRef<ExId>>(&self, obj: O, heads: &[ChangeHash]) -> Keys<'_>;
55
56    /// Iterate over the keys and values of the map `obj` in the given range.
57    ///
58    /// If the object correspoding to `obj` is a list then this will return an empty iterator
59    ///
60    /// The returned iterator yields `(key, value, exid)` tuples, where the
61    /// third element is the ID of the operation which created the value.
62    fn map_range<'a, O: AsRef<ExId>, R: RangeBounds<String> + 'a>(
63        &'a self,
64        obj: O,
65        range: R,
66    ) -> MapRange<'a, R>;
67
68    /// Iterate over the keys and values of the map `obj` in the given range as
69    /// at `heads`
70    ///
71    /// If the object correspoding to `obj` is a list then this will return an empty iterator
72    ///
73    /// The returned iterator yields `(key, value, exid)` tuples, where the
74    /// third element is the ID of the operation which created the value.
75    ///
76    /// See [`Self::map_range()`]
77    fn map_range_at<'a, O: AsRef<ExId>, R: RangeBounds<String> + 'a>(
78        &'a self,
79        obj: O,
80        range: R,
81        heads: &[ChangeHash],
82    ) -> MapRange<'a, R>;
83
84    /// Iterate over the indexes and values of the list or text `obj` in the given range.
85    ///
86    /// The reuturned iterator yields `(index, value, exid)` tuples, where the third
87    /// element is the ID of the operation which created the value.
88    fn list_range<O: AsRef<ExId>, R: RangeBounds<usize>>(
89        &self,
90        obj: O,
91        range: R,
92    ) -> ListRange<'_, R>;
93
94    /// Iterate over the indexes and values of the list or text `obj` in the given range as at `heads`
95    ///
96    /// The returned iterator yields `(index, value, exid)` tuples, where the third
97    /// element is the ID of the operation which created the value.
98    ///
99    /// See [`Self::list_range()`]
100    fn list_range_at<O: AsRef<ExId>, R: RangeBounds<usize>>(
101        &self,
102        obj: O,
103        range: R,
104        heads: &[ChangeHash],
105    ) -> ListRange<'_, R>;
106
107    /// Iterate over the values in a map, list, or text object
108    ///
109    /// The returned iterator yields `(value, exid)` tuples, where the second element
110    /// is the ID of the operation which created the value.
111    fn values<O: AsRef<ExId>>(&self, obj: O) -> Values<'_>;
112
113    /// Iterate over the values in a map, list, or text object as at `heads`
114    ///
115    /// The returned iterator yields `(value, exid)` tuples, where the second element
116    /// is the ID of the operation which created the value.
117    ///
118    /// See [`Self::values()`]
119    fn values_at<O: AsRef<ExId>>(&self, obj: O, heads: &[ChangeHash]) -> Values<'_>;
120
121    /// Get the length of the given object.
122    ///
123    /// If the given object is not in this document this method will return `0`
124    fn length<O: AsRef<ExId>>(&self, obj: O) -> usize;
125
126    /// Get the length of the given object as at `heads`
127    ///
128    /// If the given object is not in this document this method will return `0`
129    ///
130    /// See [`Self::length()`]
131    fn length_at<O: AsRef<ExId>>(&self, obj: O, heads: &[ChangeHash]) -> usize;
132
133    /// Get the type of this object, if it is an object.
134    fn object_type<O: AsRef<ExId>>(&self, obj: O) -> Result<ObjType, AutomergeError>;
135
136    /// Get all marks on a current sequence
137    fn marks<O: AsRef<ExId>>(&self, obj: O) -> Result<Vec<Mark<'_>>, AutomergeError>;
138
139    /// Get all marks on a sequence at a given heads
140    fn marks_at<O: AsRef<ExId>>(
141        &self,
142        obj: O,
143        heads: &[ChangeHash],
144    ) -> Result<Vec<Mark<'_>>, AutomergeError>;
145
146    fn get_marks<O: AsRef<ExId>>(
147        &self,
148        obj: O,
149        index: usize,
150        heads: Option<&[ChangeHash]>,
151    ) -> Result<MarkSet, AutomergeError>;
152
153    /// Get the string represented by the given text object.
154    fn text<O: AsRef<ExId>>(&self, obj: O) -> Result<String, AutomergeError>;
155
156    /// Get the string represented by the given text object as at `heads`, see
157    /// [`Self::text()`]
158    fn text_at<O: AsRef<ExId>>(
159        &self,
160        obj: O,
161        heads: &[ChangeHash],
162    ) -> Result<String, AutomergeError>;
163
164    /// Return the sequence of text and block markers in the text object `obj`
165    fn spans<O: AsRef<ExId>>(&self, obj: O) -> Result<Spans<'_>, AutomergeError>;
166
167    /// Return the sequence of text and block markers in the text object `obj` as at `heads`
168    fn spans_at<O: AsRef<ExId>>(
169        &self,
170        obj: O,
171        heads: &[ChangeHash],
172    ) -> Result<Spans<'_>, AutomergeError>;
173
174    /// Obtain the stable address (Cursor) for a [`usize`] position in a Sequence (either [`ObjType::List`] or [`ObjType::Text`]).
175    ///
176    /// **This is equivalent to [`Self::get_cursor_moving()`] with `move_cursor` = `MoveCursor::After`.**
177    fn get_cursor<O: AsRef<ExId>, I: Into<CursorPosition>>(
178        &self,
179        obj: O,
180        position: I,
181        at: Option<&[ChangeHash]>,
182    ) -> Result<Cursor, AutomergeError>;
183
184    /// Obtain the stable address (Cursor) for a [`usize`] position in a Sequence (either [`ObjType::List`] or [`ObjType::Text`]).
185    ///
186    /// # Use cases
187    /// - User cursor tracking, to maintain contextual position while merging remote changes.
188    /// - Indexing sentences in a text field.
189    ///
190    /// # Cursor movement
191    ///
192    /// `move_cursor` determines how the cursor resolves its position if the item originally referenced at the given position is **removed** in later versions of the document. See [`MoveCursor`] for more details.
193    ///
194    /// # Start/end cursors
195    /// If you'd like a cursor which follows the start (`position = 0`) or end (`position = sequence.length`) of the sequence, pass `CursorPosition::Start` or `CursorPosition::End` respectively.
196    ///
197    /// Conceptually, start cursors behaves like a cursor pointed an index of `-1`. End cursors behave like a cursor pointed at `sequence.length`.
198    ///
199    /// Note that `move_cursor` does not affect start/end cursors, as the start/end positions can never be removed.
200    ///
201    /// To translate a cursor into a position, see [`Self::get_cursor_position()`].
202    fn get_cursor_moving<O: AsRef<ExId>, I: Into<CursorPosition>>(
203        &self,
204        obj: O,
205        position: I,
206        at: Option<&[ChangeHash]>,
207        move_cursor: MoveCursor,
208    ) -> Result<Cursor, AutomergeError>;
209
210    /// Translate Cursor in a Sequence into an absolute position of type [`usize`].
211    ///
212    /// Applicable only for Sequences (either [`ObjType::List`] or [`ObjType::Text`]).
213    ///
214    /// To reverse the operation, see [`Self::get_cursor()`].
215    fn get_cursor_position<O: AsRef<ExId>>(
216        &self,
217        obj: O,
218        cursor: &Cursor,
219        at: Option<&[ChangeHash]>,
220    ) -> Result<usize, AutomergeError>;
221
222    /// Get a value out of the document.
223    ///
224    /// This returns a tuple of `(value, object ID)`. This is for two reasons:
225    ///
226    /// 1. If `value` is an object (represented by [`Value::Object`]) then the ID
227    ///    is the ID of that object. This can then be used to retrieve nested
228    ///    values from the document.
229    /// 2. Even if `value` is a scalar, the ID represents the operation which
230    ///    created the value. This is useful if there are conflicting values for
231    ///    this key as each value is tagged with the ID.
232    ///
233    /// In the case of a key which has conflicting values, this method will
234    /// return a single arbitrarily chosen value. This value will be chosen
235    /// deterministically on all nodes. If you want to get all the values for a
236    /// key use [`Self::get_all()`].
237    fn get<O: AsRef<ExId>, P: Into<Prop>>(
238        &self,
239        obj: O,
240        prop: P,
241    ) -> Result<Option<(Value<'_>, ExId)>, AutomergeError>;
242
243    /// Get the value of the given key as at `heads`, see [`Self::get()`]
244    fn get_at<O: AsRef<ExId>, P: Into<Prop>>(
245        &self,
246        obj: O,
247        prop: P,
248        heads: &[ChangeHash],
249    ) -> Result<Option<(Value<'_>, ExId)>, AutomergeError>;
250
251    fn hydrate<O: AsRef<ExId>>(
252        &self,
253        obj: O,
254        heads: Option<&[ChangeHash]>,
255    ) -> Result<hydrate::Value, AutomergeError>;
256
257    /// Get all conflicting values out of the document at this prop that conflict.
258    ///
259    /// If there are multiple conflicting values for a given key this method
260    /// will return all of them, with each value tagged by the ID of the
261    /// operation which created it.
262    fn get_all<O: AsRef<ExId>, P: Into<Prop>>(
263        &self,
264        obj: O,
265        prop: P,
266    ) -> Result<Vec<(Value<'_>, ExId)>, AutomergeError>;
267
268    /// Get all possibly conflicting values for a key as at `heads`
269    ///
270    /// See [`Self::get_all()`]
271    fn get_all_at<O: AsRef<ExId>, P: Into<Prop>>(
272        &self,
273        obj: O,
274        prop: P,
275        heads: &[ChangeHash],
276    ) -> Result<Vec<(Value<'_>, ExId)>, AutomergeError>;
277
278    /// Get the hashes of the changes in this document that aren't transitive dependencies of the
279    /// given `heads`.
280    fn get_missing_deps(&self, heads: &[ChangeHash]) -> Vec<ChangeHash>;
281
282    /// Get a change by its hash.
283    fn get_change_by_hash(&self, hash: &ChangeHash) -> Option<&Change>;
284
285    /// Return some statistics about the document
286    fn stats(&self) -> Stats;
287
288    fn text_encoding(&self) -> TextEncoding;
289}
290
291pub(crate) trait ReadDocInternal: ReadDoc {
292    /// Produce a map from object ID to path for all visible objects in this doc
293    fn live_obj_paths(&self) -> HashMap<ExId, Vec<(ExId, Prop)>>;
294}
295
296/// Statistics about the document
297///
298/// This is returned by [`ReadDoc::stats()`]
299#[derive(Debug, Clone, Copy, PartialEq, Eq)]
300pub struct Stats {
301    /// The number of operations in the document
302    pub num_ops: u64,
303    /// The number of changes in the change graph for the document
304    pub num_changes: u64,
305}