use std::fmt::Debug;
use self::errors::CodecError;
pub mod errors;
pub type ColumnFamilyName = &'static str;
pub trait Schema: Debug + Send + Sync + 'static + Sized {
const COLUMN_FAMILY_NAME: ColumnFamilyName;
type Key: KeyCodec<Self>;
type Value: ValueCodec<Self>;
}
pub type Result<T, E = CodecError> = core::result::Result<T, E>;
pub trait KeyCodec<S: Schema + ?Sized>: KeyEncoder<S> + KeyDecoder<S> {}
impl<T, S: Schema + ?Sized> KeyCodec<S> for T where T: KeyEncoder<S> + KeyDecoder<S> {}
pub trait KeyEncoder<S: Schema + ?Sized>: Sized + PartialEq + Debug {
fn encode_key(&self) -> Result<Vec<u8>>;
}
pub trait KeyDecoder<S: Schema + ?Sized>: Sized + PartialEq + Debug {
fn decode_key(data: &[u8]) -> Result<Self>;
}
pub trait ValueCodec<S: Schema + ?Sized>: Sized + PartialEq + Debug {
fn encode_value(&self) -> Result<Vec<u8>>;
fn decode_value(data: &[u8]) -> Result<Self>;
}
pub trait SeekKeyEncoder<S: Schema + ?Sized>: Sized {
fn encode_seek_key(&self) -> Result<Vec<u8>>;
}
impl<S, K> SeekKeyEncoder<S> for K
where
S: Schema,
K: KeyEncoder<S>,
{
fn encode_seek_key(&self) -> Result<Vec<u8>> {
<K as KeyEncoder<S>>::encode_key(self)
}
}
#[macro_export]
macro_rules! define_schema {
($schema_type:ident, $key_type:ty, $value_type:ty, $cf_name:expr) => {
#[derive(Debug)]
pub(crate) struct $schema_type;
impl $crate::db::Schema for $schema_type {
type Key = $key_type;
type Value = $value_type;
const COLUMN_FAMILY_NAME: $crate::db::ColumnFamilyName = $cf_name;
}
};
}
#[cfg(feature = "fuzzing")]
pub mod fuzzing {
use super::{KeyDecoder, KeyEncoder, Schema, ValueCodec};
use proptest::{collection::vec, prelude::*};
pub fn assert_encode_decode<S: Schema>(key: &S::Key, value: &S::Value) {
{
let encoded = key.encode_key().expect("Encoding key should work.");
let decoded = S::Key::decode_key(&encoded).expect("Decoding key should work.");
assert_eq!(*key, decoded);
}
{
let encoded = value.encode_value().expect("Encoding value should work.");
let decoded = S::Value::decode_value(&encoded).expect("Decoding value should work.");
assert_eq!(*value, decoded);
}
}
#[allow(unused_must_use)]
pub fn assert_no_panic_decoding<S: Schema>(bytes: &[u8]) {
S::Key::decode_key(bytes);
S::Value::decode_value(bytes);
}
pub fn arb_small_vec_u8() -> impl Strategy<Value = Vec<u8>> {
vec(any::<u8>(), 0..2048)
}
#[macro_export]
macro_rules! test_no_panic_decoding {
($schema_type:ty) => {
use proptest::prelude::*;
use sov_schema_db::schema::fuzzing::{arb_small_vec_u8, assert_no_panic_decoding};
proptest! {
#[test]
fn test_no_panic_decoding(bytes in arb_small_vec_u8()) {
assert_no_panic_decoding::<$schema_type>(&bytes)
}
}
};
}
}