1use crate::error::{require, Error, Rule};
7use crate::value::{name, positive, row, Value};
8use crate::wire::{wire_struct, Decoder, Encoder, Wire};
9use crate::write_sources::ChangeId;
10use coven_merge::{Audience, Change, Operation, RowId, Timestamp, WriteId};
11use std::collections::BTreeMap;
12
13#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct WriteHeader {
16 pub position: WriteId,
18 pub timestamp: Timestamp,
20 pub read_through: u64,
22 pub schema_version: u32,
24 pub disposition: WriteDisposition,
26}
27wire_struct!(WriteHeader, position, timestamp, read_through, schema_version, disposition);
28impl WriteHeader {
29 pub(crate) fn validate(&self) -> Result<(), Error> {
30 positive(self.position.number)?;
31 require(
32 self.timestamp.device() == self.position.device,
33 "write timestamp",
34 Rule::TimestampDevice,
35 )?;
36 Ok(())
37 }
38
39 pub(crate) fn validate_parts<'a>(
43 &self,
44 audiences: impl ExactSizeIterator<Item = &'a Audience>,
45 ) -> Result<(), Error> {
46 self.validate()?;
47 self.disposition.validate_parts(audiences.len())?;
48 let mut previous = None;
49 for audience in audiences {
50 require(previous.is_none_or(|p| p < audience), "write parts", Rule::Order)?;
51 previous = Some(audience);
52 }
53 Ok(())
54 }
55}
56
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum WriteDisposition {
61 Apply,
63 Migration,
65}
66impl WriteDisposition {
67 pub(crate) fn validate_parts(self, count: usize) -> Result<(), Error> {
68 match self {
69 Self::Migration => require(count == 0, "migration write parts", Rule::StreamLength),
70 Self::Apply => require(count > 0, "write parts", Rule::Required),
71 }
72 }
73}
74impl Wire for WriteDisposition {
75 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
76 match self {
77 Self::Apply => 0u8.put(out),
78 Self::Migration => 2u8.put(out),
79 }
80 }
81 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
82 match u8::get(input)? {
83 0 => Ok(Self::Apply),
84 2 => Ok(Self::Migration),
85 tag => Err(Error::UnknownTag { field: "write disposition", tag }),
86 }
87 }
88}
89
90impl Wire for Operation<Value> {
91 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
92 match self {
93 Self::Insert(values) => {
94 0u8.put(out)?;
95 values.put(out)
96 }
97 Self::Update(values) => {
98 1u8.put(out)?;
99 values.put(out)
100 }
101 Self::Delete => 2u8.put(out),
102 }
103 }
104 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
105 match u8::get(input)? {
106 0 => Ok(Self::Insert(crate::wire::get_name_map(input)?)),
107 1 => Ok(Self::Update(crate::wire::get_name_map(input)?)),
108 2 => Ok(Self::Delete),
109 tag => Err(Error::UnknownTag { field: "row operation", tag }),
110 }
111 }
112}
113wire_struct!(Change<Value>, generation, operation);
114
115#[derive(Clone, Debug, PartialEq, Eq)]
118pub struct RowChange {
119 pub row: RowId,
121 pub change: Change<Value>,
123 pub old: BTreeMap<String, Value>,
127 pub sources: crate::write_sources::WriteSources,
129 pub creator: Option<ChangeId>,
132 pub execution: Execution,
137}
138impl Wire for RowChange {
139 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
140 self.row.put(out)?;
141 self.change.put(out)?;
142 if matches!(self.change.operation, Operation::Delete) {
143 self.old.put(out)?;
144 }
145 self.sources.put(out)?;
146 self.creator.put(out)?;
147 self.execution.put_against(out, Some(&self.change))
148 }
149 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
150 let row = Wire::get(input)?;
151 let change: Change<Value> = Wire::get(input)?;
152 let old = match change.operation {
153 Operation::Delete => crate::wire::get_name_map(input)?,
154 Operation::Insert(_) | Operation::Update(_) => BTreeMap::new(),
155 };
156 let sources = Wire::get(input)?;
157 let creator = Wire::get(input)?;
158 let execution = Execution::get_against(input, Some(&change))?;
159 Ok(Self { row, change, old, sources, creator, execution })
160 }
161}
162impl RowChange {
163 pub fn encode(&self) -> Result<Vec<u8>, Error> {
165 self.validate()?;
166 crate::encode_frame(crate::kinds::ROW_CHANGE, self)
167 }
168
169 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
171 let row: Self =
172 crate::wire::decode_frame_value(bytes, crate::kinds::ROW_CHANGE, "row change kind")?;
173 row.validate()?;
174 Ok(row)
175 }
176
177 pub(crate) fn validate(&self) -> Result<(), Error> {
178 row(&self.row)?;
179 self.change.validate(&self.row).map_err(Error::Merge)?;
180 match &self.change.operation {
181 Operation::Insert(values) | Operation::Update(values) => {
182 require(!values.is_empty(), "changed columns", Rule::Required)?;
183 crate::merge_wire::columns(values)?;
184 require(self.old.is_empty(), "old columns", Rule::ColumnOperation)?;
185 }
186 Operation::Delete => {}
187 }
188 for (n, value) in &self.old {
189 name(n)?;
190 value.validate()?;
191 }
192 self.sources.validate(self.change.generation)?;
193 let valid = match &self.change.operation {
194 Operation::Insert(_) => self.sources.setters.is_empty(),
195 Operation::Update(columns) => {
196 self.sources.setters.keys().all(|n| columns.contains_key(n))
197 }
198 Operation::Delete => true,
199 };
200 require(valid, "replaced setters", Rule::ColumnOperation)?;
201 if let Some(creator) = &self.creator {
202 require(
204 matches!(self.change.operation, Operation::Insert(_))
205 && self.change.generation == 0
206 && creator.row.table == self.row.table
207 && creator.row.key == self.row.key
208 && creator.row.audience != self.row.audience,
209 "copied creation",
210 Rule::ColumnOperation,
211 )?;
212 positive(creator.write.number)?;
213 }
214 self.execution.validate(&self.row)
215 }
216
217 pub fn validate_past(&self, past: &impl coven_merge::WritePast) -> Result<(), Error> {
219 self.sources.validate_past(past)?;
220 self.execution.sources.validate_past(past)?;
221 if let Some(creator) = &self.creator {
222 require(past.contains(&creator.write), "copied creation read", Rule::Coverage)?;
223 }
224 Ok(())
225 }
226}
227
228#[derive(Clone, Debug, PartialEq, Eq)]
232pub struct Step {
233 pub sequence: u32,
238 pub change: Change<Value>,
241 pub half: Half,
243}
244
245#[derive(Clone, Copy, Debug, PartialEq, Eq)]
247pub enum Half {
248 Whole,
250 OldKey,
253 Move,
258}
259
260impl Half {
261 fn put(self, out: &mut Encoder) -> Result<(), Error> {
262 let tag: u8 = match self {
263 Self::Whole => 0,
264 Self::OldKey => 1,
265 Self::Move => 2,
266 };
267 tag.put(out)
268 }
269
270 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
271 match u8::get(input)? {
272 0 => Ok(Self::Whole),
273 1 => Ok(Self::OldKey),
274 2 => Ok(Self::Move),
275 tag => Err(Error::UnknownTag { field: "step half", tag }),
276 }
277 }
278}
279
280impl Step {
281 pub fn after<'a>(steps: impl IntoIterator<Item = &'a Step>) -> u32 {
284 steps.into_iter().map(|step| step.sequence + 1).max().unwrap_or(0)
285 }
286}
287
288impl crate::wire::Wire for Step {
289 fn put(&self, out: &mut crate::wire::Encoder) -> Result<(), Error> {
290 self.sequence.put(out)?;
291 self.change.put(out)?;
292 self.half.put(out)
293 }
294 fn get(input: &mut crate::wire::Decoder<'_>) -> Result<Self, Error> {
295 let sequence = Wire::get(input)?;
296 let change = Wire::get(input)?;
297 Ok(Self { sequence, change, half: Half::get(input)? })
298 }
299}
300#[derive(Clone, Debug, Default, PartialEq, Eq)]
303pub struct Execution {
304 pub steps: Vec<Step>,
307 pub sources: crate::write_sources::WriteSources,
310}
311impl Execution {
312 fn put_against(&self, out: &mut Encoder, own: Option<&Change<Value>>) -> Result<(), Error> {
316 crate::error::bound(self.steps.len(), crate::wire::MAX_ITEMS, "collection")?;
317 out.charge_items(self.steps.len())?;
318 (self.steps.len() as u32).put(out)?;
319 for step in &self.steps {
320 step.sequence.put(out)?;
321 if own == Some(&step.change) {
322 0u8.put(out)?;
323 } else {
324 1u8.put(out)?;
325 step.change.put(out)?;
326 }
327 step.half.put(out)?;
328 }
329 self.sources.put(out)
330 }
331
332 fn get_against(input: &mut Decoder<'_>, own: Option<&Change<Value>>) -> Result<Self, Error> {
333 let steps = crate::wire::get_sequence(input, |input| {
334 let sequence = Wire::get(input)?;
335 let change = match (u8::get(input)?, own) {
336 (0, Some(own)) => own.clone(),
337 (1, own) => {
338 let change: Change<Value> = Wire::get(input)?;
339 require(own != Some(&change), "step change", Rule::Required)?;
341 change
342 }
343 (tag, _) => return Err(Error::UnknownTag { field: "step change", tag }),
344 };
345 Ok(Step { sequence, change, half: Half::get(input)? })
346 })?;
347 Ok(Self { steps, sources: Wire::get(input)? })
348 }
349
350 pub(crate) fn validate(&self, row_id: &RowId) -> Result<(), Error> {
351 for step in &self.steps {
352 step.change.validate(row_id).map_err(Error::Merge)?;
353 if let Operation::Insert(values) | Operation::Update(values) = &step.change.operation {
354 crate::merge_wire::columns(values)?;
355 }
356 require(
357 step.half != Half::OldKey || matches!(step.change.operation, Operation::Delete),
358 "key update step",
359 Rule::ColumnOperation,
360 )?;
361 }
362 for pair in self.steps.windows(2) {
363 require(pair[0].sequence < pair[1].sequence, "execution steps", Rule::Order)?;
364 require(
365 pair[0].change.after().ok() == Some(pair[1].change.generation),
366 "execution step generation",
367 Rule::Generation,
368 )?;
369 }
370 for source in self.sources.changes() {
371 positive(source.write.number)?;
372 row(&source.row)?;
373 }
374 for (column, source) in &self.sources.setters {
375 name(column)?;
376 name(&source.column)?;
377 }
378 Ok(())
379 }
380}
381
382#[derive(Clone, Debug, PartialEq, Eq)]
386pub struct RowExecution {
387 pub row: RowId,
389 pub execution: Execution,
391}
392impl Wire for RowExecution {
393 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
394 self.row.put(out)?;
395 self.execution.put_against(out, None)
396 }
397 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
398 Ok(Self { row: Wire::get(input)?, execution: Execution::get_against(input, None)? })
399 }
400}
401impl RowExecution {
402 pub fn encode(&self) -> Result<Vec<u8>, Error> {
404 self.validate()?;
405 crate::encode_frame(crate::kinds::ROW_EXECUTION, self)
406 }
407
408 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
410 let row: Self = crate::wire::decode_frame_value(
411 bytes,
412 crate::kinds::ROW_EXECUTION,
413 "row execution kind",
414 )?;
415 row.validate()?;
416 Ok(row)
417 }
418
419 pub(crate) fn validate(&self) -> Result<(), Error> {
420 row(&self.row)?;
421 require(!self.execution.steps.is_empty(), "execution steps", Rule::Required)?;
422 self.execution.validate(&self.row)
423 }
424}
425
426#[derive(Clone, Debug, PartialEq, Eq)]
428pub struct WritePart {
429 pub audience: Audience,
431 pub rows: Vec<RowChange>,
433 pub executions: Vec<RowExecution>,
436 pub dismissals: Vec<crate::dismissal::Dismissal>,
438}
439impl WritePart {
440 pub(crate) fn validate(&self) -> Result<(), Error> {
441 self.validate_shape()?;
442 for change in &self.rows {
443 change.validate()?;
444 }
445 for execution in &self.executions {
446 execution.validate()?;
447 }
448 Ok(())
449 }
450
451 pub(crate) fn validate_shape(&self) -> Result<(), Error> {
454 require(
455 !self.rows.is_empty() || !self.executions.is_empty() || !self.dismissals.is_empty(),
456 "write part rows",
457 Rule::Required,
458 )?;
459 require(
460 self.dismissals.windows(2).all(|pair| pair[0] < pair[1]),
461 "write part dismissals",
462 Rule::Order,
463 )?;
464 for dismissal in &self.dismissals {
465 dismissal.validate()?;
466 require(
467 dismissal.row.audience == self.audience,
468 "write part audience",
469 Rule::Audience,
470 )?;
471 }
472 require(self.rows.windows(2).all(|r| r[0].row < r[1].row), "write part rows", Rule::Order)?;
473 require(
474 self.executions.windows(2).all(|r| r[0].row < r[1].row),
475 "write part executions",
476 Rule::Order,
477 )?;
478 for change in &self.rows {
479 require(change.row.audience == self.audience, "write part audience", Rule::Audience)?;
480 }
481 for execution in &self.executions {
482 require(
483 execution.row.audience == self.audience
484 && self.rows.binary_search_by(|change| change.row.cmp(&execution.row)).is_err(),
485 "write part executions",
486 Rule::Audience,
487 )?;
488 }
489 Ok(())
490 }
491
492 pub fn records(&self) -> impl Iterator<Item = PartRecord<'_>> + '_ {
494 let mut rows = self.rows.iter().peekable();
495 let mut executions = self.executions.iter().peekable();
496 std::iter::from_fn(move || match (rows.peek(), executions.peek()) {
497 (Some(row), Some(execution)) if row.row < execution.row => {
498 rows.next().map(PartRecord::Change)
499 }
500 (_, Some(_)) => executions.next().map(PartRecord::Execution),
501 (Some(_), None) => rows.next().map(PartRecord::Change),
502 (None, None) => None,
503 })
504 }
505
506 pub fn encode_records(&self) -> Result<Vec<Vec<u8>>, Error> {
510 self.records().map(|record| record.encode()).collect()
511 }
512
513 pub(crate) fn frames(&self) -> impl Iterator<Item = Result<Vec<u8>, Error>> + '_ {
514 self.frames_with(|_, record| record.encode())
515 }
516
517 pub(crate) fn frames_from<'a>(
519 &'a self,
520 encoded: &'a [Vec<u8>],
521 ) -> impl Iterator<Item = Result<Vec<u8>, Error>> + 'a {
522 self.frames_with(|index, _| Ok(encoded[index].clone()))
523 }
524
525 fn frames_with<'a>(
528 &'a self,
529 record: impl Fn(usize, PartRecord<'a>) -> Result<Vec<u8>, Error> + 'a,
530 ) -> impl Iterator<Item = Result<Vec<u8>, Error>> + 'a {
531 let mut records = self.records().enumerate().peekable();
532 let mut dismissals = self.dismissals.iter().peekable();
533 std::iter::from_fn(move || match (records.peek(), dismissals.peek()) {
534 (Some((_, next)), Some(dismissal)) if next.row() <= &dismissal.row => {
535 records.next().map(|(index, next)| record(index, next))
536 }
537 (_, Some(_)) => dismissals.next().map(crate::dismissal::Dismissal::encode),
538 (Some(_), None) => records.next().map(|(index, next)| record(index, next)),
539 (None, None) => None,
540 })
541 }
542}
543
544#[derive(Clone, Copy, Debug, PartialEq, Eq)]
546pub enum PartRecord<'a> {
547 Change(&'a RowChange),
549 Execution(&'a RowExecution),
551}
552impl<'a> PartRecord<'a> {
553 pub fn row(&self) -> &RowId {
555 match self {
556 Self::Change(change) => &change.row,
557 Self::Execution(execution) => &execution.row,
558 }
559 }
560
561 pub fn execution(&self) -> &'a Execution {
563 match self {
564 Self::Change(change) => &change.execution,
565 Self::Execution(execution) => &execution.execution,
566 }
567 }
568
569 pub fn encode(&self) -> Result<Vec<u8>, Error> {
571 match self {
572 Self::Change(change) => change.encode(),
573 Self::Execution(execution) => execution.encode(),
574 }
575 }
576}
577
578#[derive(Clone, Debug, PartialEq, Eq)]
580pub struct WriteRecord {
581 pub header: WriteHeader,
583 pub parts: Vec<WritePart>,
585}
586impl WriteRecord {
587 pub(crate) fn validate(&self) -> Result<(), Error> {
588 self.header.validate_parts(self.parts.iter().map(|part| &part.audience))?;
589 for part in &self.parts {
590 part.validate()?;
591 }
592 Ok(())
593 }
594
595 pub(crate) fn validate_encoded(&self) -> Result<(), Error> {
598 self.header.validate_parts(self.parts.iter().map(|part| &part.audience))?;
599 for part in &self.parts {
600 part.validate_shape()?;
601 }
602 Ok(())
603 }
604}
605
606#[derive(Clone, Debug, PartialEq, Eq)]
609pub enum OriginalRow {
610 Change(RowChange),
612 Execution(RowExecution),
614}
615impl OriginalRow {
616 pub fn row(&self) -> &RowId {
618 match self {
619 Self::Change(change) => &change.row,
620 Self::Execution(execution) => &execution.row,
621 }
622 }
623
624 pub fn record(&self) -> PartRecord<'_> {
626 match self {
627 Self::Change(change) => PartRecord::Change(change),
628 Self::Execution(execution) => PartRecord::Execution(execution),
629 }
630 }
631
632 pub fn execution(&self) -> &Execution {
634 match self {
635 Self::Change(change) => &change.execution,
636 Self::Execution(execution) => &execution.execution,
637 }
638 }
639
640 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
642 match crate::dismissal::WriteFrame::decode(bytes)? {
643 crate::dismissal::WriteFrame::Change(change) => Ok(Self::Change(change)),
644 crate::dismissal::WriteFrame::Execution(execution) => Ok(Self::Execution(execution)),
645 crate::dismissal::WriteFrame::Dismissal(_) => {
646 Err(Error::UnknownTag { field: "original row kind", tag: 3 })
647 }
648 }
649 }
650}
651
652#[cfg(test)]
653#[path = "write_tests.rs"]
654mod tests;