use crate::graph::GraphStorage;
use crate::traversal::step::local_scope::local_len;
use crate::value::Scope;
use crate::*;
#[derive(Default, Clone)]
struct StepCountLocal {}
impl fmt::Display for StepCountLocal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "count(Scope.local)")
}
}
impl<'g, S: GraphStorage + 'g> GraphTraversalSource<'g, S> {
pub fn count_scoped(self, scope: Scope) -> Self {
match scope {
Scope::Global => self.count(),
Scope::Local => {
self.push_step(GraphStep::Map("count", Box::new(StepCountLocal::default())))
}
}
}
}
impl __ {
pub fn count_scoped<'g, S: GraphStorage + 'g>(scope: Scope) -> AnonymousTraversal<'g, S> {
AnonymousTraversal::new().count_scoped(scope)
}
}
impl<'g, S: GraphStorage + 'g> AnonymousTraversal<'g, S> {
pub fn count_scoped(self, scope: Scope) -> Self {
match scope {
Scope::Global => self.count(),
Scope::Local => {
self.push_step(GraphStep::Map("count", Box::new(StepCountLocal::default())))
}
}
}
}
impl<'g, S: GraphStorage + 'g> GraphStepMap<'g, S> for StepCountLocal {
#[inline]
fn process(
&self,
context: &mut TraverserContext<'_, S>,
source: Traverser<S>,
) -> TraverserResult<Traverser<S>> {
let length = local_len(context, &source.value)?;
Ok(Traverser::with_parts(
TraverserValue::Computed(ElementProperty::Number(length.into()), None),
source.path,
source.bulk,
source.sack,
))
}
fn clone_box(&self) -> Box<dyn GraphStepMap<'g, S> + 'g> {
Box::new(self.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fold() {
test_dual!(
graph: GraphSource::tinkerpop_modern(),
rust: |g| g.v(None).fold().count_scoped(Scope::Local).to_list(),
rhai: [
r#"g.V().fold().count(Scope.local)"#,
r#"g.v().fold().count(Scope::local)"#,
],
assert: |res| assert_eq!(res, vec![ElementProperty::Number(6.into())]),
);
}
#[test]
fn map() {
test_dual!(
graph: GraphSource::tinkerpop_modern(),
rust: |g| g.v(None).group().by(By::Label).count_scoped(Scope::Local).to_list(),
rhai: [
r#"g.V().group().by(T.label).count(Scope.local)"#,
r#"g.v().group().by(T.label).count(Scope::Local)"#,
],
assert: |res| assert_eq!(res, vec![ElementProperty::Number(2.into())]),
);
}
#[test]
fn scalar() {
test_dual!(
graph: GraphSource::tinkerpop_modern(),
rust: |g| g.v(None).count_scoped(Scope::Local).to_list(),
rhai: [
r#"g.V().count(Scope.local)"#,
r#"g.v().count(Scope::local)"#,
],
assert: |res| {
assert_eq!(res.len(), 6);
assert!(res.iter().all(|r| r.as_i64() == Some(1)));
},
);
}
#[test]
fn global_is_count() {
test_dual!(
graph: GraphSource::tinkerpop_modern(),
rust: |g| g.v(None).count_scoped(Scope::Global).to_list(),
rhai: [
r#"g.V().count(Scope.global)"#,
r#"g.v().count(Scope::Global)"#,
],
assert: |res| assert_eq!(res, vec![ElementProperty::Number(6.into())]),
);
}
#[test]
fn profile() {
let graph = GraphSource::tinkerpop_modern();
let g_lock = graph.read();
let g = g_lock.traversal();
let result = g
.v(None)
.fold()
.count_scoped(Scope::Local)
.profile()
.unwrap();
assert!(result.to_string().contains("count(Scope.local)"));
}
}