use crate::backend::native::NativeBackendError;
use crate::backend::native::NativeResult;
use crate::backend::native::types::NodeFlags;
mod codec_support;
#[cfg(test)]
mod tests;
pub mod constants {
pub const FIXED_METADATA_SIZE: usize = 44;
pub const MAX_INLINE_DATA: usize = 64;
pub const ID_OFFSET: usize = 0;
pub const FLAGS_OFFSET: usize = 8;
pub const KIND_OFFSET: usize = 12;
pub const NAME_OFFSET: usize = 14;
pub const DATA_LEN_OFFSET: usize = 16;
pub const OUTGOING_CLUSTER_OFFSET: usize = 18;
pub const OUTGOING_COUNT_OFFSET: usize = 26;
pub const INCOMING_CLUSTER_OFFSET: usize = 30;
pub const INCOMING_COUNT_OFFSET: usize = 38;
pub const EXTERNAL_DATA_FLAG: u16 = 0x8000;
pub const MAX_DATA_LEN: u16 = 0x7FFF;
pub const ID_SIZE: usize = 8;
pub const FLAGS_SIZE: usize = 4;
pub const KIND_OFFSET_SIZE: usize = 2;
pub const NAME_OFFSET_SIZE: usize = 2;
pub const DATA_LEN_SIZE: usize = 2;
pub const OUTGOING_CLUSTER_SIZE: usize = 8;
pub const OUTGOING_COUNT_SIZE: usize = 4;
pub const INCOMING_CLUSTER_SIZE: usize = 8;
pub const INCOMING_COUNT_SIZE: usize = 4;
}
pub const FIXED_METADATA_SIZE: usize = constants::FIXED_METADATA_SIZE;
pub const MAX_INLINE_DATA: usize = constants::MAX_INLINE_DATA;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NodeRecordV3 {
pub id: i64,
pub flags: NodeFlags,
pub kind_offset: u16,
pub name_offset: u16,
pub data_len: u16,
pub data_inline: Option<Vec<u8>>,
pub data_external_offset: Option<u64>,
pub outgoing_cluster_offset: u64,
pub outgoing_edge_count: u32,
pub incoming_cluster_offset: u64,
pub incoming_edge_count: u32,
}
impl NodeRecordV3 {
pub fn new_inline(
id: i64,
flags: NodeFlags,
kind_offset: u16,
name_offset: u16,
data: Vec<u8>,
outgoing_cluster_offset: u64,
outgoing_edge_count: u32,
incoming_cluster_offset: u64,
incoming_edge_count: u32,
) -> Self {
let data_len = data.len() as u16;
assert!(
data_len <= MAX_INLINE_DATA as u16,
"Inline data exceeds MAX_INLINE_DATA"
);
NodeRecordV3 {
id,
flags,
kind_offset,
name_offset,
data_len,
data_inline: Some(data),
data_external_offset: None,
outgoing_cluster_offset,
outgoing_edge_count,
incoming_cluster_offset,
incoming_edge_count,
}
}
pub fn new_external(
id: i64,
flags: NodeFlags,
kind_offset: u16,
name_offset: u16,
data_external_offset: u64,
data_len: u16,
outgoing_cluster_offset: u64,
outgoing_edge_count: u32,
incoming_cluster_offset: u64,
incoming_edge_count: u32,
) -> Self {
assert!(
data_len > MAX_INLINE_DATA as u16,
"External data must exceed MAX_INLINE_DATA"
);
NodeRecordV3 {
id,
flags,
kind_offset,
name_offset,
data_len,
data_inline: None,
data_external_offset: Some(data_external_offset),
outgoing_cluster_offset,
outgoing_edge_count,
incoming_cluster_offset,
incoming_edge_count,
}
}
pub fn id(&self) -> i64 {
self.id
}
pub fn is_inline(&self) -> bool {
self.data_inline.is_some()
}
pub fn is_external(&self) -> bool {
self.data_external_offset.is_some() || (self.data_len & constants::EXTERNAL_DATA_FLAG) != 0
}
pub fn data_len(&self) -> u16 {
self.data_len & constants::MAX_DATA_LEN
}
pub fn serialized_size(&self) -> usize {
let mut size = FIXED_METADATA_SIZE;
if self.is_inline() {
size += self.data_inline.as_ref().map(|d| d.len()).unwrap_or(0);
} else if self.is_external() {
size += 8;
}
size
}
pub fn size_estimate() -> usize {
FIXED_METADATA_SIZE + MAX_INLINE_DATA / 2
}
}