use std::{fmt::Debug, future::Future, io::Write};
use linera_base::crypto::CryptoHash;
pub use linera_views_derive::{
ClonableView, CryptoHashRootView, CryptoHashView, HashableView, RootView, View,
};
use serde::Serialize;
use crate::{batch::Batch, common::HasherOutput, ViewError};
#[cfg(test)]
#[path = "unit_tests/views.rs"]
mod tests;
pub mod register_view;
pub mod lazy_register_view;
pub mod log_view;
pub mod bucket_queue_view;
pub mod queue_view;
pub mod map_view;
pub mod set_view;
pub mod collection_view;
pub mod reentrant_collection_view;
pub mod key_value_store_view;
pub mod hashable_wrapper;
pub mod historical_hash_wrapper;
pub const MIN_VIEW_TAG: u8 = 1;
#[cfg_attr(not(web), trait_variant::make(Send + Sync))]
pub trait View: Sized {
const NUM_INIT_KEYS: usize;
type Context: crate::context::Context;
fn context(&self) -> &Self::Context;
fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError>;
fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError>;
fn load(context: Self::Context) -> impl Future<Output = Result<Self, ViewError>> {
async {
if Self::NUM_INIT_KEYS == 0 {
Self::post_load(context, &[])
} else {
use crate::{context::Context, store::ReadableKeyValueStore};
let keys = Self::pre_load(&context)?;
let values = context.store().read_multi_values_bytes(&keys).await?;
Self::post_load(context, &values)
}
}
}
fn rollback(&mut self);
async fn has_pending_changes(&self) -> bool;
fn clear(&mut self);
fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError>;
fn post_save(&mut self);
fn new(context: Self::Context) -> Result<Self, ViewError> {
let values = vec![None; Self::NUM_INIT_KEYS];
let mut view = Self::post_load(context, &values)?;
view.clear();
Ok(view)
}
}
pub trait ReplaceContext<C: crate::context::Context>: View {
type Target: View<Context = C>;
async fn with_context(&mut self, ctx: impl FnOnce(&Self::Context) -> C + Clone)
-> Self::Target;
}
#[cfg_attr(not(web), trait_variant::make(Send))]
pub trait HashableView: View {
type Hasher: Hasher;
async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError>;
async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError>;
}
pub trait Hasher: Default + Write + Send + Sync + 'static {
type Output: Debug + Clone + Eq + AsRef<[u8]> + 'static;
fn finalize(self) -> Self::Output;
fn update_with_bcs_bytes(&mut self, value: &impl Serialize) -> Result<(), ViewError> {
bcs::serialize_into(self, value)?;
Ok(())
}
fn update_with_bytes(&mut self, value: &[u8]) -> Result<(), ViewError> {
self.write_all(value)?;
Ok(())
}
}
impl Hasher for sha3::Sha3_256 {
type Output = HasherOutput;
fn finalize(self) -> Self::Output {
<sha3::Sha3_256 as sha3::Digest>::finalize(self)
}
}
#[cfg_attr(not(web), trait_variant::make(Send))]
pub trait RootView: View {
async fn save(&mut self) -> Result<(), ViewError>;
async fn save_and_drop(self) -> Result<(), ViewError>;
}
#[cfg_attr(not(web), trait_variant::make(Send))]
pub trait CryptoHashView: HashableView {
async fn crypto_hash(&self) -> Result<CryptoHash, ViewError>;
async fn crypto_hash_mut(&mut self) -> Result<CryptoHash, ViewError>;
}
#[cfg_attr(not(web), trait_variant::make(Send))]
pub trait CryptoHashRootView: RootView + CryptoHashView {}
pub trait ClonableView: View {
fn clone_unchecked(&mut self) -> Result<Self, ViewError>;
}