use core::marker::ConstParamTy;
use core::marker::PhantomData;
#[derive(ConstParamTy, PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum OcpqScopeKind {
Open,
Closed,
SingleType,
}
pub struct ObjectScopeConst<const KIND: OcpqScopeKind> {
object_types: alloc::vec::Vec<alloc::string::String>,
}
extern crate alloc;
impl<const KIND: OcpqScopeKind> ObjectScopeConst<KIND> {
pub fn new<I, S>(types: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<alloc::string::String>,
{
ObjectScopeConst {
object_types: types.into_iter().map(Into::into).collect(),
}
}
pub fn object_types(&self) -> &[alloc::string::String] {
&self.object_types
}
pub fn is_empty(&self) -> bool {
self.object_types.is_empty()
}
pub const fn kind(&self) -> OcpqScopeKind {
KIND
}
}
#[derive(ConstParamTy, PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum EventPredicateKind {
ActivityEquals,
AttributeEquals,
TimestampInRange,
}
#[derive(ConstParamTy, PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum ObjectPredicateKind {
AttributeEquals,
TypeEquals,
}
pub struct TypedEventPredicate<const KIND: EventPredicateKind> {
expression: alloc::string::String,
}
impl<const KIND: EventPredicateKind> TypedEventPredicate<KIND> {
pub fn new(expression: impl Into<alloc::string::String>) -> Self {
TypedEventPredicate {
expression: expression.into(),
}
}
pub fn expression(&self) -> &str {
&self.expression
}
pub const fn kind(&self) -> EventPredicateKind {
KIND
}
}
pub struct TypedObjectPredicate<const KIND: ObjectPredicateKind> {
expression: alloc::string::String,
}
impl<const KIND: ObjectPredicateKind> TypedObjectPredicate<KIND> {
pub fn new(expression: impl Into<alloc::string::String>) -> Self {
TypedObjectPredicate {
expression: expression.into(),
}
}
pub fn expression(&self) -> &str {
&self.expression
}
pub const fn kind(&self) -> ObjectPredicateKind {
KIND
}
}
#[derive(ConstParamTy, PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum RelationPredicateKind {
E2O,
O2O,
TimeBetweenEvents,
}
pub struct TypedRelationPredicate<const KIND: RelationPredicateKind> {
expression: alloc::string::String,
}
impl<const KIND: RelationPredicateKind> TypedRelationPredicate<KIND> {
pub fn new(expression: impl Into<alloc::string::String>) -> Self {
TypedRelationPredicate {
expression: expression.into(),
}
}
pub fn expression(&self) -> &str {
&self.expression
}
pub const fn kind(&self) -> RelationPredicateKind {
KIND
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct EventPredicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct ObjectPredicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct RelationPredicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct TemporalPredicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct CardinalityPredicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct NestedQuery;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Constraint;
mod predicate_seal {
pub trait Sealed {}
impl Sealed for super::EventPredicate {}
impl Sealed for super::ObjectPredicate {}
impl Sealed for super::RelationPredicate {}
impl Sealed for super::TemporalPredicate {}
impl Sealed for super::CardinalityPredicate {}
impl Sealed for super::NestedQuery {}
impl Sealed for super::Constraint {}
}
pub trait IsOcpqPredicate: predicate_seal::Sealed {}
impl IsOcpqPredicate for EventPredicate {}
impl IsOcpqPredicate for ObjectPredicate {}
impl IsOcpqPredicate for RelationPredicate {}
impl IsOcpqPredicate for TemporalPredicate {}
impl IsOcpqPredicate for CardinalityPredicate {}
impl IsOcpqPredicate for NestedQuery {}
impl IsOcpqPredicate for Constraint {}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ObjectScope {
pub object_types: Vec<String>,
}
impl ObjectScope {
pub fn new<I, S>(types: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
Self {
object_types: types.into_iter().map(Into::into).collect(),
}
}
pub fn is_empty(&self) -> bool {
self.object_types.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PredicateKind {
Event(String),
Object(String),
Relation(String),
Temporal(String),
Cardinality {
min: usize,
max: usize,
},
Nested(usize),
E2ORelation {
event_var: String,
object_var: String,
qualifier: Option<String>,
},
O2ORelation {
object_var1: String,
object_var2: String,
qualifier: Option<String>,
},
TimeBetweenEvents {
event_var1: String,
event_var2: String,
t_min: u64,
t_max: u64,
},
ChildSetBound {
branch_label: String,
min: usize,
max: usize,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Predicate<W = ()> {
pub kind: PredicateKind,
pub witness: PhantomData<W>,
}
impl<W> Predicate<W> {
pub fn new(kind: PredicateKind) -> Self {
Self {
kind,
witness: PhantomData,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct OcpqQuery {
pub scope: ObjectScope,
pub predicates: Vec<Predicate>,
pub sub_queries: Vec<OcpqQuery>,
}
impl OcpqQuery {
pub fn new(scope: ObjectScope) -> Self {
Self {
scope,
predicates: Vec::new(),
sub_queries: Vec::new(),
}
}
}
pub struct OcpqQueryConst<const KIND: OcpqScopeKind> {
scope: ObjectScopeConst<KIND>,
predicates: alloc::vec::Vec<Predicate>,
sub_queries: alloc::vec::Vec<OcpqQueryConst<KIND>>,
}
impl<const KIND: OcpqScopeKind> OcpqQueryConst<KIND> {
pub fn new(scope: ObjectScopeConst<KIND>) -> Self {
OcpqQueryConst {
scope,
predicates: alloc::vec::Vec::new(),
sub_queries: alloc::vec::Vec::new(),
}
}
pub fn scope(&self) -> &ObjectScopeConst<KIND> {
&self.scope
}
pub fn predicates(&self) -> &[Predicate] {
&self.predicates
}
pub const fn scope_kind(&self) -> OcpqScopeKind {
KIND
}
pub fn sub_queries(&self) -> &[OcpqQueryConst<KIND>] {
&self.sub_queries
}
pub fn with_predicate(mut self, predicate: Predicate) -> Self {
self.predicates.push(predicate);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum OcpqRefusal {
MissingObjectScope,
UnknownObjectType,
UnknownEventType,
InvalidCardinality,
UnsafeProjection,
FlatteningRequired,
InvalidChildSetBound,
EmptyScopeType,
ConflictingPredicateKinds,
UnboundVariable,
}
impl core::fmt::Display for OcpqRefusal {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let law = match self {
OcpqRefusal::MissingObjectScope => "MissingObjectScope",
OcpqRefusal::UnknownObjectType => "UnknownObjectType",
OcpqRefusal::UnknownEventType => "UnknownEventType",
OcpqRefusal::InvalidCardinality => "InvalidCardinality",
OcpqRefusal::UnsafeProjection => "UnsafeProjection",
OcpqRefusal::FlatteningRequired => "FlatteningRequired",
OcpqRefusal::InvalidChildSetBound => "InvalidChildSetBound",
OcpqRefusal::EmptyScopeType => "EmptyScopeType",
OcpqRefusal::ConflictingPredicateKinds => "ConflictingPredicateKinds",
OcpqRefusal::UnboundVariable => "UnboundVariable",
};
write!(f, "OCPQ refused: {law}")
}
}
pub struct CardinalityBoundConst<const MIN: usize, const MAX: usize>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
_private: (),
}
impl<const MIN: usize, const MAX: usize> CardinalityBoundConst<MIN, MAX>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
pub const fn new() -> Self {
CardinalityBoundConst { _private: () }
}
pub const fn min(&self) -> usize {
MIN
}
pub const fn max(&self) -> usize {
MAX
}
}
impl<const MIN: usize, const MAX: usize> Default for CardinalityBoundConst<MIN, MAX>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
fn default() -> Self {
Self::new()
}
}
pub struct ChildSetBoundConst<const LABEL: &'static str, const MIN: usize, const MAX: usize>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
_private: (),
}
impl<const LABEL: &'static str, const MIN: usize, const MAX: usize>
ChildSetBoundConst<LABEL, MIN, MAX>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
pub const fn new() -> Self {
ChildSetBoundConst { _private: () }
}
pub const fn branch_label(&self) -> &'static str {
LABEL
}
pub const fn min(&self) -> usize {
MIN
}
pub const fn max(&self) -> usize {
MAX
}
}
impl<const LABEL: &'static str, const MIN: usize, const MAX: usize> Default
for ChildSetBoundConst<LABEL, MIN, MAX>
where
crate::law::Require<{ MIN <= MAX }>: crate::law::IsTrue,
{
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OcpqQueryMonomorphic<ObjectTypes, EventTypes> {
pub query: OcpqQuery,
pub _objects: core::marker::PhantomData<ObjectTypes>,
pub _events: core::marker::PhantomData<EventTypes>,
}
impl<ObjectTypes, EventTypes> OcpqQueryMonomorphic<ObjectTypes, EventTypes> {
pub fn new(query: OcpqQuery) -> Self {
Self {
query,
_objects: core::marker::PhantomData,
_events: core::marker::PhantomData,
}
}
}
pub const fn const_str_eq(a: &str, b: &str) -> bool {
let a_bytes = a.as_bytes();
let b_bytes = b.as_bytes();
if a_bytes.len() != b_bytes.len() {
return false;
}
let mut i = 0;
while i < a_bytes.len() {
if a_bytes[i] != b_bytes[i] {
return false;
}
i += 1;
}
true
}
pub const fn const_contains(arr: &[&str], target: &str) -> bool {
let mut i = 0;
while i < arr.len() {
if const_str_eq(arr[i], target) {
return true;
}
i += 1;
}
false
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OcpqQueryBounded<
const OBJECT_TYPES: &'static [&'static str],
const EVENT_TYPES: &'static [&'static str],
> {
pub query: OcpqQuery,
}
impl<const OBJECT_TYPES: &'static [&'static str], const EVENT_TYPES: &'static [&'static str]>
OcpqQueryBounded<OBJECT_TYPES, EVENT_TYPES>
{
pub fn new(query: OcpqQuery) -> Self {
Self { query }
}
pub fn with_object_predicate<const OBJ_TYPE: &'static str>(self) -> Self
where
crate::law::Require<{ const_contains(OBJECT_TYPES, OBJ_TYPE) }>: crate::law::IsTrue,
{
self
}
pub fn with_event_predicate<const EV_TYPE: &'static str>(self) -> Self
where
crate::law::Require<{ const_contains(EVENT_TYPES, EV_TYPE) }>: crate::law::IsTrue,
{
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ConstraintViolation<const OBJ_TYPE: &'static str, const EV_TYPE: &'static str>;
impl<const OBJ_TYPE: &'static str, const EV_TYPE: &'static str>
ConstraintViolation<OBJ_TYPE, EV_TYPE>
{
pub fn new() -> Self {
Self
}
}
impl<const OBJ_TYPE: &'static str, const EV_TYPE: &'static str> Default
for ConstraintViolation<OBJ_TYPE, EV_TYPE>
{
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SimilarityScore<const NUM: u64, const DEN: u64>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
pub score: crate::law::Between01<NUM, DEN>,
}
impl<const NUM: u64, const DEN: u64> SimilarityScore<NUM, DEN>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
pub fn new() -> Self {
Self {
score: crate::law::Between01::new(),
}
}
}
impl<const NUM: u64, const DEN: u64> Default for SimilarityScore<NUM, DEN>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
fn default() -> Self {
Self::new()
}
}
pub type NormedSimilarityScore<const N: u64, const D: u64> =
SimilarityScore<{ N / crate::law::gcd(N, D) }, { D / crate::law::gcd(N, D) }>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OcpqResult<const NUM: u64, const DEN: u64>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
pub score: SimilarityScore<NUM, DEN>,
}
impl<const NUM: u64, const DEN: u64> OcpqResult<NUM, DEN>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
pub fn new() -> Self {
Self {
score: SimilarityScore::new(),
}
}
}
impl<const NUM: u64, const DEN: u64> Default for OcpqResult<NUM, DEN>
where
crate::law::Require<{ DEN > 0 }>: crate::law::IsTrue,
crate::law::Require<{ NUM <= DEN }>: crate::law::IsTrue,
{
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, core::marker::ConstParamTy)]
pub enum TemporalOrderingAxiom {
Before,
After,
During,
Concurrent,
Overlap,
}
pub struct TypedTemporalPredicate<const AXIOM: TemporalOrderingAxiom> {
pub predicate: Predicate,
}
impl<const AXIOM: TemporalOrderingAxiom> TypedTemporalPredicate<AXIOM> {
pub fn new(predicate: Predicate) -> Self {
Self { predicate }
}
}