use std::{io::Write, sync::Arc};
pub mod block;
pub mod chain;
pub mod shielded;
pub mod transparent;
pub mod upgrade;
#[cfg(any(test, feature = "proptest-impl"))]
mod tests;
pub use block::{TransactionIndex, TransactionLocation, MAX_ON_DISK_HEIGHT};
pub use transparent::OutputLocation;
#[cfg(any(test, feature = "proptest-impl"))]
pub use tests::KV;
pub trait IntoDisk {
type Bytes: AsRef<[u8]>;
fn as_bytes(&self) -> Self::Bytes;
}
pub trait FromDisk: Sized {
fn from_bytes(bytes: impl AsRef<[u8]>) -> Self;
}
impl<T> IntoDisk for &T
where
T: IntoDisk,
{
type Bytes = T::Bytes;
fn as_bytes(&self) -> Self::Bytes {
T::as_bytes(*self)
}
}
impl<T> IntoDisk for Arc<T>
where
T: IntoDisk,
{
type Bytes = T::Bytes;
fn as_bytes(&self) -> Self::Bytes {
T::as_bytes(self)
}
}
impl<T> FromDisk for Arc<T>
where
T: FromDisk,
{
fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
Arc::new(T::from_bytes(bytes))
}
}
impl IntoDisk for () {
type Bytes = [u8; 0];
fn as_bytes(&self) -> Self::Bytes {
[]
}
}
impl FromDisk for () {
#[allow(clippy::unused_unit)]
fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
assert_eq!(
bytes.as_ref().len(),
0,
"unexpected data in zero-sized column family type",
);
()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct RawBytes(Vec<u8>);
impl RawBytes {
pub fn new_raw_bytes(bytes: Vec<u8>) -> Self {
Self(bytes)
}
pub fn raw_bytes(&self) -> &Vec<u8> {
&self.0
}
}
impl IntoDisk for RawBytes {
type Bytes = Vec<u8>;
fn as_bytes(&self) -> Self::Bytes {
self.raw_bytes().clone()
}
}
impl FromDisk for RawBytes {
fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
Self::new_raw_bytes(bytes.as_ref().to_vec())
}
}
pub fn truncate_zero_be_bytes(mem_bytes: &[u8], disk_len: usize) -> Option<&[u8]> {
#![allow(clippy::unwrap_in_result)]
let discarded_bytes = mem_bytes
.len()
.checked_sub(disk_len)
.expect("unexpected `mem_bytes` length: must be at least `disk_len`");
if discarded_bytes == 0 {
return Some(mem_bytes);
}
let (discarded, truncated) = mem_bytes.split_at(discarded_bytes);
if !discarded.iter().all(|&byte| byte == 0) {
return None;
}
assert_eq!(truncated.len(), disk_len);
Some(truncated)
}
#[inline]
pub fn expand_zero_be_bytes<const MEM_SIZE: usize>(disk_bytes: &[u8]) -> [u8; MEM_SIZE] {
if let Ok(disk_bytes_array) = disk_bytes.try_into() {
return disk_bytes_array;
}
let extra_bytes = MEM_SIZE
.checked_sub(disk_bytes.len())
.expect("unexpected `disk_bytes` length: must not exceed `MEM_SIZE`");
let mut expanded = [0; MEM_SIZE];
let _ = (&mut expanded[extra_bytes..])
.write(disk_bytes)
.expect("should fit");
expanded
}