kacrab_protocol/
record.rs1use bytes::{Buf, Bytes, BytesMut};
9
10use crate::primitives::{read_signed_varint, signed_varint_len, write_signed_varint};
11
12pub mod batch;
13pub mod entry;
14pub mod error;
15pub mod header;
16
17pub use self::{
18 batch::{RecordBatch, TimestampType, decode_batches, decode_next_batch},
19 entry::Record,
20 error::{RecordError, RecordErrorKind},
21 header::RecordHeader,
22};
23
24pub type Result<T> = core::result::Result<T, RecordError>;
26
27pub const MAX_RECORDS_PER_BATCH: usize = 1_000_000;
33
34fn max_i32_len() -> usize {
35 usize::try_from(i32::MAX).unwrap_or(usize::MAX)
36}
37
38const fn length_overflow(field: &'static str, got: usize, remaining: usize) -> RecordError {
39 RecordError::unknown_offset(RecordErrorKind::LengthOverflow {
40 field,
41 got,
42 remaining,
43 })
44}
45
46fn encode_len(field: &'static str, len: usize) -> Result<i32> {
47 i32::try_from(len).map_err(|_| length_overflow(field, len, max_i32_len()))
48}
49
50pub(super) fn add_encoded_len(field: &'static str, current: usize, addend: usize) -> Result<usize> {
51 current
52 .checked_add(addend)
53 .ok_or_else(|| length_overflow(field, usize::MAX, max_i32_len()))
54}
55
56pub(super) fn bytes_field_len(field: &'static str, bytes: &Bytes) -> Result<usize> {
57 let len = encode_len(field, bytes.len())?;
58 add_encoded_len(field, signed_varint_len(len), bytes.len())
59}
60
61pub(super) fn nullable_bytes_field_len(
62 field: &'static str,
63 bytes: Option<&Bytes>,
64) -> Result<usize> {
65 bytes.map_or_else(
66 || Ok(signed_varint_len(-1)),
67 |bytes| bytes_field_len(field, bytes),
68 )
69}
70
71fn split_exact(buf: &mut Bytes, field: &'static str, len: usize) -> Result<Bytes> {
72 let remaining = buf.remaining();
73 if len > remaining {
74 return Err(length_overflow(field, len, remaining));
75 }
76 Ok(buf.split_to(len))
77}
78
79pub(super) fn read_bytes_field(buf: &mut Bytes, field: &'static str) -> Result<Bytes> {
80 let length = read_signed_varint(buf)?;
81 if length < 0 {
82 return Err(RecordError::unknown_offset(
83 RecordErrorKind::NegativeLength { field, length },
84 ));
85 }
86 let len =
87 usize::try_from(length).map_err(|_| length_overflow(field, usize::MAX, buf.remaining()))?;
88 split_exact(buf, field, len)
89}
90
91pub(super) fn read_nullable_bytes_field(
92 buf: &mut Bytes,
93 field: &'static str,
94) -> Result<Option<Bytes>> {
95 let length = read_signed_varint(buf)?;
96 if length < 0 {
97 return Ok(None);
98 }
99 let len =
100 usize::try_from(length).map_err(|_| length_overflow(field, usize::MAX, buf.remaining()))?;
101 split_exact(buf, field, len).map(Some)
102}
103
104pub(super) fn write_bytes_field(
105 buf: &mut BytesMut,
106 field: &'static str,
107 bytes: &Bytes,
108) -> Result<()> {
109 write_signed_varint(buf, encode_len(field, bytes.len())?);
110 buf.extend_from_slice(bytes);
111 Ok(())
112}
113
114pub(super) fn write_nullable_bytes_field(
115 buf: &mut BytesMut,
116 field: &'static str,
117 bytes: Option<&Bytes>,
118) -> Result<()> {
119 match bytes {
120 None => {
121 write_signed_varint(buf, -1);
122 Ok(())
123 },
124 Some(bytes) => write_bytes_field(buf, field, bytes),
125 }
126}