pub mod model_tests;
pub mod prims;
pub mod values;
pub use prims::install;
pub use values::{
db_value, destructure_db, inst_value, kw_ns, str_val, tx_report_value, DbRef, TxReport,
};
use mino_rs::Value;
pub trait ScriptBackend {
fn open(&mut self, path: Option<&str>) -> Result<i64, String>;
fn close(&mut self, conn: i64) -> Result<(), String>;
fn basis_tx(&self, conn: i64) -> Result<i64, String>;
fn transact(&mut self, conn: i64, edn: &str) -> Result<TxReport, String>;
fn with(&mut self, db: &DbRef, edn: &str) -> Result<(i64, TxReport), String>;
fn q(&self, db: &DbRef, query_edn: &str) -> Result<Value, String>;
fn q_with_inputs(
&self,
db: &DbRef,
query_edn: &str,
inputs: &[serde_json::Value],
) -> Result<Value, String> {
if inputs.is_empty() {
self.q(db, query_edn)
} else {
Err("this backend does not take :in arguments".into())
}
}
fn pull(&self, db: &DbRef, eid: i64, pattern_edn: &str) -> Result<Value, String>;
fn datoms(&self, db: &DbRef) -> Result<Value, String>;
fn resolve_eid(&self, db: &DbRef, arg: &Value) -> Result<i64, String>;
fn entity(&self, db: &DbRef, eid: i64) -> Result<Value, String> {
use mino_rs::collections::map::PMap;
use mino_rs::{Gc, Value as V};
let pulled = self.pull(db, eid, "[*]")?;
let mut m = PMap::empty().assoc(values::kw_ns("db", "id"), V::Int(eid));
if let V::Map(ref pm) = pulled {
for (k, v) in pm.entries() {
m = m.assoc(k.clone(), v.clone());
}
}
Ok(V::Map(Gc::new(m)))
}
fn read(&self, db: &DbRef, eid: i64, attr: &str) -> Result<Value, String> {
use mino_rs::collections::map::PSet;
use mino_rs::{Gc, Value as V};
let query = format!("[:find [?v ...] :where [{eid} {attr} ?v]]");
match self.q(db, &query)? {
V::Vector(ref v) => match v.len() {
0 => Ok(V::Nil),
1 => Ok(v.nth(0).cloned().unwrap_or(V::Nil)),
_ => {
let mut set = PSet::empty();
for x in v.iter() {
set = set.conj(x.clone());
}
Ok(V::Set(Gc::new(set)))
}
},
V::Nil => Ok(V::Nil),
other => Ok(other),
}
}
fn entities(&self, db: &DbRef, attr: &str) -> Result<Value, String> {
use mino_rs::collections::map::PSet;
use mino_rs::{Gc, Value as V};
let query = format!("[:find [?e ...] :where [?e {attr} _]]");
let mut set = PSet::empty();
if let V::Vector(ref v) = self.q(db, &query)? {
for e in v.iter() {
set = set.conj(e.clone());
}
}
Ok(V::Set(Gc::new(set)))
}
}