zephyr_vm/db/database.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
//! This module defines how the database implementation in
//! Zephyr should be implemented.
//!
//! Implementors that wish to use the Zephyr VM in their code
//! must provide the Zephyr host environment with a valid implementation
//! of the Database.
use crate::{ZephyrMock, ZephyrStandard};
use anyhow::Result;
use rs_zephyr_common::DatabaseError;
/// Allowed column conditions
pub enum WhereCond {
/// Where column i64 is equal to the corresponding condition
/// argument.
ColEq(i64),
/// Where column i64 is greater than the corresponding condition
/// argument.
ColGt(i64),
/// Where column i64 is less than the corresponding condition
/// argument.
ColLt(i64),
}
impl WhereCond {
pub(crate) fn from_column_and_operator(col: i64, operator: i64) -> Result<Self> {
match operator {
0 => Ok(Self::ColEq(col)),
1 => Ok(Self::ColGt(col)),
2 => Ok(Self::ColLt(col)),
_ => Err(DatabaseError::OperatorError.into()),
}
}
}
/// Zephyr-compatible database trait.
/// Implementations of Zephyr that allow from a database from within
/// a Zephyr execution must implement this trait.
pub trait ZephyrDatabase {
/// Reads the database from raw data.
/// - user id is the identifier of the host, which might be
/// needed for database access control depending on how the
/// implementor initializes the host.
/// - read point hash is the identifier of the slot Zephyr
/// is trying to read from the database.
/// - read data is a slice of integers that define the read
/// instruction that Zephyr is providing to the database implementation
fn read_raw(
&self,
user_id: i64,
read_point_hash: [u8; 16],
read_data: &[i64],
condition: Option<&[WhereCond]>,
condition_args: Option<Vec<Vec<u8>>>,
) -> Result<Vec<u8>, DatabaseError>;
/// Writes the database from raw data.
/// - user id is the identifier of the host, which might be
/// needed for database access control depending on how the
/// implementor initializes the host.
/// - written point hash is the identifier of the slot in
/// the database that Zephyr is writing to.
/// - write data is a slice of integers with instructions
/// about the write operation.
/// - written is a multidimensional vector with bytes being
/// written as a single value in the database.
fn write_raw(
&self,
user_id: i64,
written_point_hash: [u8; 16],
write_data: &[i64],
written: Vec<Vec<u8>>,
) -> Result<(), DatabaseError>;
/// Updates database rows from raw data.
/// - user id is the identifier of the host, which might be
/// needed for database access control depending on how the
/// implementor initializes the host.
/// - written point hash is the identifier of the slot in
/// the database that Zephyr is writing to.
/// - write data is a slice of integers with instructions
/// about the write operation.
/// - written is a multidimensional vector with bytes being
/// written as a single value in the database.
fn update_raw(
&self,
user_id: i64,
written_point_hash: [u8; 16],
write_data: &[i64],
written: Vec<Vec<u8>>,
condition: &[WhereCond],
condition_args: Vec<Vec<u8>>,
) -> Result<(), DatabaseError>;
}
/// Specify the database permissions that the implementor
/// is granting to Zephyr.
#[derive(Clone)]
pub enum DatabasePermissions {
/// Zephyr can only read the database.
ReadOnly,
/// Zephyr can only write the database.
WriteOnly,
/// Zephyr can both read and write the database.
ReadWrite,
}
/// Database implementation.
/// Wraps the implementor-supplied DB implementation that
/// Zephyr will use to communicate with the database.
#[derive(Clone)]
pub struct DatabaseImpl<DB: ZephyrDatabase> {
/// Permissions granted.
pub permissions: DatabasePermissions,
/// Implementor's database.
pub db: Box<DB>,
}
/// Wrapper of the database implementation.
#[derive(Clone)]
pub struct Database<DB: ZephyrDatabase>(pub(crate) DatabaseImpl<DB>);
impl<DB: ZephyrDatabase + ZephyrStandard> ZephyrStandard for DatabaseImpl<DB> {
fn zephyr_standard() -> Result<Self> {
Ok(Self {
permissions: DatabasePermissions::ReadWrite,
db: Box::new(DB::zephyr_standard()?),
})
}
}
impl<DB: ZephyrDatabase + ZephyrStandard> ZephyrStandard for Database<DB> {
fn zephyr_standard() -> Result<Self> {
Ok(Self(DatabaseImpl::zephyr_standard()?))
}
}
impl<DB: ZephyrDatabase + ZephyrMock> ZephyrMock for DatabaseImpl<DB> {
fn mocked() -> Result<Self> {
Ok(Self {
permissions: DatabasePermissions::ReadWrite,
db: Box::new(DB::mocked()?),
})
}
}
impl<DB: ZephyrDatabase + ZephyrMock> ZephyrMock for Database<DB> {
fn mocked() -> Result<Self> {
Ok(Self(DatabaseImpl::mocked()?))
}
}