pub trait KeyCodec<S: Schema + ?Sized>: KeyEncoder<S> + KeyDecoder<S> { }
Expand description

This trait defines a type that can serve as a Schema::Key.

KeyCodec is a marker trait with a blaket implementation for all types that are both KeyEncoder and KeyDecoder. Having KeyEncoder and KeyDecoder as two standalone traits on top of KeyCodec may seem superflous, but it allows for zero-copy key encoding under specific circumstances. E.g.:

use anyhow::Context;

use sov_schema_db::define_schema;
use sov_schema_db::schema::{
    Schema, KeyEncoder, KeyDecoder, ValueCodec, Result,
};

define_schema!(PersonAgeByName, String, u32, "person_age_by_name");

impl KeyEncoder<PersonAgeByName> for String {
    fn encode_key(&self) -> Result<Vec<u8>> {
        Ok(self.as_bytes().to_vec())
    }
}

/// What about encoding a `&str`, though? We'd have to copy it into a
/// `String` first, which is not ideal. But we can do better:
impl<'a> KeyEncoder<PersonAgeByName> for &'a str {
    fn encode_key(&self) -> Result<Vec<u8>> {
        Ok(self.as_bytes().to_vec())
    }
}

impl KeyDecoder<PersonAgeByName> for String {
    fn decode_key(data: &[u8]) -> Result<Self> {
        Ok(String::from_utf8(data.to_vec()).context("Can't read key")?)
    }
}

impl ValueCodec<PersonAgeByName> for u32 {
    fn encode_value(&self) -> Result<Vec<u8>> {
        Ok(self.to_le_bytes().to_vec())
    }

    fn decode_value(data: &[u8]) -> Result<Self> {
        let mut buf = [0u8; 4];
        buf.copy_from_slice(data);
        Ok(u32::from_le_bytes(buf))
    }
}

Implementors§

source§

impl<T, S: Schema + ?Sized> KeyCodec<S> for Twhere T: KeyEncoder<S> + KeyDecoder<S>,