use crate::resp::is_collection_tag;
use bytes::{BufMut, Bytes, BytesMut};
pub(crate) const TAPE_NODE_SIZE: usize = 8;
const PAYLOAD_MASK: u64 = 0x00FF_FFFF_FFFF_FFFF;
pub(crate) const MAX_TAPE_PAYLOAD: u64 = PAYLOAD_MASK;
pub(crate) const TAPE_LEN_TAG: u8 = 0;
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) struct TapeNode(u64);
impl TapeNode {
#[inline(always)]
pub(crate) fn new(tag: u8, payload: u64) -> Self {
debug_assert!(
payload <= MAX_TAPE_PAYLOAD,
"tape payload overflows 56 bits"
);
Self((u64::from(tag) << 56) | (payload & PAYLOAD_MASK))
}
#[inline(always)]
pub(crate) fn tag(self) -> u8 {
(self.0 >> 56) as u8
}
#[inline(always)]
pub(crate) fn payload(self) -> u64 {
self.0 & PAYLOAD_MASK
}
#[inline(always)]
pub(crate) fn payload_index(self) -> usize {
usize::try_from(self.payload()).unwrap_or(usize::MAX)
}
#[inline(always)]
pub(crate) fn is_collection(self) -> bool {
is_collection_tag(self.tag())
}
}
#[repr(transparent)]
#[derive(Clone, Default, PartialEq, Eq)]
pub(crate) struct RespTape(Bytes);
impl RespTape {
#[inline(always)]
pub(crate) fn node_count(&self) -> usize {
self.0.len() / TAPE_NODE_SIZE
}
#[inline(always)]
pub(crate) fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline(always)]
#[expect(
clippy::indexing_slicing,
clippy::expect_used,
clippy::arithmetic_side_effects,
reason = "invariant: `index` addresses a node this crate wrote. Tape indices \
are never read off the wire — they are literal roots (0) or `next` \
payloads the parser back-patched from `node_count`. The byte offset \
therefore lands inside a buffer that already holds that node, so \
neither the multiply nor the add can leave `usize`. A fallback \
would have to invent a node word and corrupt the read silently, \
so the invariant is checked by the debug assertion instead."
)]
pub(crate) fn node(&self, index: usize) -> TapeNode {
let start = index * TAPE_NODE_SIZE;
debug_assert!(
start + TAPE_NODE_SIZE <= self.0.len(),
"tape node {index} is past the end of a {}-node tape",
self.node_count()
);
let bytes: [u8; TAPE_NODE_SIZE] = self.0[start..start + TAPE_NODE_SIZE]
.try_into()
.expect("tape slice shorter than a node");
TapeNode(u64::from_le_bytes(bytes))
}
#[inline(always)]
pub(crate) fn byte_len(&self) -> usize {
self.0.len()
}
#[inline]
#[cfg(any(test, feature = "client-cache"))]
pub(crate) fn compact(&self) -> RespTape {
RespTape(Bytes::copy_from_slice(&self.0))
}
#[cfg(test)]
#[inline]
pub(crate) fn collection_len(&self, root: usize) -> Option<usize> {
let companion = root.checked_add(1)?;
if self.node_count() <= companion {
return None;
}
Some(self.node(companion).payload_index())
}
}
#[derive(Default)]
pub(crate) struct RespTapeMut(BytesMut);
impl RespTapeMut {
#[inline]
pub(crate) fn with_capacity(capacity: usize) -> Self {
Self(BytesMut::with_capacity(capacity))
}
#[inline(always)]
pub(crate) fn node_count(&self) -> usize {
self.0.len() / TAPE_NODE_SIZE
}
#[inline(always)]
pub(crate) fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[cfg(any(test, feature = "bench"))]
#[inline(always)]
pub(crate) fn byte_capacity(&self) -> usize {
self.0.capacity()
}
#[inline(always)]
pub(crate) fn push(&mut self, tag: u8, payload: u64) -> usize {
let index = self.node_count();
self.0.put_u64_le(TapeNode::new(tag, payload).0);
index
}
#[inline(always)]
#[expect(
clippy::indexing_slicing,
clippy::arithmetic_side_effects,
reason = "invariant: `index` was returned by `push` for this same tape, \
so the node it addresses has already been appended and its byte \
offset is inside the buffer."
)]
pub(crate) fn patch(&mut self, index: usize, tag: u8, payload: u64) {
let start = index * TAPE_NODE_SIZE;
debug_assert!(
start + TAPE_NODE_SIZE <= self.0.len(),
"tape node {index} is past the end of a {}-node tape",
self.node_count()
);
self.0[start..start + TAPE_NODE_SIZE]
.copy_from_slice(&TapeNode::new(tag, payload).0.to_le_bytes());
}
#[inline]
pub(crate) fn split_freeze(&mut self) -> RespTape {
RespTape(self.0.split().freeze())
}
#[inline]
pub(crate) fn clear(&mut self) {
self.0.clear();
}
}