1use crate::{
6 Admission, AppendError, CollectionLimits, CollisionVerdict, Crdt, DecodeError, DecodeLimits,
7 EventLog, Record, RecordCollision, RecordId, VersionVector, WireDecode, WireEncode, WireError,
8 WireSchema,
9};
10use alloc::vec::Vec;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum ReplicaError {
15 RecordDecode(WireError),
16 LogDecode(DecodeError),
17 LogEncode(WireError),
18 Append(AppendError),
19 ReportDecode(DecodeError),
21 ReportEncode(WireError),
22}
23impl core::fmt::Display for ReplicaError {
24 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25 match self {
26 Self::RecordDecode(e) | Self::LogEncode(e) | Self::LogDecode(DecodeError::Wire(e)) => {
27 e.fmt(f)
28 }
29 Self::LogDecode(DecodeError::RecordLimitExceeded { max_records }) => {
30 write!(f, "RecordLimitExceeded: {max_records}")
31 }
32 Self::LogDecode(DecodeError::DefaultRecordLimitExceeded { max_records }) => {
33 write!(f, "RecordLimitExceeded: {max_records}; pass DecodeLimits::UNLIMITED to reopen")
34 }
35 Self::Append(e) => e.fmt(f),
36 Self::ReportDecode(DecodeError::Wire(e)) => {
37 write!(f, "failed to decode collision report: {e}")
38 }
39 Self::ReportDecode(DecodeError::RecordLimitExceeded { max_records }) => write!(
40 f,
41 "failed to decode collision report: RecordLimitExceeded: {max_records}"
42 ),
43 Self::ReportDecode(DecodeError::DefaultRecordLimitExceeded { max_records }) => write!(
44 f,
45 "failed to decode collision report: RecordLimitExceeded: {max_records}; pass DecodeLimits::UNLIMITED to reopen"
46 ),
47 Self::ReportEncode(e) => write!(f, "failed to encode collision report: {e}"),
48 }
49 }
50}
51impl core::error::Error for ReplicaError {
52 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
53 match self {
54 Self::RecordDecode(e) | Self::LogEncode(e) | Self::LogDecode(DecodeError::Wire(e)) => {
55 Some(e)
56 }
57 Self::ReportDecode(DecodeError::Wire(e)) | Self::ReportEncode(e) => Some(e),
58 Self::Append(e) => Some(e),
59 Self::LogDecode(DecodeError::RecordLimitExceeded { .. })
60 | Self::ReportDecode(DecodeError::RecordLimitExceeded { .. })
61 | Self::LogDecode(DecodeError::DefaultRecordLimitExceeded { .. })
62 | Self::ReportDecode(DecodeError::DefaultRecordLimitExceeded { .. }) => None,
63 }
64 }
65}
66pub struct Replica<C: Crdt> {
69 state: C,
70 log: EventLog<C::Delta>,
71}
72impl<C: Crdt> Replica<C> {
73 pub fn new(state: C) -> Self {
74 let log = EventLog::for_crdt(&state);
75 Self { state, log }
76 }
77 pub fn state(&self) -> &C {
78 &self.state
79 }
80 pub fn log(&self) -> &EventLog<C::Delta> {
81 &self.log
82 }
83 pub fn version(&self) -> &VersionVector {
84 self.log.version()
85 }
86 pub fn since(&self, peer: &VersionVector) -> Vec<Record<C::Delta>>
87 where
88 C::Delta: Clone,
89 {
90 self.log.since(peer)
91 }
92 pub fn admit(&mut self, record: Record<C::Delta>) -> Admission
95 where
96 C::Delta: Clone + PartialEq,
97 {
98 self.log
99 .admit_with(&mut self.state, record, |state, delta| {
100 state.apply_delta(delta.clone())
101 })
102 }
103 pub fn append(&mut self, author: u64, delta: C::Delta) -> Result<Record<C::Delta>, ReplicaError>
104 where
105 C::Delta: Clone + PartialEq,
106 {
107 let id = self
108 .log
109 .append_with(&mut self.state, author, delta.clone(), |state, delta| {
110 state.apply_delta(delta.clone())
111 })
112 .map_err(ReplicaError::Append)?;
113 Ok(Record { id, delta })
114 }
115 pub fn inspect_record_bytes(
117 bytes: &[u8],
118 limits: CollectionLimits,
119 ) -> Result<Record<C::Delta>, ReplicaError>
120 where
121 C::Delta: WireDecode,
122 {
123 Record::from_wire_bytes_with_collection_limits(bytes, limits)
124 .map_err(ReplicaError::RecordDecode)
125 }
126 pub fn merge_record_bytes(
127 &mut self,
128 bytes: &[u8],
129 limits: CollectionLimits,
130 ) -> Result<Admission, ReplicaError>
131 where
132 C::Delta: Clone + PartialEq + WireDecode,
133 {
134 Ok(self.admit(Self::inspect_record_bytes(bytes, limits)?))
135 }
136 pub fn decode_log_bytes(
138 &self,
139 bytes: &[u8],
140 limits: DecodeLimits,
141 ) -> Result<Vec<Record<C::Delta>>, ReplicaError>
142 where
143 C::Delta: Clone + PartialEq + WireDecode + WireSchema,
144 {
145 EventLog::records_from_wire_bytes_for_with_limits(bytes, &self.state, limits)
146 .map_err(ReplicaError::LogDecode)
147 }
148 pub fn merge_log_bytes(
149 &mut self,
150 bytes: &[u8],
151 limits: DecodeLimits,
152 ) -> Result<Vec<Admission>, ReplicaError>
153 where
154 C::Delta: Clone + PartialEq + WireDecode + WireSchema,
155 {
156 let records = self.decode_log_bytes(bytes, limits)?;
157 Ok(records
158 .into_iter()
159 .map(|record| self.admit(record))
160 .collect())
161 }
162 pub fn log_bytes(&self) -> Result<Vec<u8>, ReplicaError>
163 where
164 C::Delta: WireEncode + WireSchema,
165 {
166 self.log.to_wire_bytes().map_err(ReplicaError::LogEncode)
167 }
168 pub fn restore(mut state: C, bytes: &[u8], limits: DecodeLimits) -> Result<Self, ReplicaError>
170 where
171 C::Delta: Clone + PartialEq + WireDecode + WireSchema,
172 {
173 let log = EventLog::from_wire_bytes_for_with_limits(bytes, &state, limits)
174 .map_err(ReplicaError::LogDecode)?;
175 for record in log.records() {
176 state.apply_delta(record.delta.clone());
177 }
178 Ok(Self { state, log })
179 }
180
181 pub fn collisions(&self) -> Vec<RecordCollision<C::Delta>>
185 where
186 C::Delta: Clone,
187 {
188 self.log.collisions()
189 }
190 pub fn collision_report_bytes(&self) -> Result<Option<Vec<u8>>, ReplicaError>
193 where
194 C::Delta: Clone + WireEncode + WireSchema,
195 {
196 self.log
197 .collision_report_bytes()
198 .map_err(ReplicaError::ReportEncode)
199 }
200 pub fn merge_collision_report_bytes(
203 &mut self,
204 bytes: &[u8],
205 limits: DecodeLimits,
206 ) -> Result<Vec<(RecordId, CollisionVerdict)>, ReplicaError>
207 where
208 C::Delta: PartialEq + WireDecode + WireSchema,
209 {
210 self.log
211 .merge_collision_report_bytes(bytes, limits)
212 .map_err(ReplicaError::ReportDecode)
213 }
214}