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}