1use crate::error::{require, Error, Rule as FormatRule};
4use crate::value::{positive, Slot, Value};
5use crate::wire::{wire_struct, Decoder, Encoder, Wire};
6use coven_merge::{
7 Change, ColumnValue, Operation, RowId, RowState, Timestamp, WriteId, WriteOracle,
8};
9use std::collections::BTreeMap;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct AppliedWrite {
14 pub id: WriteId,
16 pub slot: Slot,
18 pub timestamp: Timestamp,
20 pub read_through: u64,
22}
23wire_struct!(AppliedWrite, id, slot, timestamp, read_through);
24impl AppliedWrite {
25 pub(crate) fn validate(&self) -> Result<(), Error> {
26 positive(self.id.number)?;
27 require(
28 self.timestamp.device() == self.id.device,
29 "applied write timestamp",
30 FormatRule::TimestampDevice,
31 )?;
32 require(
33 self.read_through < self.slot.get(),
34 "applied write read-through",
35 FormatRule::Coverage,
36 )
37 }
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
42pub struct SyncedColumn {
43 pub table: String,
45 pub column: String,
47}
48wire_struct!(SyncedColumn, table => crate::wire::get_name, column => crate::wire::get_name);
49
50#[derive(Clone, Debug, PartialEq, Eq)]
52pub struct MergeRow {
53 pub state: RowState<Value>,
55}
56impl MergeRow {
57 pub(crate) fn put(&self, out: &mut Encoder) -> Result<(), Error> {
58 self.state.row().put(out)?;
59 self.state.generations().put(out)?;
60 self.state.cells().put(out)
61 }
62 pub(crate) fn get<O: WriteOracle>(input: &mut Decoder<'_>, oracle: &O) -> Result<Self, O::Error>
63 where
64 O::Error: From<Error>,
65 {
66 let state = RowState::from_parts(
67 Wire::get(input)?,
68 Wire::get(input)?,
69 crate::wire::get_name_map(input)?,
70 BTreeMap::new(),
71 oracle,
72 )?;
73 Ok(Self { state })
74 }
75 pub(crate) fn validate(&self) -> Result<(), Error> {
76 crate::merge_wire::state(&self.state)?;
77 require(
78 self.state.lost().is_empty(),
79 "merge losses belong in the loss section",
80 FormatRule::Required,
81 )?;
82 Ok(())
83 }
84}
85
86#[derive(Clone, Debug, PartialEq, Eq)]
90pub enum ChangeVerdict {
91 Unjudged,
93 Applied,
95 Excluded(u32),
97 Refused,
99 Dependent(Vec<crate::write_sources::ChangeId>),
101 Ignored(Slot),
103 NotAuthorized(crate::loss::AuthorizationFailure),
106 Derived(Vec<crate::write_sources::ChangeId>),
110}
111impl ChangeVerdict {
112 pub(crate) fn validate(&self) -> Result<(), Error> {
113 match self {
114 Self::Excluded(version) => {
115 require(*version > 0, "breaking schema version", FormatRule::Required)
116 }
117 Self::Ignored(_) => Ok(()),
118 Self::Dependent(sources) | Self::Derived(sources) => {
119 require(!sources.is_empty(), "verdict sources", FormatRule::Required)?;
120 sources.iter().try_for_each(|s| positive(s.write.number))
121 }
122 Self::Unjudged | Self::Applied | Self::Refused | Self::NotAuthorized(_) => Ok(()),
123 }
124 }
125
126 pub fn retained(&self) -> bool {
128 matches!(self, Self::Unjudged | Self::Applied | Self::Derived(_))
129 }
130}
131impl Wire for ChangeVerdict {
132 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
133 match self {
134 Self::Unjudged => 0u8.put(out),
135 Self::Applied => 1u8.put(out),
136 Self::Excluded(version) => {
137 2u8.put(out)?;
138 version.put(out)
139 }
140 Self::Refused => 3u8.put(out),
141 Self::Dependent(sources) => {
142 4u8.put(out)?;
143 sources.put(out)
144 }
145 Self::Ignored(entry) => {
146 5u8.put(out)?;
147 entry.put(out)
148 }
149 Self::NotAuthorized(reason) => {
150 6u8.put(out)?;
151 reason.put(out)
152 }
153 Self::Derived(causes) => {
154 7u8.put(out)?;
155 causes.put(out)
156 }
157 }
158 }
159 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
160 match u8::get(input)? {
161 0 => Ok(Self::Unjudged),
162 1 => Ok(Self::Applied),
163 2 => Ok(Self::Excluded(Wire::get(input)?)),
164 3 => Ok(Self::Refused),
165 4 => Ok(Self::Dependent(Wire::get(input)?)),
166 5 => Ok(Self::Ignored(Wire::get(input)?)),
167 6 => Ok(Self::NotAuthorized(Wire::get(input)?)),
168 7 => Ok(Self::Derived(Wire::get(input)?)),
169 tag => Err(Error::UnknownTag { field: "change verdict", tag }),
170 }
171 }
172}
173
174#[derive(Clone, Debug, PartialEq, Eq)]
179pub enum KeptValue {
180 Value(Value),
182 Digest([u8; 32]),
184}
185impl KeptValue {
186 pub fn digest(value: &Value) -> Result<[u8; 32], Error> {
188 let mut out = Encoder::new();
189 value.put(&mut out)?;
190 Ok(coven_crypto::kept_value_digest(&out.bytes))
191 }
192
193 pub fn matches(&self, value: &Value) -> Result<bool, Error> {
195 Ok(match self {
196 Self::Value(kept) => kept == value,
197 Self::Digest(digest) => Self::digest(value)? == *digest,
198 })
199 }
200}
201
202impl Wire for ColumnValue<KeptValue> {
205 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
206 match &self.value {
207 KeptValue::Value(value) => {
208 0u8.put(out)?;
209 value.put(out)?;
210 self.parents.put(out)
211 }
212 KeptValue::Digest(digest) => {
213 1u8.put(out)?;
214 digest.put(out)
215 }
216 }
217 }
218 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
219 match u8::get(input)? {
220 0 => {
221 Ok(Self { value: KeptValue::Value(Wire::get(input)?), parents: Wire::get(input)? })
222 }
223 1 => Ok(Self { value: KeptValue::Digest(Wire::get(input)?), parents: BTreeMap::new() }),
224 tag => Err(Error::UnknownTag { field: "kept value", tag }),
225 }
226 }
227}
228
229#[derive(Clone, Debug, PartialEq, Eq)]
234pub enum KeptRecord {
235 Change(KeptChange),
237 Execution {
239 row: RowId,
241 steps: u32,
243 },
244}
245
246#[derive(Clone, Debug, PartialEq, Eq)]
248pub struct KeptChange {
249 pub row: RowId,
251 pub change: Change<KeptValue>,
254 pub creator: Option<crate::write_sources::ChangeId>,
256 pub steps: u32,
258}
259
260impl Wire for Change<KeptValue> {
261 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
262 self.generation.put(out)?;
263 match &self.operation {
264 Operation::Insert(columns) => {
265 0u8.put(out)?;
266 columns.put(out)
267 }
268 Operation::Update(columns) => {
269 1u8.put(out)?;
270 columns.put(out)
271 }
272 Operation::Delete => 2u8.put(out),
273 }
274 }
275 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
276 let generation = Wire::get(input)?;
277 let operation = match u8::get(input)? {
278 0 => Operation::Insert(crate::wire::get_name_map(input)?),
279 1 => Operation::Update(crate::wire::get_name_map(input)?),
280 2 => Operation::Delete,
281 tag => return Err(Error::UnknownTag { field: "row operation", tag }),
282 };
283 Ok(Self { generation, operation })
284 }
285}
286
287impl Wire for KeptRecord {
288 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
289 match self {
290 Self::Change(change) => {
291 0u8.put(out)?;
292 change.row.put(out)?;
293 change.change.put(out)?;
294 change.creator.put(out)?;
295 change.steps.put(out)
296 }
297 Self::Execution { row, steps } => {
298 1u8.put(out)?;
299 row.put(out)?;
300 steps.put(out)
301 }
302 }
303 }
304 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
305 match u8::get(input)? {
306 0 => Ok(Self::Change(KeptChange {
307 row: Wire::get(input)?,
308 change: Wire::get(input)?,
309 creator: Wire::get(input)?,
310 steps: Wire::get(input)?,
311 })),
312 1 => Ok(Self::Execution { row: Wire::get(input)?, steps: Wire::get(input)? }),
313 tag => Err(Error::UnknownTag { field: "kept record", tag }),
314 }
315 }
316}
317
318impl KeptRecord {
319 pub fn keep(
322 record: crate::write::PartRecord<'_>,
323 reference: impl Fn(&str) -> bool,
324 ) -> Result<Self, Error> {
325 let steps = |execution: &crate::write::Execution| {
327 crate::error::bound(execution.steps.len(), crate::wire::MAX_ITEMS, "collection")
328 .map(|()| execution.steps.len() as u32)
329 };
330 Ok(match record {
331 crate::write::PartRecord::Change(change) => {
332 let kept = |columns: &BTreeMap<String, ColumnValue<Value>>| {
333 columns
334 .iter()
335 .map(|(name, cell)| {
336 let kept = if reference(name) {
337 ColumnValue {
338 value: KeptValue::Value(cell.value.clone()),
339 parents: cell.parents.clone(),
340 }
341 } else {
342 ColumnValue {
343 value: KeptValue::Digest(KeptValue::digest(&cell.value)?),
344 parents: BTreeMap::new(),
345 }
346 };
347 Ok((name.clone(), kept))
348 })
349 .collect::<Result<BTreeMap<_, _>, Error>>()
350 };
351 let operation = match &change.change.operation {
352 Operation::Insert(columns) => Operation::Insert(kept(columns)?),
353 Operation::Update(columns) => Operation::Update(kept(columns)?),
354 Operation::Delete => Operation::Delete,
355 };
356 Self::Change(KeptChange {
357 row: change.row.clone(),
358 change: Change { generation: change.change.generation, operation },
359 creator: change.creator.clone(),
360 steps: steps(&change.execution)?,
361 })
362 }
363 crate::write::PartRecord::Execution(execution) => {
364 Self::Execution { row: execution.row.clone(), steps: steps(&execution.execution)? }
365 }
366 })
367 }
368
369 pub fn conforms(&self, reference: impl Fn(&str) -> bool) -> bool {
372 match self {
373 Self::Change(change) => match &change.change.operation {
374 Operation::Insert(columns) | Operation::Update(columns) => {
375 columns.iter().all(|(name, cell)| {
376 matches!(cell.value, KeptValue::Value(_)) == reference(name)
377 })
378 }
379 Operation::Delete => true,
380 },
381 Self::Execution { .. } => true,
382 }
383 }
384
385 pub fn row(&self) -> &RowId {
387 match self {
388 Self::Change(change) => &change.row,
389 Self::Execution { row, .. } => row,
390 }
391 }
392
393 pub fn encode(&self) -> Result<Vec<u8>, Error> {
395 self.validate()?;
396 let mut out = Encoder::new();
397 self.put(&mut out)?;
398 Ok(out.bytes)
399 }
400
401 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
403 let mut input = Decoder::new(bytes)?;
404 let record = Self::get(&mut input)?;
405 input.finish()?;
406 record.validate()?;
407 Ok(record)
408 }
409
410 pub(crate) fn validate(&self) -> Result<(), Error> {
411 crate::value::row(self.row())?;
412 match self {
413 Self::Execution { steps, .. } => {
414 require(*steps > 0, "execution steps", FormatRule::Required)
415 }
416 Self::Change(change) => {
417 change.change.validate(&change.row).map_err(Error::Merge)?;
418 if let Operation::Insert(columns) | Operation::Update(columns) =
419 &change.change.operation
420 {
421 require(!columns.is_empty(), "changed columns", FormatRule::Required)?;
422 for (name, cell) in columns {
423 crate::value::name(name)?;
424 if let KeptValue::Value(value) = &cell.value {
425 value.validate()?;
426 }
427 crate::merge_wire::parents(&cell.parents)?;
428 }
429 }
430 if let Some(creator) = &change.creator {
431 require(
433 matches!(change.change.operation, Operation::Insert(_))
434 && change.change.generation == 0
435 && creator.row.table == change.row.table
436 && creator.row.key == change.row.key
437 && creator.row.audience != change.row.audience,
438 "copied creation",
439 FormatRule::ColumnOperation,
440 )?;
441 positive(creator.write.number)?;
442 }
443 Ok(())
444 }
445 }
446 }
447}
448
449#[derive(Clone, Debug, PartialEq, Eq)]
454pub struct AuthoredPart {
455 pub header: crate::write::WriteHeader,
457}
458wire_struct!(AuthoredPart, header);
459
460#[derive(Clone, Debug, PartialEq, Eq)]
463pub struct AuthoredChange {
464 pub record: KeptRecord,
466 pub verdict: ChangeVerdict,
468 pub stop: Option<Slot>,
471}
472wire_struct!(AuthoredChange, record, verdict, stop);
473impl AuthoredChange {
474 pub fn id(&self, header: &crate::write::WriteHeader) -> crate::write_sources::ChangeId {
476 crate::write_sources::ChangeId { write: header.position, row: self.record.row().clone() }
477 }
478
479 pub(crate) fn validate(&self) -> Result<(), Error> {
480 self.record.validate()?;
481 self.verdict.validate()
482 }
483
484 pub(crate) fn validate_in(&self, header: &crate::write::WriteHeader) -> Result<(), Error> {
487 match &self.verdict {
488 ChangeVerdict::Dependent(sources) => {
489 for source in sources {
490 require(
491 crate::loss::dependency_source(self.record.row(), header.position, source),
492 "dependency source row",
493 FormatRule::Required,
494 )?;
495 }
496 Ok(())
497 }
498 ChangeVerdict::Derived(causes) => require(
499 causes.iter().all(|cause| cause.write == header.position),
500 "derivation cause write",
501 FormatRule::Required,
502 ),
503 _ => Ok(()),
504 }
505 }
506}
507
508#[derive(Clone, Debug, PartialEq, Eq)]
510pub enum AuthoredRecord {
511 Part(AuthoredPart),
513 Change(AuthoredChange),
515}
516impl Wire for AuthoredRecord {
517 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
518 match self {
519 Self::Part(part) => {
520 0u8.put(out)?;
521 part.put(out)
522 }
523 Self::Change(change) => {
524 1u8.put(out)?;
525 change.put(out)
526 }
527 }
528 }
529 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
530 match u8::get(input)? {
531 0 => Ok(Self::Part(Wire::get(input)?)),
532 1 => Ok(Self::Change(Wire::get(input)?)),
533 tag => Err(Error::UnknownTag { field: "authored record", tag }),
534 }
535 }
536}