use crate::db::{api::view::GraphViewOps, graph::graph::Graph};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, collections::HashMap, fmt, sync::Arc};
#[cfg(test)]
extern crate core;
pub mod entities;
pub mod state;
pub(crate) mod storage;
pub mod utils;
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
pub enum Direction {
OUT,
IN,
BOTH,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub enum Prop {
Str(String),
I32(i32),
I64(i64),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Bool(bool),
List(Arc<Vec<Prop>>),
Map(Arc<HashMap<String, Prop>>),
DTime(NaiveDateTime),
Graph(Graph),
}
impl PartialOrd for Prop {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self, other) {
(Prop::Str(a), Prop::Str(b)) => a.partial_cmp(b),
(Prop::I32(a), Prop::I32(b)) => a.partial_cmp(b),
(Prop::I64(a), Prop::I64(b)) => a.partial_cmp(b),
(Prop::U32(a), Prop::U32(b)) => a.partial_cmp(b),
(Prop::U64(a), Prop::U64(b)) => a.partial_cmp(b),
(Prop::F32(a), Prop::F32(b)) => a.partial_cmp(b),
(Prop::F64(a), Prop::F64(b)) => a.partial_cmp(b),
(Prop::Bool(a), Prop::Bool(b)) => a.partial_cmp(b),
(Prop::DTime(a), Prop::DTime(b)) => a.partial_cmp(b),
_ => None,
}
}
}
impl Prop {
pub fn str(s: &str) -> Prop {
Prop::Str(s.to_string())
}
pub fn add(self, other: Prop) -> Option<Prop> {
match (self, other) {
(Prop::I32(a), Prop::I32(b)) => Some(Prop::I32(a + b)),
(Prop::I64(a), Prop::I64(b)) => Some(Prop::I64(a + b)),
(Prop::U32(a), Prop::U32(b)) => Some(Prop::U32(a + b)),
(Prop::U64(a), Prop::U64(b)) => Some(Prop::U64(a + b)),
(Prop::F32(a), Prop::F32(b)) => Some(Prop::F32(a + b)),
(Prop::F64(a), Prop::F64(b)) => Some(Prop::F64(a + b)),
(Prop::Str(a), Prop::Str(b)) => Some(Prop::Str(a + &b)),
_ => None,
}
}
pub fn divide(self, other: Prop) -> Option<Prop> {
match (self, other) {
(Prop::I32(a), Prop::I32(b)) if b != 0 => Some(Prop::I32(a / b)),
(Prop::I64(a), Prop::I64(b)) if b != 0 => Some(Prop::I64(a / b)),
(Prop::U32(a), Prop::U32(b)) if b != 0 => Some(Prop::U32(a / b)),
(Prop::U64(a), Prop::U64(b)) if b != 0 => Some(Prop::U64(a / b)),
(Prop::F32(a), Prop::F32(b)) if b != 0.0 => Some(Prop::F32(a / b)),
(Prop::F64(a), Prop::F64(b)) if b != 0.0 => Some(Prop::F64(a / b)),
_ => None,
}
}
}
pub trait PropUnwrap: Sized {
fn into_str(self) -> Option<String>;
fn unwrap_str(self) -> String {
self.into_str().unwrap()
}
fn into_i32(self) -> Option<i32>;
fn unwrap_i32(self) -> i32 {
self.into_i32().unwrap()
}
fn into_i64(self) -> Option<i64>;
fn unwrap_i64(self) -> i64 {
self.into_i64().unwrap()
}
fn into_u32(self) -> Option<u32>;
fn unwrap_u32(self) -> u32 {
self.into_u32().unwrap()
}
fn into_u64(self) -> Option<u64>;
fn unwrap_u64(self) -> u64 {
self.into_u64().unwrap()
}
fn into_f32(self) -> Option<f32>;
fn unwrap_f32(self) -> f32 {
self.into_f32().unwrap()
}
fn into_f64(self) -> Option<f64>;
fn unwrap_f64(self) -> f64 {
self.into_f64().unwrap()
}
fn into_bool(self) -> Option<bool>;
fn unwrap_bool(self) -> bool {
self.into_bool().unwrap()
}
fn into_list(self) -> Option<Arc<Vec<Prop>>>;
fn unwrap_list(self) -> Arc<Vec<Prop>> {
self.into_list().unwrap()
}
fn into_map(self) -> Option<Arc<HashMap<String, Prop>>>;
fn unwrap_map(self) -> Arc<HashMap<String, Prop>> {
self.into_map().unwrap()
}
fn into_dtime(self) -> Option<NaiveDateTime>;
fn unwrap_dtime(self) -> NaiveDateTime {
self.into_dtime().unwrap()
}
fn into_graph(self) -> Option<Graph>;
fn unwrap_graph(self) -> Graph {
self.into_graph().unwrap()
}
}
impl<P: PropUnwrap> PropUnwrap for Option<P> {
fn into_str(self) -> Option<String> {
self.and_then(|p| p.into_str())
}
fn into_i32(self) -> Option<i32> {
self.and_then(|p| p.into_i32())
}
fn into_i64(self) -> Option<i64> {
self.and_then(|p| p.into_i64())
}
fn into_u32(self) -> Option<u32> {
self.and_then(|p| p.into_u32())
}
fn into_u64(self) -> Option<u64> {
self.and_then(|p| p.into_u64())
}
fn into_f32(self) -> Option<f32> {
self.and_then(|p| p.into_f32())
}
fn into_f64(self) -> Option<f64> {
self.and_then(|p| p.into_f64())
}
fn into_bool(self) -> Option<bool> {
self.and_then(|p| p.into_bool())
}
fn into_list(self) -> Option<Arc<Vec<Prop>>> {
self.and_then(|p| p.into_list())
}
fn into_map(self) -> Option<Arc<HashMap<String, Prop>>> {
self.and_then(|p| p.into_map())
}
fn into_dtime(self) -> Option<NaiveDateTime> {
self.and_then(|p| p.into_dtime())
}
fn into_graph(self) -> Option<Graph> {
self.and_then(|p| p.into_graph())
}
}
impl PropUnwrap for Prop {
fn into_str(self) -> Option<String> {
if let Prop::Str(s) = self {
Some(s)
} else {
None
}
}
fn into_i32(self) -> Option<i32> {
if let Prop::I32(v) = self {
Some(v)
} else {
None
}
}
fn into_i64(self) -> Option<i64> {
if let Prop::I64(v) = self {
Some(v)
} else {
None
}
}
fn into_u32(self) -> Option<u32> {
if let Prop::U32(v) = self {
Some(v)
} else {
None
}
}
fn into_u64(self) -> Option<u64> {
if let Prop::U64(v) = self {
Some(v)
} else {
None
}
}
fn into_f32(self) -> Option<f32> {
if let Prop::F32(v) = self {
Some(v)
} else {
None
}
}
fn into_f64(self) -> Option<f64> {
if let Prop::F64(v) = self {
Some(v)
} else {
None
}
}
fn into_bool(self) -> Option<bool> {
if let Prop::Bool(v) = self {
Some(v)
} else {
None
}
}
fn into_list(self) -> Option<Arc<Vec<Prop>>> {
if let Prop::List(v) = self {
Some(v)
} else {
None
}
}
fn into_map(self) -> Option<Arc<HashMap<String, Prop>>> {
if let Prop::Map(v) = self {
Some(v)
} else {
None
}
}
fn into_dtime(self) -> Option<NaiveDateTime> {
if let Prop::DTime(v) = self {
Some(v)
} else {
None
}
}
fn into_graph(self) -> Option<Graph> {
if let Prop::Graph(g) = self {
Some(g)
} else {
None
}
}
}
impl fmt::Display for Prop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Prop::Str(value) => write!(f, "{}", value),
Prop::I32(value) => write!(f, "{}", value),
Prop::I64(value) => write!(f, "{}", value),
Prop::U32(value) => write!(f, "{}", value),
Prop::U64(value) => write!(f, "{}", value),
Prop::F32(value) => write!(f, "{}", value),
Prop::F64(value) => write!(f, "{}", value),
Prop::Bool(value) => write!(f, "{}", value),
Prop::DTime(value) => write!(f, "{}", value),
Prop::Graph(value) => write!(
f,
"Graph(num_vertices={}, num_edges={})",
value.num_vertices(),
value.num_edges()
),
Prop::List(value) => {
write!(f, "{:?}", value)
}
Prop::Map(value) => {
write!(f, "{:?}", value)
}
}
}
}
impl From<String> for Prop {
fn from(s: String) -> Self {
Prop::Str(s)
}
}
impl From<&str> for Prop {
fn from(s: &str) -> Self {
Prop::Str(s.to_string())
}
}
impl From<i32> for Prop {
fn from(i: i32) -> Self {
Prop::I32(i)
}
}
impl From<i64> for Prop {
fn from(i: i64) -> Self {
Prop::I64(i)
}
}
impl From<u32> for Prop {
fn from(u: u32) -> Self {
Prop::U32(u)
}
}
impl From<u64> for Prop {
fn from(u: u64) -> Self {
Prop::U64(u)
}
}
impl From<f32> for Prop {
fn from(f: f32) -> Self {
Prop::F32(f)
}
}
impl From<f64> for Prop {
fn from(f: f64) -> Self {
Prop::F64(f)
}
}
impl From<bool> for Prop {
fn from(b: bool) -> Self {
Prop::Bool(b)
}
}
impl From<HashMap<String, Prop>> for Prop {
fn from(value: HashMap<String, Prop>) -> Self {
Prop::Map(Arc::new(value))
}
}
impl From<Vec<Prop>> for Prop {
fn from(value: Vec<Prop>) -> Self {
Prop::List(Arc::new(value))
}
}
impl From<&Prop> for Prop {
fn from(value: &Prop) -> Self {
value.clone()
}
}
pub trait IntoPropMap {
fn into_prop_map(self) -> Prop;
}
impl<I: IntoIterator<Item = (K, V)>, K: Into<String>, V: Into<Prop>> IntoPropMap for I {
fn into_prop_map(self) -> Prop {
Prop::Map(Arc::new(
self.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
))
}
}
pub trait IntoPropList {
fn into_prop_list(self) -> Prop;
}
impl<I: IntoIterator<Item = K>, K: Into<Prop>> IntoPropList for I {
fn into_prop_list(self) -> Prop {
Prop::List(Arc::new(self.into_iter().map(|v| v.into()).collect()))
}
}
pub trait IntoProp {
fn into_prop(self) -> Prop;
}
impl<T: Into<Prop>> IntoProp for T {
fn into_prop(self) -> Prop {
self.into()
}
}