use std::fmt::{self, Debug, Display};
use bytes::Bytes;
pub const PAGE_SIZE: usize = 4096;
pub const MAX_KEY_LENGTH: usize = 1024;
#[allow(dead_code)]
pub const MAX_VALUE_LENGTH: usize = PAGE_SIZE - 128;
pub const PAGE_HEADER_SIZE: usize = 32;
pub const CRC_SIZE: usize = 4;
pub const BTREE_MIN_KEYS: usize = 4;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct PageId(u64);
impl PageId {
pub const SUPERBLOCK: PageId = PageId(0);
pub fn new(id: u64) -> Self {
Self(id)
}
pub fn as_u64(self) -> u64 {
self.0
}
pub fn byte_offset(self) -> u64 {
self.0 * PAGE_SIZE as u64
}
pub fn next(self) -> Self {
Self(self.0 + 1)
}
}
impl Debug for PageId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PageId({})", self.0)
}
}
impl Display for PageId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for PageId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<PageId> for u64 {
fn from(id: PageId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct TableId(u64);
impl TableId {
pub fn new(id: u64) -> Self {
Self(id)
}
pub fn as_u64(self) -> u64 {
self.0
}
}
impl Debug for TableId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TableId({})", self.0)
}
}
impl Display for TableId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for TableId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<TableId> for u64 {
fn from(id: TableId) -> Self {
id.0
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Key(Bytes);
impl Key {
pub fn new(data: impl Into<Bytes>) -> Self {
let bytes = data.into();
debug_assert!(
bytes.len() <= MAX_KEY_LENGTH,
"key length {} exceeds maximum {}",
bytes.len(),
MAX_KEY_LENGTH
);
Self(bytes)
}
pub fn from_static(data: &'static [u8]) -> Self {
Self::new(Bytes::from_static(data))
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn into_bytes(self) -> Bytes {
self.0
}
pub fn min() -> Self {
Self(Bytes::new())
}
pub fn max() -> Self {
Self(Bytes::from(vec![0xFF; MAX_KEY_LENGTH]))
}
}
impl Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Key(")?;
for (i, byte) in self.0.iter().take(16).enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{byte:02x}")?;
}
if self.0.len() > 16 {
write!(f, "...+{} more", self.0.len() - 16)?;
}
write!(f, ")")
}
}
impl Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Ok(s) = std::str::from_utf8(&self.0) {
if s.chars().all(|c| c.is_ascii_graphic() || c == ' ') {
return write!(f, "{s}");
}
}
for byte in &self.0 {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}
impl From<&[u8]> for Key {
fn from(data: &[u8]) -> Self {
Self::new(Bytes::copy_from_slice(data))
}
}
impl From<Vec<u8>> for Key {
fn from(data: Vec<u8>) -> Self {
Self::new(Bytes::from(data))
}
}
impl From<Bytes> for Key {
fn from(data: Bytes) -> Self {
Self::new(data)
}
}
impl From<&str> for Key {
fn from(s: &str) -> Self {
Self::new(Bytes::copy_from_slice(s.as_bytes()))
}
}
impl From<String> for Key {
fn from(s: String) -> Self {
Self::new(Bytes::from(s))
}
}
impl AsRef<[u8]> for Key {
fn as_ref(&self) -> &[u8] {
&self.0
}
}