diff --git a/src/flow.rs b/src/flow.rs index 8675398..c832713 100644 --- a/src/flow.rs +++ b/src/flow.rs @@ -4,5 +4,6 @@ pub mod binary; pub mod comparator; +pub mod query; pub mod speculative; pub mod traversible; diff --git a/src/flow/query.rs b/src/flow/query.rs new file mode 100644 index 0000000..86cca5f --- /dev/null +++ b/src/flow/query.rs @@ -0,0 +1,137 @@ +use std::marker::PhantomData; + +pub trait Query: Copy { + type Output; +} + +pub trait QueryConvert: Query { + fn convert(e: E) -> Self::Output; +} + +pub trait QueryEnrich: Query { + fn enrich(&self, output: Self::Output, a: A) -> Self::Output; +} + +pub trait QueryChain: Query { + type Original: Query; + + fn original(&self) -> &Self::Original; +} + +pub struct StartQuery(Q, PhantomData); + +impl Clone for StartQuery { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Copy for StartQuery {} + +impl Query for StartQuery { + type Output = Q::Output; +} + +impl QueryChain for StartQuery { + type Original = Q; + + fn original(&self) -> &Self::Original { + &self.0 + } +} + +struct BootQuery; +struct IgnoreQuery; + +impl QueryEnrich for StartQuery +where + Q: QueryEnrich, +{ + fn enrich(&self, output: Self::Output, a: A) -> Self::Output { + self.0.enrich(output, a) + } +} + +impl QueryEnrich for StartQuery { + fn enrich(&self, output: Self::Output, _a: A) -> Self::Output { + output + } +} + +impl QueryConvert for StartQuery +where + Q: QueryConvert, +{ + fn convert(e: E) -> Self::Output { + Q::convert(e) + } +} + +pub struct ChainQuery(Q, PhantomData); + +impl Clone for ChainQuery { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Copy for ChainQuery {} + +impl Query for ChainQuery { + type Output = Q::Output; +} + +impl QueryChain for ChainQuery { + type Original = Q::Original; + + fn original(&self) -> &Self::Original { + self.0.original() + } +} + +impl> QueryEnrich for ChainQuery +where + Q: QueryEnrich, + Q::Original: QueryEnrich, +{ + fn enrich(&self, output: Self::Output, a: Ax) -> Self::Output { + self.0.enrich(a.enrich(output, self.original()), a) + } +} + +impl QueryConvert for ChainQuery +where + Q::Original: QueryConvert, +{ + fn convert(e: E) -> Self::Output { + >::convert(e) + } +} + +trait QueryExt: Query { + fn start(self) -> StartQuery { + StartQuery(self, PhantomData) + } + + fn enriching(self) -> ChainQuery + where + Self: QueryChain, + Self::Original: QueryEnrich, + { + ChainQuery(self, PhantomData) + } +} + +impl QueryExt for Q {} + +pub trait Enriches { + fn enrich( + &self, + output: Output, + query: &impl QueryEnrich, + ) -> Output; +} + +pub trait QueryJoin: QueryEnrich<::Output> {} + +impl::Output>> QueryJoin for Q {}