spacetimedb_commitlog/
payload.rs1use std::sync::Arc;
2
3use spacetimedb_sats::{
4 bsatn,
5 buffer::{BufReader, BufWriter, DecodeError},
6 ser::Serialize,
7 ProductValue,
8};
9use thiserror::Error;
10
11pub mod txdata;
12pub use txdata::Txdata;
13
14pub trait Encode {
19 fn encode_record<W: BufWriter>(&self, writer: &mut W);
21}
22
23impl<T: Encode> Encode for Arc<T> {
24 fn encode_record<W: BufWriter>(&self, writer: &mut W) {
25 (**self).encode_record(writer)
26 }
27}
28
29impl Encode for ProductValue {
30 fn encode_record<W: BufWriter>(&self, writer: &mut W) {
31 self.serialize(bsatn::Serializer::new(writer))
32 .expect("bsatn serialize should never fail");
33 }
34}
35
36impl Encode for () {
37 fn encode_record<W: BufWriter>(&self, _writer: &mut W) {}
38}
39
40pub trait Decoder {
46 type Record: Encode;
50 type Error: From<DecodeError>;
52
53 fn decode_record<'a, R: BufReader<'a>>(
61 &self,
62 version: u8,
63 tx_offset: u64,
64 reader: &mut R,
65 ) -> Result<Self::Record, Self::Error>;
66
67 fn consume_record<'a, R: BufReader<'a>>(
76 &self,
77 version: u8,
78 tx_offset: u64,
79 reader: &mut R,
80 ) -> Result<(), Self::Error> {
81 self.decode_record(version, tx_offset, reader).map(drop)
82 }
83
84 fn skip_record<'a, R: BufReader<'a>>(&self, version: u8, tx_offset: u64, reader: &mut R)
87 -> Result<(), Self::Error>;
88}
89
90impl<const N: usize> Encode for [u8; N] {
91 fn encode_record<W: BufWriter>(&self, writer: &mut W) {
92 writer.put_slice(&self[..])
93 }
94}
95
96#[derive(Debug, Error)]
97pub enum ArrayDecodeError {
98 #[error(transparent)]
99 Decode(#[from] DecodeError),
100 #[error(transparent)]
101 Traversal(#[from] crate::error::Traversal),
102 #[error(transparent)]
103 Io(#[from] std::io::Error),
104}
105
106pub struct ArrayDecoder<const N: usize>;
107
108impl<const N: usize> Decoder for ArrayDecoder<N> {
109 type Record = [u8; N];
110 type Error = ArrayDecodeError;
111
112 fn decode_record<'a, R: BufReader<'a>>(
113 &self,
114 _version: u8,
115 _tx_offset: u64,
116 reader: &mut R,
117 ) -> Result<Self::Record, Self::Error> {
118 Ok(*reader.get_array()?)
119 }
120
121 fn skip_record<'a, R: BufReader<'a>>(
122 &self,
123 version: u8,
124 tx_offset: u64,
125 reader: &mut R,
126 ) -> Result<(), Self::Error> {
127 self.decode_record(version, tx_offset, reader).map(drop)
128 }
129}