use custom_debug_derive::Debug;
use linera_base::hex_debug;
use serde::{de::DeserializeOwned, Serialize};
use crate::{
batch::DeletePrefixExpander,
memory::MemoryStore,
store::{KeyValueStoreError, ReadableKeyValueStore, WithError, WritableKeyValueStore},
views::MIN_VIEW_TAG,
};
#[derive(Default, Debug, Clone, derive_more::From)]
pub struct BaseKey {
#[from]
#[debug(with = "hex_debug")]
pub bytes: Vec<u8>,
}
impl BaseKey {
pub fn base_tag(&self, tag: u8) -> Vec<u8> {
assert!(tag >= MIN_VIEW_TAG, "tag should be at least MIN_VIEW_TAG");
let mut key = Vec::with_capacity(self.bytes.len() + 1);
key.extend_from_slice(&self.bytes);
key.push(tag);
key
}
pub fn base_tag_index(&self, tag: u8, index: &[u8]) -> Vec<u8> {
assert!(tag >= MIN_VIEW_TAG, "tag should be at least MIN_VIEW_TAG");
let mut key = Vec::with_capacity(self.bytes.len() + 1 + index.len());
key.extend_from_slice(&self.bytes);
key.push(tag);
key.extend_from_slice(index);
key
}
pub fn base_index(&self, index: &[u8]) -> Vec<u8> {
let mut key = Vec::with_capacity(self.bytes.len() + index.len());
key.extend_from_slice(&self.bytes);
key.extend_from_slice(index);
key
}
pub fn derive_key<I: Serialize>(&self, index: &I) -> Result<Vec<u8>, bcs::Error> {
let mut key = self.bytes.clone();
bcs::serialize_into(&mut key, index)?;
assert!(
key.len() > self.bytes.len(),
"Empty indices are not allowed"
);
Ok(key)
}
pub fn derive_tag_key<I: Serialize>(&self, tag: u8, index: &I) -> Result<Vec<u8>, bcs::Error> {
assert!(tag >= MIN_VIEW_TAG, "tag should be at least MIN_VIEW_TAG");
let mut key = self.base_tag(tag);
bcs::serialize_into(&mut key, index)?;
Ok(key)
}
pub fn derive_short_key<I: Serialize + ?Sized>(index: &I) -> Result<Vec<u8>, bcs::Error> {
bcs::to_bytes(index)
}
pub fn deserialize_value<Item: DeserializeOwned>(bytes: &[u8]) -> Result<Item, bcs::Error> {
bcs::from_bytes(bytes)
}
}
#[cfg_attr(not(web), trait_variant::make(Send + Sync))]
pub trait Context: Clone
where
crate::ViewError: From<Self::Error>,
{
type Store: ReadableKeyValueStore + WritableKeyValueStore + WithError<Error = Self::Error>;
type Extra: Clone + linera_base::util::traits::AutoTraits;
type Error: KeyValueStoreError;
fn store(&self) -> &Self::Store;
fn extra(&self) -> &Self::Extra;
fn base_key(&self) -> &BaseKey;
fn base_key_mut(&mut self) -> &mut BaseKey;
fn clone_with_base_key(&self, base_key: Vec<u8>) -> Self {
let mut context = self.clone();
context.base_key_mut().bytes = base_key;
context
}
}
#[derive(Debug, Default, Clone)]
pub struct InactiveContext(pub BaseKey);
impl Context for InactiveContext {
type Store = crate::store::inactive_store::InactiveStore;
type Extra = ();
type Error = crate::store::inactive_store::InactiveStoreError;
fn store(&self) -> &Self::Store {
&crate::store::inactive_store::InactiveStore
}
fn extra(&self) -> &Self::Extra {
&()
}
fn base_key(&self) -> &BaseKey {
&self.0
}
fn base_key_mut(&mut self) -> &mut BaseKey {
&mut self.0
}
}
#[derive(Debug, Default, Clone)]
pub struct ViewContext<E, S> {
store: S,
base_key: BaseKey,
extra: E,
}
impl<E, S> ViewContext<E, S>
where
S: ReadableKeyValueStore + WritableKeyValueStore,
{
pub async fn create_root_context(store: S, extra: E) -> Result<Self, S::Error> {
store.clear_journal().await?;
Ok(Self::new_unchecked(store, Vec::new(), extra))
}
}
impl<E, S> ViewContext<E, S> {
pub fn new_unchecked(store: S, base_key: Vec<u8>, extra: E) -> Self {
Self {
store,
base_key: BaseKey { bytes: base_key },
extra,
}
}
}
impl<E, S> Context for ViewContext<E, S>
where
E: Clone + linera_base::util::traits::AutoTraits,
S: ReadableKeyValueStore + WritableKeyValueStore + Clone,
S::Error: From<bcs::Error> + Send + Sync + std::error::Error + 'static,
{
type Extra = E;
type Store = S;
type Error = S::Error;
fn store(&self) -> &Self::Store {
&self.store
}
fn extra(&self) -> &E {
&self.extra
}
fn base_key(&self) -> &BaseKey {
&self.base_key
}
fn base_key_mut(&mut self) -> &mut BaseKey {
&mut self.base_key
}
}
pub type MemoryContext<E> = ViewContext<E, MemoryStore>;
impl<E> MemoryContext<E> {
#[cfg(with_testing)]
pub fn new_for_testing(extra: E) -> Self {
Self {
store: MemoryStore::new_for_testing(),
base_key: BaseKey::default(),
extra,
}
}
}
impl DeletePrefixExpander for MemoryContext<()> {
type Error = crate::memory::MemoryStoreError;
async fn expand_delete_prefix(&self, key_prefix: &[u8]) -> Result<Vec<Vec<u8>>, Self::Error> {
self.store().find_keys_by_prefix(key_prefix).await
}
}