pub mod position;
pub use position::DagPosition;
use crate::event::EventKind;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::sync::Arc;
pub const MAX_COORDINATE_COMPONENT_LEN: usize = 1024;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Coordinate {
entity: Arc<str>, scope: Arc<str>, }
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CoordinateError {
EmptyEntity,
EmptyScope,
EntityTooLong {
len: usize,
max: usize,
},
ScopeTooLong {
len: usize,
max: usize,
},
}
#[derive(Clone, Debug, Default)]
pub struct Region {
pub entity_prefix: Option<Arc<str>>,
pub scope: Option<Arc<str>>,
pub fact: Option<KindFilter>,
pub clock_range: Option<(u32, u32)>, }
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum KindFilter {
Exact(EventKind),
Category(u8), Any,
}
impl Coordinate {
pub fn new(entity: impl AsRef<str>, scope: impl AsRef<str>) -> Result<Self, CoordinateError> {
let entity = entity.as_ref();
let scope = scope.as_ref();
if entity.is_empty() {
return Err(CoordinateError::EmptyEntity);
}
if scope.is_empty() {
return Err(CoordinateError::EmptyScope);
}
if entity.len() > MAX_COORDINATE_COMPONENT_LEN {
return Err(CoordinateError::EntityTooLong {
len: entity.len(),
max: MAX_COORDINATE_COMPONENT_LEN,
});
}
if scope.len() > MAX_COORDINATE_COMPONENT_LEN {
return Err(CoordinateError::ScopeTooLong {
len: scope.len(),
max: MAX_COORDINATE_COMPONENT_LEN,
});
}
Ok(Self {
entity: Arc::from(entity),
scope: Arc::from(scope),
})
}
pub fn entity(&self) -> &str {
&self.entity
}
pub fn scope(&self) -> &str {
&self.scope
}
pub(crate) fn entity_arc(&self) -> Arc<str> {
Arc::clone(&self.entity)
}
pub(crate) fn scope_arc(&self) -> Arc<str> {
Arc::clone(&self.scope)
}
}
impl fmt::Display for Coordinate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}@{}", self.entity, self.scope)
}
}
impl fmt::Display for CoordinateError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::EmptyEntity => write!(f, "entity cannot be empty"),
Self::EmptyScope => write!(f, "scope cannot be empty"),
Self::EntityTooLong { len, max } => {
write!(f, "entity length {len} exceeds maximum {max}")
}
Self::ScopeTooLong { len, max } => {
write!(f, "scope length {len} exceeds maximum {max}")
}
}
}
}
impl std::error::Error for CoordinateError {}
impl Region {
pub fn all() -> Self {
Self::default()
}
pub fn entity(prefix: impl AsRef<str>) -> Self {
Self {
entity_prefix: Some(Arc::from(prefix.as_ref())),
..Self::default()
}
}
pub fn scope(scope: impl AsRef<str>) -> Self {
Self {
scope: Some(Arc::from(scope.as_ref())),
..Self::default()
}
}
pub fn with_scope(mut self, scope: impl AsRef<str>) -> Self {
self.scope = Some(Arc::from(scope.as_ref()));
self
}
pub fn with_fact(mut self, filter: KindFilter) -> Self {
self.fact = Some(filter);
self
}
pub fn with_fact_category(mut self, cat: u8) -> Self {
self.fact = Some(KindFilter::Category(cat));
self
}
pub fn with_clock_range(mut self, range: (u32, u32)) -> Self {
self.clock_range = Some(range);
self
}
pub fn matches_event(&self, entity: &str, scope: &str, kind: EventKind) -> bool {
if let Some(ref prefix) = self.entity_prefix {
if !entity.starts_with(prefix.as_ref()) {
return false;
}
}
if let Some(ref s) = self.scope {
if scope != s.as_ref() {
return false;
}
}
if let Some(ref fact) = self.fact {
match fact {
KindFilter::Exact(k) => {
if kind != *k {
return false;
}
}
KindFilter::Category(c) => {
if kind.category() != *c {
return false;
}
}
KindFilter::Any => {}
}
}
true
}
}