automerge/columnar/column_range/
obj_id.rs1use std::{convert::Infallible, ops::Range};
2
3use crate::{
4 columnar::{
5 encoding::{raw, DecodeColumnError, RleDecoder, RleEncoder, Sink},
6 SpliceError,
7 },
8 convert,
9 types::{ObjId, OpId},
10};
11
12use super::RleRange;
13
14#[derive(Debug, Clone, PartialEq)]
15pub(crate) struct ObjIdRange {
16 actor: RleRange<u64>,
17 counter: RleRange<u64>,
18}
19
20impl ObjIdRange {
21 pub(crate) fn new(actor: RleRange<u64>, counter: RleRange<u64>) -> Option<Self> {
22 if actor.is_empty() || counter.is_empty() {
23 None
24 } else {
25 Some(Self { actor, counter })
26 }
27 }
28
29 pub(crate) fn actor_range(&self) -> &RleRange<u64> {
30 &self.actor
31 }
32
33 pub(crate) fn counter_range(&self) -> &RleRange<u64> {
34 &self.counter
35 }
36
37 pub(crate) fn encode<O, I: Iterator<Item = convert::ObjId<O>> + Clone>(
38 ids: I,
39 out: &mut Vec<u8>,
40 ) -> Option<Self>
41 where
42 O: convert::OpId<usize>,
43 {
44 Self {
46 actor: (0..0).into(),
47 counter: (0..0).into(),
48 }
49 .splice::<_, Infallible, _>(&[], 0..0, ids.map(Ok), out)
50 .unwrap()
51 }
52
53 pub(crate) fn splice<
59 O,
60 E: std::error::Error,
61 I: Iterator<Item = Result<convert::ObjId<O>, E>> + Clone,
62 >(
63 &self,
64 data: &[u8],
65 replace: Range<usize>,
66 ids: I,
67 out: &mut Vec<u8>,
68 ) -> Result<Option<Self>, SpliceError<raw::Error, E>>
69 where
70 O: convert::OpId<usize>,
71 {
72 let actor = self.actor.splice(
73 data,
74 replace.clone(),
75 ids.clone().map(|id| id.map(encoded_actor)),
76 out,
77 )?;
78
79 if actor.is_empty() {
80 return Ok(None);
81 }
82
83 let counter = self.counter.splice(
84 data,
85 replace,
86 ids.map(|i| {
87 i.map(|i| match i {
88 convert::ObjId::Root => None,
89 convert::ObjId::Op(o) => Some(o.counter()),
90 })
91 }),
92 out,
93 )?;
94
95 Ok(Some(Self { actor, counter }))
96 }
97
98 pub(crate) fn iter<'a>(&self, data: &'a [u8]) -> ObjIdIter<'a> {
99 ObjIdIter {
100 actor: self.actor.decoder(data),
101 counter: self.counter.decoder(data),
102 }
103 }
104}
105
106fn encoded_actor<O>(id: convert::ObjId<O>) -> Option<u64>
107where
108 O: convert::OpId<usize>,
109{
110 match id {
111 convert::ObjId::Root => None,
112 convert::ObjId::Op(o) => Some(o.actor() as u64),
113 }
114}
115
116#[derive(Clone)]
117pub(crate) struct ObjIdIter<'a> {
118 actor: RleDecoder<'a, u64>,
119 counter: RleDecoder<'a, u64>,
120}
121
122impl ObjIdIter<'_> {
123 fn try_next(&mut self) -> Result<Option<ObjId>, DecodeColumnError> {
124 let actor = self
125 .actor
126 .next()
127 .transpose()
128 .map_err(|e| DecodeColumnError::decode_raw("actor", e))?;
129 let counter = self
130 .counter
131 .next()
132 .transpose()
133 .map_err(|e| DecodeColumnError::decode_raw("counter", e))?;
134 match (actor, counter) {
135 (None | Some(None), None | Some(None)) => Ok(Some(ObjId::root())),
136 (Some(Some(a)), Some(Some(c))) => Ok(Some(ObjId(OpId::new(c, a as usize)))),
137 (_, Some(Some(0))) => Ok(Some(ObjId::root())),
138 (Some(None) | None, _) => Err(DecodeColumnError::unexpected_null("actor")),
139 (_, Some(None) | None) => Err(DecodeColumnError::unexpected_null("counter")),
140 }
141 }
142}
143
144impl Iterator for ObjIdIter<'_> {
145 type Item = Result<ObjId, DecodeColumnError>;
146
147 fn next(&mut self) -> Option<Self::Item> {
148 self.try_next().transpose()
149 }
150}
151
152pub(crate) struct ObjIdEncoder<S> {
153 actor: RleEncoder<S, u64>,
154 counter: RleEncoder<S, u64>,
155}
156
157impl<S: Sink> ObjIdEncoder<S> {
158 pub(crate) fn append<O>(&mut self, id: convert::ObjId<O>)
159 where
160 O: convert::OpId<usize>,
161 {
162 match id {
163 convert::ObjId::Root => {
164 self.actor.append_null();
165 self.counter.append_null();
166 }
167 convert::ObjId::Op(o) => {
168 self.actor.append_value(o.actor() as u64);
169 self.counter.append_value(o.counter());
170 }
171 }
172 }
173}
174
175impl ObjIdEncoder<Vec<u8>> {
176 pub(crate) fn new() -> Self {
177 Self {
178 actor: RleEncoder::from(Vec::new()),
179 counter: RleEncoder::from(Vec::new()),
180 }
181 }
182
183 pub(crate) fn finish(self, out: &mut Vec<u8>) -> Option<ObjIdRange> {
184 let start = out.len();
185 let (actor, _) = self.actor.finish();
186 out.extend(actor);
187 let actor_end = out.len();
188
189 let (counter, _) = self.counter.finish();
190 out.extend(counter);
191 let counter_end = out.len();
192
193 if start == counter_end {
194 None
195 } else {
196 Some(ObjIdRange {
197 actor: (start..actor_end).into(),
198 counter: (actor_end..counter_end).into(),
199 })
200 }
201 }
202}