use std::sync::Arc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsError;
use crate::storage::cow::Graph as InnerGraph;
use crate::traversal::aggregate::{GroupKey, GroupValue};
use crate::traversal::repeat::RepeatConfig;
use crate::traversal::transform::functional::Projection;
use crate::traversal::transform::order::{Order, OrderKey};
use crate::value::Value;
use crate::wasm::traversal::{Traversal, TraversalType};
use crate::wasm::types::js_to_u64;
#[wasm_bindgen]
pub struct OrderBuilder {
graph: Arc<InnerGraph>,
steps: Vec<Box<dyn crate::traversal::DynStep>>,
output_type: TraversalType,
keys: Vec<OrderKey>,
}
impl OrderBuilder {
pub(crate) fn new(traversal: Traversal) -> Self {
Self {
graph: traversal.graph.clone(),
steps: traversal.steps,
output_type: traversal.output_type,
keys: Vec::new(),
}
}
}
#[wasm_bindgen]
impl OrderBuilder {
#[wasm_bindgen(js_name = "byAsc")]
pub fn by_asc(mut self) -> OrderBuilder {
self.keys.push(OrderKey::Natural(Order::Asc));
self
}
#[wasm_bindgen(js_name = "byDesc")]
pub fn by_desc(mut self) -> OrderBuilder {
self.keys.push(OrderKey::Natural(Order::Desc));
self
}
#[wasm_bindgen(js_name = "byKeyAsc")]
pub fn by_key_asc(mut self, key: &str) -> OrderBuilder {
self.keys
.push(OrderKey::Property(key.to_string(), Order::Asc));
self
}
#[wasm_bindgen(js_name = "byKeyDesc")]
pub fn by_key_desc(mut self, key: &str) -> OrderBuilder {
self.keys
.push(OrderKey::Property(key.to_string(), Order::Desc));
self
}
#[wasm_bindgen(js_name = "byTraversalAsc")]
pub fn by_traversal_asc(mut self, traversal: Traversal) -> OrderBuilder {
let core_traversal = traversal.into_core_traversal();
self.keys
.push(OrderKey::Traversal(core_traversal, Order::Asc));
self
}
#[wasm_bindgen(js_name = "byTraversalDesc")]
pub fn by_traversal_desc(mut self, traversal: Traversal) -> OrderBuilder {
let core_traversal = traversal.into_core_traversal();
self.keys
.push(OrderKey::Traversal(core_traversal, Order::Desc));
self
}
pub fn build(mut self) -> Traversal {
if self.keys.is_empty() {
self.keys.push(OrderKey::Natural(Order::Asc));
}
let step = crate::traversal::OrderStep::with_keys(self.keys);
self.steps.push(Box::new(step));
Traversal {
graph: self.graph,
source: crate::wasm::traversal::TraversalSource::Anonymous, steps: self.steps,
output_type: self.output_type,
}
}
}
#[wasm_bindgen]
pub struct ProjectBuilder {
graph: Arc<InnerGraph>,
steps: Vec<Box<dyn crate::traversal::DynStep>>,
#[allow(dead_code)]
output_type: TraversalType,
keys: Vec<String>,
projections: Vec<Projection>,
}
impl ProjectBuilder {
pub(crate) fn new(traversal: Traversal, keys: Vec<String>) -> Self {
Self {
graph: traversal.graph.clone(),
steps: traversal.steps,
output_type: traversal.output_type,
keys,
projections: Vec::new(),
}
}
}
#[wasm_bindgen]
impl ProjectBuilder {
#[wasm_bindgen(js_name = "byKey")]
pub fn by_key(mut self, property_key: &str) -> ProjectBuilder {
self.projections
.push(Projection::Key(property_key.to_string()));
self
}
#[wasm_bindgen(js_name = "byTraversal")]
pub fn by_traversal(mut self, traversal: Traversal) -> ProjectBuilder {
let core_traversal = traversal.into_core_traversal();
self.projections.push(Projection::Traversal(core_traversal));
self
}
pub fn build(mut self) -> Traversal {
while self.projections.len() < self.keys.len() {
let key = &self.keys[self.projections.len()];
self.projections.push(Projection::Key(key.clone()));
}
let step = crate::traversal::ProjectStep::new(self.keys, self.projections);
self.steps.push(Box::new(step));
Traversal {
graph: self.graph,
source: crate::wasm::traversal::TraversalSource::Anonymous,
steps: self.steps,
output_type: TraversalType::Value,
}
}
}
#[wasm_bindgen]
pub struct GroupBuilder {
graph: Arc<InnerGraph>,
steps: Vec<Box<dyn crate::traversal::DynStep>>,
#[allow(dead_code)]
output_type: TraversalType,
key_selector: Option<GroupKey>,
value_collector: Option<GroupValue>,
}
impl GroupBuilder {
pub(crate) fn new(traversal: Traversal) -> Self {
Self {
graph: traversal.graph.clone(),
steps: traversal.steps,
output_type: traversal.output_type,
key_selector: None,
value_collector: None,
}
}
}
#[wasm_bindgen]
impl GroupBuilder {
#[wasm_bindgen(js_name = "byLabel")]
pub fn by_label(mut self) -> GroupBuilder {
self.key_selector = Some(GroupKey::Label);
self
}
#[wasm_bindgen(js_name = "byKey")]
pub fn by_key(mut self, key: &str) -> GroupBuilder {
self.key_selector = Some(GroupKey::Property(key.to_string()));
self
}
#[wasm_bindgen(js_name = "byTraversal")]
pub fn by_traversal(mut self, traversal: Traversal) -> GroupBuilder {
let core_traversal = traversal.into_core_traversal();
self.key_selector = Some(GroupKey::Traversal(Box::new(core_traversal)));
self
}
#[wasm_bindgen(js_name = "valuesByTraversal")]
pub fn values_by_traversal(mut self, traversal: Traversal) -> GroupBuilder {
let core_traversal = traversal.into_core_traversal();
self.value_collector = Some(GroupValue::Traversal(Box::new(core_traversal)));
self
}
#[wasm_bindgen(js_name = "valuesFold")]
pub fn values_fold(mut self) -> GroupBuilder {
self.value_collector = Some(GroupValue::Identity);
self
}
#[wasm_bindgen(js_name = "valuesByKey")]
pub fn values_by_key(mut self, key: &str) -> GroupBuilder {
self.value_collector = Some(GroupValue::Property(key.to_string()));
self
}
pub fn build(mut self) -> Traversal {
let key_selector = self.key_selector.unwrap_or(GroupKey::Label);
let value_collector = self.value_collector.unwrap_or(GroupValue::Identity);
let step = crate::traversal::GroupStep::with_selectors(key_selector, value_collector);
self.steps.push(Box::new(step));
Traversal {
graph: self.graph,
source: crate::wasm::traversal::TraversalSource::Anonymous,
steps: self.steps,
output_type: TraversalType::Value,
}
}
}
#[wasm_bindgen]
pub struct GroupCountBuilder {
graph: Arc<InnerGraph>,
steps: Vec<Box<dyn crate::traversal::DynStep>>,
#[allow(dead_code)]
output_type: TraversalType,
key_selector: Option<GroupKey>,
}
impl GroupCountBuilder {
pub(crate) fn new(traversal: Traversal) -> Self {
Self {
graph: traversal.graph.clone(),
steps: traversal.steps,
output_type: traversal.output_type,
key_selector: None,
}
}
}
#[wasm_bindgen]
impl GroupCountBuilder {
#[wasm_bindgen(js_name = "byLabel")]
pub fn by_label(mut self) -> GroupCountBuilder {
self.key_selector = Some(GroupKey::Label);
self
}
#[wasm_bindgen(js_name = "byKey")]
pub fn by_key(mut self, key: &str) -> GroupCountBuilder {
self.key_selector = Some(GroupKey::Property(key.to_string()));
self
}
#[wasm_bindgen(js_name = "byTraversal")]
pub fn by_traversal(mut self, traversal: Traversal) -> GroupCountBuilder {
let core_traversal = traversal.into_core_traversal();
self.key_selector = Some(GroupKey::Traversal(Box::new(core_traversal)));
self
}
pub fn build(mut self) -> Traversal {
let key_selector = self.key_selector.unwrap_or(GroupKey::Label);
let step = crate::traversal::GroupCountStep::new(key_selector);
self.steps.push(Box::new(step));
Traversal {
graph: self.graph,
source: crate::wasm::traversal::TraversalSource::Anonymous,
steps: self.steps,
output_type: TraversalType::Value,
}
}
}
#[wasm_bindgen]
pub struct RepeatBuilder {
graph: Arc<InnerGraph>,
steps: Vec<Box<dyn crate::traversal::DynStep>>,
output_type: TraversalType,
sub_traversal: crate::traversal::Traversal<Value, Value>,
config: RepeatConfig,
}
impl RepeatBuilder {
pub(crate) fn new(traversal: Traversal, sub: Traversal) -> Self {
Self {
graph: traversal.graph.clone(),
steps: traversal.steps,
output_type: traversal.output_type,
sub_traversal: sub.into_core_traversal(),
config: RepeatConfig::new(),
}
}
}
#[wasm_bindgen]
impl RepeatBuilder {
pub fn times(mut self, n: JsValue) -> Result<RepeatBuilder, JsError> {
let num = js_to_u64(n)?;
self.config = self.config.with_times(num as usize);
Ok(self)
}
pub fn until(mut self, condition: Traversal) -> RepeatBuilder {
let core_traversal = condition.into_core_traversal();
self.config = self.config.with_until(core_traversal);
self
}
pub fn emit(mut self) -> RepeatBuilder {
self.config = self.config.with_emit();
self
}
#[wasm_bindgen(js_name = "emitIf")]
pub fn emit_if(mut self, condition: Traversal) -> RepeatBuilder {
let core_traversal = condition.into_core_traversal();
self.config = self.config.with_emit_if(core_traversal);
self
}
pub fn build(mut self) -> Traversal {
let step = crate::traversal::RepeatStep::with_config(self.sub_traversal, self.config);
self.steps.push(Box::new(step));
Traversal {
graph: self.graph,
source: crate::wasm::traversal::TraversalSource::Anonymous,
steps: self.steps,
output_type: self.output_type,
}
}
}