use std::io::Write;
use diesel::{
backend::Backend,
deserialize::{self, FromSql},
serialize::{self, Output, ToSql},
sql_types::Text,
sqlite::Sqlite,
};
use crate::state::merkle::sql::store::schema::sqlite_merkle_radix_tree_node;
#[derive(Insertable, Queryable, QueryableByName, Identifiable)]
#[cfg_attr(test, derive(Debug, PartialEq))]
#[table_name = "sqlite_merkle_radix_tree_node"]
#[primary_key(hash, tree_id)]
pub struct MerkleRadixTreeNode {
pub hash: String,
pub tree_id: i64,
pub leaf_id: Option<i64>,
pub children: Children,
pub reference: i64,
}
impl MerkleRadixTreeNode {
pub fn new<S: Into<String>>(hash: S, tree_id: i64) -> Self {
Self::inner_new(hash.into(), tree_id)
}
fn inner_new(hash: String, tree_id: i64) -> Self {
Self {
hash,
tree_id,
leaf_id: None,
children: Children(vec![None; 256]),
reference: 1,
}
}
pub fn with_children(mut self, children: Vec<Option<String>>) -> Self {
self.children = Children(children);
self
}
pub fn with_leaf_id(mut self, leaf_id: Option<i64>) -> Self {
self.leaf_id = leaf_id;
self
}
}
#[derive(AsExpression, Debug, FromSqlRow, Deserialize, Serialize)]
#[cfg_attr(test, derive(PartialEq))]
#[sql_type = "diesel::sql_types::Text"]
pub struct Children(pub Vec<Option<String>>);
impl FromSql<Text, Sqlite> for Children {
fn from_sql(bytes: Option<&<Sqlite as Backend>::RawValue>) -> deserialize::Result<Self> {
let t = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?;
Ok(serde_json::from_str(&t)?)
}
}
impl ToSql<Text, Sqlite> for Children {
fn to_sql<W: Write>(&self, out: &mut Output<W, Sqlite>) -> serialize::Result {
let s = serde_json::to_string(&self.0)?;
<String as ToSql<Text, Sqlite>>::to_sql(&s, out)
}
}