pub mod doc;
mod local;
mod session;
mod store;
pub use doc::{Doc, Options};
#[derive(Clone, Debug)]
pub struct MountSpec {
pub name: Option<String>,
pub path: std::path::PathBuf,
}
impl MountSpec {
pub fn parse(arg: &str) -> MountSpec {
if let Some((name, target)) = arg.split_once('=')
&& !name.is_empty()
&& !target.is_empty()
&& name
.chars()
.all(|c| c.is_alphanumeric() || c == '_' || c == '-')
{
return MountSpec {
name: Some(name.to_string()),
path: std::path::PathBuf::from(target),
};
}
MountSpec {
name: None,
path: std::path::PathBuf::from(arg),
}
}
}
pub use local::LocalExecutor;
pub use session::Session;
pub use store::{MemStore, SessionState, Store};
#[cfg(feature = "native")]
pub use store::FileStore;
use quarb::Value;
#[derive(Clone, Debug)]
pub enum Cell {
Node(String),
Value(Value),
}
impl Cell {
pub fn display(&self) -> String {
match self {
Cell::Node(s) => s.clone(),
Cell::Value(v) => v.to_string(),
}
}
}
pub trait Executor {
fn run(&self, query: &str) -> anyhow::Result<Vec<Cell>>;
fn run_fresh(&self, query: &str) -> anyhow::Result<Vec<Cell>> {
self.run(query)
}
}
#[cfg(feature = "native")]
mod daemon;
#[cfg(feature = "native")]
pub use daemon::DaemonExecutor;
#[cfg(test)]
mod mount_spec_tests {
use super::MountSpec;
#[test]
fn name_target_splits() {
let spec = MountSpec::parse("t=data/titanic.csv");
assert_eq!(spec.name.as_deref(), Some("t"));
assert_eq!(spec.path.to_str(), Some("data/titanic.csv"));
let spec = MountSpec::parse("births-2=x.json");
assert_eq!(spec.name.as_deref(), Some("births-2"));
}
#[test]
fn bare_paths_stay_bare() {
for arg in [
"titanic.csv",
"git:.",
"a/b=c.json",
"=x.json",
"name=",
] {
let spec = MountSpec::parse(arg);
assert!(spec.name.is_none(), "{arg} should not split");
assert_eq!(spec.path.to_str(), Some(arg));
}
}
}