mod bcs_codec;
mod borsh_codec;
mod json_codec;
mod split_codec;
pub use bcs_codec::BcsCodec;
use borsh::BorshSerialize;
pub use borsh_codec::BorshCodec;
pub use json_codec::JsonCodec;
pub trait StateValueCodec<V> {
type Error: std::fmt::Debug;
fn encode_value(&self, value: &V) -> Vec<u8>;
fn try_decode_value(&self, bytes: &[u8]) -> Result<V, Self::Error>;
fn decode_value_unwrap(&self, bytes: &[u8]) -> V {
self.try_decode_value(bytes)
.map_err(|err| {
format!(
"Failed to decode value 0x{}, error: {:?}",
hex::encode(bytes),
err
)
})
.unwrap()
}
}
pub trait StateKeyCodec<K> {
fn encode_key(&self, key: &K) -> Vec<u8>;
}
pub trait StateCodec {
type KeyCodec;
type ValueCodec;
fn key_codec(&self) -> &Self::KeyCodec;
fn value_codec(&self) -> &Self::ValueCodec;
}
pub trait EncodeKeyLike<Ref: ?Sized, Target> {
fn encode_key_like(&self, borrowed: &Ref) -> Vec<u8>;
}
impl<C, T> EncodeKeyLike<T, T> for C
where
C: StateKeyCodec<T>,
{
fn encode_key_like(&self, borrowed: &T) -> Vec<u8> {
self.encode_key(borrowed)
}
}
impl<T> EncodeKeyLike<[T], Vec<T>> for BorshCodec
where
T: BorshSerialize,
{
fn encode_key_like(&self, borrowed: &[T]) -> Vec<u8> {
borrowed.try_to_vec().unwrap()
}
}
#[cfg(test)]
mod tests {
use proptest::collection::vec;
use proptest::prelude::any;
use proptest::strategy::Strategy;
use super::*;
fn arb_vec_i32() -> impl Strategy<Value = Vec<i32>> {
vec(any::<i32>(), 0..2048)
}
proptest::proptest! {
#[test]
fn test_borsh_slice_encode_alike(vec in arb_vec_i32()) {
let codec = BorshCodec;
assert_eq!(
<BorshCodec as EncodeKeyLike<[i32], Vec<i32>>>::encode_key_like(&codec, &vec[..]),
codec.encode_value(&vec)
);
}
}
}