use std::fmt::Debug;
use std::sync::Arc;
use anyhow::{Result, bail};
use crate::catalog;
use crate::cnf::CommonConfig;
use crate::err::Error;
use crate::expr::Base;
use crate::iam::Auth;
#[derive(Clone, Debug)]
pub struct Options {
pub(crate) ns: Option<Arc<str>>,
pub(crate) db: Option<Arc<str>>,
pub(crate) dive: u32,
pub(crate) auth: Arc<Auth>,
pub(crate) force: Force,
pub(crate) perms: bool,
pub(crate) permission_predicate: bool,
pub(crate) import: bool,
pub(crate) version: Option<u64>,
async_event_depth: Option<u16>,
}
#[derive(Clone, Debug)]
pub enum Force {
All,
None,
Table(Arc<[catalog::TableDefinition]>),
}
impl Options {
pub(crate) fn new(config: &CommonConfig) -> Self {
Self {
ns: None,
db: None,
dive: config.max_computation_depth,
perms: true,
permission_predicate: false,
force: Force::None,
import: false,
auth: Arc::new(Auth::default()),
version: None,
async_event_depth: None,
}
}
pub fn set_ns(&mut self, ns: Option<Arc<str>>) {
self.ns = ns
}
pub fn set_db(&mut self, db: Option<Arc<str>>) {
self.db = db
}
pub fn with_max_computation_depth(mut self, depth: u32) -> Self {
self.dive = depth;
self
}
pub(crate) fn with_dive_consumed(&self, depth: u32) -> Self {
Self {
dive: self.dive.saturating_sub(depth),
..self.clone()
}
}
pub fn with_ns(mut self, ns: Option<Arc<str>>) -> Self {
self.ns = ns;
self
}
pub fn with_db(mut self, db: Option<Arc<str>>) -> Self {
self.db = db;
self
}
pub fn with_auth(mut self, auth: Arc<Auth>) -> Self {
self.auth = auth;
self
}
pub fn with_perms(mut self, perms: bool) -> Self {
self.perms = perms;
self
}
pub fn with_force(mut self, force: Force) -> Self {
self.force = force;
self
}
pub fn with_import(mut self, import: bool) -> Self {
self.set_import(import);
self
}
pub fn set_import(&mut self, import: bool) {
self.import = import;
}
pub fn with_version(mut self, version: Option<u64>) -> Self {
self.version = version;
self
}
pub fn with_async_event_depth(mut self, depth: u16) -> Self {
self.async_event_depth = Some(depth);
self
}
pub fn new_with_auth(&self, auth: Arc<Auth>) -> Self {
Self {
auth,
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
perms: self.perms,
..self.clone()
}
}
pub fn new_with_perms(&self, perms: bool) -> Self {
Self {
perms,
..self.clone()
}
}
pub fn new_for_permission_predicate(&self) -> Self {
Self {
perms: false,
permission_predicate: true,
..self.clone()
}
}
pub fn new_with_force(&self, force: Force) -> Self {
Self {
force,
..self.clone()
}
}
pub fn new_with_import(&self, import: bool) -> Self {
Self {
import,
..self.clone()
}
}
pub(crate) fn selected_base(&self) -> Result<Base, Error> {
match (self.ns.as_ref(), self.db.as_ref()) {
(None, None) => Ok(Base::Root),
(Some(_), None) => Ok(Base::Ns),
(Some(_), Some(_)) => Ok(Base::Db),
(None, Some(_)) => Err(Error::NsEmpty),
}
}
pub(crate) fn dive(&self, cost: u8) -> Result<Self, Error> {
if self.dive < cost as u32 {
return Err(Error::ComputationDepthExceeded);
}
Ok(Self {
dive: self.dive - cost as u32,
..self.clone()
})
}
#[inline(always)]
pub fn ns(&self) -> Result<&str> {
self.ns.as_deref().ok_or_else(|| Error::NsEmpty).map_err(anyhow::Error::new)
}
pub(crate) fn arc_ns(&self) -> Result<Arc<str>> {
self.ns.clone().ok_or_else(|| Error::NsEmpty).map_err(anyhow::Error::new)
}
#[inline(always)]
pub fn db(&self) -> Result<&str> {
self.db.as_deref().ok_or_else(|| Error::DbEmpty).map_err(anyhow::Error::new)
}
pub(crate) fn arc_db(&self) -> Result<Arc<str>> {
self.db.clone().ok_or_else(|| Error::DbEmpty).map_err(anyhow::Error::new)
}
#[inline(always)]
pub fn ns_db(&self) -> Result<(&str, &str)> {
Ok((self.ns()?, self.db()?))
}
pub(crate) fn arc_ns_db(&self) -> Result<(Arc<str>, Arc<str>)> {
Ok((self.arc_ns()?, self.arc_db()?))
}
pub fn ns_db_arc(&self) -> Result<(&str, &str)> {
Ok((self.ns()?, self.db()?))
}
#[inline(always)]
pub fn valid_for_ns(&self) -> Result<()> {
if self.ns.is_none() {
bail!(Error::NsEmpty);
}
Ok(())
}
#[inline(always)]
pub fn valid_for_db(&self) -> Result<()> {
if self.ns.is_none() {
bail!(Error::NsEmpty);
}
if self.db.is_none() {
bail!(Error::DbEmpty);
}
Ok(())
}
pub(crate) fn async_event_depth(&self) -> Option<u16> {
self.async_event_depth
}
}
const _: () = assert!(std::mem::size_of::<Options>() <= 128);