use crate::{Error, Result};
use borsh::{BorshDeserialize, BorshSerialize};
pub trait Storable: BorshSerialize + BorshDeserialize + Sized {
type Key: KeyType;
fn key(&self) -> Self::Key;
fn validate(&self) -> Result<()> {
Ok(())
}
fn on_stored(&self) {}
fn on_deleted(&self) {}
}
pub trait KeyType:
BorshSerialize + BorshDeserialize + Clone + Send + Sync + std::fmt::Debug + 'static
{
fn to_bytes(&self) -> Result<Vec<u8>>;
#[allow(dead_code)]
fn from_bytes(bytes: &[u8]) -> Result<Self>;
}
impl KeyType for u8 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for u16 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for u32 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for u64 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for u128 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for i8 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for i16 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for i32 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for i64 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for i128 {
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl KeyType for String {
fn to_bytes(&self) -> Result<Vec<u8>> {
Ok(self.as_bytes().to_vec())
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
String::from_utf8(bytes.to_vec())
.map_err(|e| Error::InvalidKey(format!("Invalid UTF-8 in key: {}", e)))
}
}
impl KeyType for Vec<u8> {
fn to_bytes(&self) -> Result<Vec<u8>> {
Ok(self.clone())
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(bytes.to_vec())
}
}
impl<A, B> KeyType for (A, B)
where
A: KeyType,
B: KeyType,
{
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl<A, B, C> KeyType for (A, B, C)
where
A: KeyType,
B: KeyType,
C: KeyType,
{
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
impl<A, B, C, D> KeyType for (A, B, C, D)
where
A: KeyType,
B: KeyType,
C: KeyType,
D: KeyType,
{
fn to_bytes(&self) -> Result<Vec<u8>> {
borsh::to_vec(self).map_err(Into::into)
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
borsh::from_slice(bytes).map_err(Into::into)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_type_u64() {
let key: u64 = 42;
let bytes = key.to_bytes().unwrap();
let recovered = u64::from_bytes(&bytes).unwrap();
assert_eq!(key, recovered);
}
#[test]
fn test_key_type_string() {
let key = "test_key".to_string();
let bytes = key.to_bytes().unwrap();
let recovered = String::from_bytes(&bytes).unwrap();
assert_eq!(key, recovered);
}
#[test]
fn test_key_type_tuple() {
let key: (u64, String) = (123, "test".to_string());
let bytes = key.to_bytes().unwrap();
let recovered = <(u64, String)>::from_bytes(&bytes).unwrap();
assert_eq!(key, recovered);
}
}