use crate::graph::GraphStorage;
use crate::traversal::step::map_steps::temporal::{
ZoneArg, check_zone, incoming_temporal, replaced, temporal_error, zone_of,
};
use crate::value::dt::DT;
use crate::value::literal::TokenLiteral;
use crate::value::temporal::arith;
use crate::*;
#[derive(Clone)]
struct StepDatePart {
part: DT,
zone: Option<ZoneArg>,
}
impl fmt::Display for StepDatePart {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "date_part({}", self.part.token_literal())?;
if let Some(zone) = &self.zone {
write!(f, ", {}", zone.literal())?;
}
f.write_str(")")
}
}
fn step<'g, S: GraphStorage + 'g>(part: DT, zone: Option<&str>) -> GraphStep<'g, S> {
GraphStep::Map(
"date_part",
Box::new(StepDatePart {
part,
zone: zone.map(ZoneArg::parse),
}),
)
}
macro_rules! date_part_builders {
() => {
pub fn date_part(self, part: DT) -> Self {
self.push_step(step(part, None))
}
pub fn date_part_in(self, part: DT, zone: &str) -> Self {
self.push_step(step(part, Some(zone)))
}
};
}
impl<'g, S: GraphStorage + 'g> GraphTraversalSource<'g, S> {
date_part_builders!();
}
impl<'g, S: GraphStorage + 'g> AnonymousTraversal<'g, S> {
date_part_builders!();
}
impl __ {
pub fn date_part<'g, S: GraphStorage + 'g>(part: DT) -> AnonymousTraversal<'g, S> {
AnonymousTraversal::new().date_part(part)
}
}
impl<'g, S: GraphStorage + 'g> GraphStepMap<'g, S> for StepDatePart {
fn process(
&self,
context: &mut TraverserContext<'_, S>,
source: Traverser<S>,
) -> TraverserResult<Traverser<S>> {
let value = incoming_temporal(context, &source.value, "date_part", "a date or time")?;
let zone = zone_of(&self.zone, "date_part")?;
let result = arith::part(value, self.part, zone)
.map_err(|error| temporal_error("date_part", error))?;
Ok(replaced(
source,
TraverserValue::Computed(ElementProperty::Number(result), None),
))
}
fn may_filter(&self) -> bool {
true
}
fn plan_check(&self) -> TraverserResult<()> {
check_zone(&self.zone, "date_part")
}
fn clone_box(&self) -> Box<dyn GraphStepMap<'g, S> + 'g> {
Box::new(self.clone())
}
}