coven_format/
dismissal.rs1use crate::error::{require, Error, Rule};
4use crate::value::{name, positive, row};
5use crate::wire::{decode_frame, decode_frame_value, wire_struct, Decoder, Encoder, Wire};
6use coven_merge::{RowId, WriteId, WritePast};
7
8#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
10pub enum DismissalTarget {
11 Cell(String),
13 EmptyRow,
15}
16
17impl Wire for DismissalTarget {
18 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
19 match self {
20 Self::Cell(column) => {
21 0u8.put(out)?;
22 column.put(out)
23 }
24 Self::EmptyRow => 1u8.put(out),
25 }
26 }
27 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
28 match u8::get(input)? {
29 0 => crate::wire::get_name(input).map(Self::Cell),
30 1 => Ok(Self::EmptyRow),
31 tag => Err(Error::UnknownTag { field: "dismissal target", tag }),
32 }
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
38pub struct Dismissal {
39 pub row: RowId,
41 pub target: DismissalTarget,
43 pub write: WriteId,
45}
46wire_struct!(Dismissal, row, target, write);
47
48impl Dismissal {
49 pub fn encode(&self) -> Result<Vec<u8>, Error> {
51 self.validate()?;
52 crate::encode_frame(crate::kinds::DISMISSAL, self)
53 }
54
55 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
57 let dismissal: Self = decode_frame_value(bytes, crate::kinds::DISMISSAL, "dismissal kind")?;
58 dismissal.validate()?;
59 Ok(dismissal)
60 }
61
62 pub fn validate_past(&self, past: &impl WritePast) -> Result<(), Error> {
64 require(past.contains(&self.write), "dismissed write", Rule::Coverage)
65 }
66
67 pub(crate) fn validate(&self) -> Result<(), Error> {
68 row(&self.row)?;
69 if let DismissalTarget::Cell(column) = &self.target {
70 name(column)?;
71 }
72 positive(self.write.number)
73 }
74}
75
76#[derive(Clone, Debug, PartialEq, Eq)]
79pub enum WriteFrame {
80 Change(crate::write::RowChange),
82 Execution(crate::write::RowExecution),
84 Dismissal(Dismissal),
86}
87
88impl WriteFrame {
89 pub fn encode(&self) -> Result<Vec<u8>, Error> {
91 match self {
92 Self::Change(row) => row.encode(),
93 Self::Execution(execution) => execution.encode(),
94 Self::Dismissal(dismissal) => dismissal.encode(),
95 }
96 }
97
98 pub fn record(&self) -> Option<crate::write::PartRecord<'_>> {
101 match self {
102 Self::Change(row) => Some(crate::write::PartRecord::Change(row)),
103 Self::Execution(execution) => Some(crate::write::PartRecord::Execution(execution)),
104 Self::Dismissal(_) => None,
105 }
106 }
107
108 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
110 let (kind, _) = decode_frame(bytes)?;
111 match kind {
112 crate::kinds::ROW_CHANGE => crate::write::RowChange::decode(bytes).map(Self::Change),
113 crate::kinds::DISMISSAL => Dismissal::decode(bytes).map(Self::Dismissal),
114 crate::kinds::ROW_EXECUTION => {
115 crate::write::RowExecution::decode(bytes).map(Self::Execution)
116 }
117 tag => Err(Error::UnknownTag { field: "write record kind", tag }),
118 }
119 }
120
121 pub(crate) fn key(&self) -> (RowId, Option<(DismissalTarget, WriteId)>) {
122 match self {
123 Self::Change(row) => (row.row.clone(), None),
124 Self::Execution(execution) => (execution.row.clone(), None),
125 Self::Dismissal(dismissal) => {
126 (dismissal.row.clone(), Some((dismissal.target.clone(), dismissal.write)))
127 }
128 }
129 }
130}
131
132#[cfg(test)]
133#[path = "dismissal_tests.rs"]
134mod tests;