coven_format/
writes_slot.rs1use crate::error::{exact_length, require, Error, Rule};
5use crate::path::ObjectPath;
6use crate::sequence::SlotHeader;
7use crate::value::positive;
8use crate::write::WriteHeader;
9
10pub const HEAD_LEN: usize = SlotHeader::ENCODED_LEN + 8;
12
13pub fn encode_head(header: &SlotHeader, path: &ObjectPath, count: u64) -> Result<Vec<u8>, Error> {
15 positive(count)?;
16 let mut bytes = header.encode(path)?;
17 bytes.extend_from_slice(&count.to_be_bytes());
18 Ok(bytes)
19}
20
21pub fn decode_head(bytes: &[u8], path: &ObjectPath) -> Result<(SlotHeader, u64), Error> {
23 exact_length(bytes.len(), HEAD_LEN)?;
24 let (header, count) = bytes.split_at(SlotHeader::ENCODED_LEN);
25 let header = SlotHeader::decode(header, path)?;
26 let count = u64::from_be_bytes(count.try_into().expect("eight bytes"));
27 positive(count)?;
28 Ok((header, count))
29}
30
31pub fn encode_write_length(length: u64) -> [u8; 8] {
33 length.to_be_bytes()
34}
35
36pub fn decode_write_length(bytes: [u8; 8], remaining: u64) -> Result<u64, Error> {
39 let length = u64::from_be_bytes(bytes);
40 require(length > 0 && length <= remaining, "inner write length", Rule::StreamLength)?;
41 Ok(length)
42}
43
44pub fn identity(
46 store: coven_foundation::id_source::StoreId,
47 write: coven_merge::WriteId,
48) -> Result<String, Error> {
49 crate::value::positive(write.number)?;
50 Ok(format!("coven/write/{store}/{}/{}", write.device.0, write.number))
51}
52
53pub fn check_write(
56 slot: &SlotHeader,
57 previous: Option<u64>,
58 header: &WriteHeader,
59) -> Result<(), Error> {
60 slot.check_write(header)?;
61 require(
62 previous.is_none_or(|number| number < header.position.number),
63 "batch write order",
64 Rule::Order,
65 )
66}
67
68#[cfg(test)]
69#[path = "writes_slot_tests.rs"]
70mod tests;