diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f43d8033f..4654df4bf 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -42,6 +42,7 @@ - fossdd - Wei Jian Gan (weijiangan) - adamcstephens +- Chris Olstrom (colstrom) ## Acknowledgements diff --git a/libs/scim_proto/src/filter.rs b/libs/scim_proto/src/filter.rs index a4d325494..3c73e6374 100644 --- a/libs/scim_proto/src/filter.rs +++ b/libs/scim_proto/src/filter.rs @@ -1,16 +1,32 @@ #![allow(warnings)] +use serde::{Deserialize, Serialize}; use serde_json::Value; use std::str::FromStr; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct AttrPath { // Uri: Option, a: String, s: Option, } -#[derive(Debug, Clone, PartialEq, Eq)] +impl ToString for AttrPath { + fn to_string(&self) -> String { + match self { + Self { + a: attrname, + s: Some(subattr), + } => format!("{attrname}.{subattr}"), + Self { + a: attrname, + s: None, + } => attrname.to_owned(), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ScimFilter { Or(Box, Box), And(Box, Box), @@ -30,7 +46,30 @@ pub enum ScimFilter { Complex(String, Box), } -#[derive(Debug, Clone, PartialEq, Eq)] +impl ToString for ScimFilter { + fn to_string(&self) -> String { + match self { + Self::And(this, that) => format!("({} and {})", this.to_string(), that.to_string()), + Self::Contains(attrpath, value) => format!("({} co {value})", attrpath.to_string()), + Self::EndsWith(attrpath, value) => format!("({} ew {value})", attrpath.to_string()), + Self::Equal(attrpath, value) => format!("({} eq {value})", attrpath.to_string()), + Self::Greater(attrpath, value) => format!("({} gt {value})", attrpath.to_string()), + Self::GreaterOrEqual(attrpath, value) => { + format!("({} ge {value})", attrpath.to_string()) + } + Self::Less(attrpath, value) => format!("({} lt {value})", attrpath.to_string()), + Self::LessOrEqual(attrpath, value) => format!("({} le {value})", attrpath.to_string()), + Self::Not(expr) => format!("(not ({}))", expr.to_string()), + Self::NotEqual(attrpath, value) => format!("({} ne {value})", attrpath.to_string()), + Self::Or(this, that) => format!("({} or {})", this.to_string(), that.to_string()), + Self::Present(attrpath) => format!("({} pr)", attrpath.to_string()), + Self::StartsWith(attrpath, value) => format!("({} sw {value})", attrpath.to_string()), + Self::Complex(attrname, expr) => format!("{attrname}[{}]", expr.to_string()), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ScimComplexFilter { Or(Box, Box), And(Box, Box), @@ -48,6 +87,26 @@ pub enum ScimComplexFilter { LessOrEqual(String, Value), } +impl ToString for ScimComplexFilter { + fn to_string(&self) -> String { + match self { + Self::And(this, that) => format!("({} and {})", this.to_string(), that.to_string()), + Self::Contains(attrname, value) => format!("({attrname} co {value})"), + Self::EndsWith(attrname, value) => format!("({attrname} ew {value})"), + Self::Equal(attrname, value) => format!("({attrname} eq {value})"), + Self::Greater(attrname, value) => format!("({attrname} gt {value})"), + Self::GreaterOrEqual(attrname, value) => format!("({attrname} ge {value})"), + Self::Less(attrname, value) => format!("({attrname} lt {value})"), + Self::LessOrEqual(attrname, value) => format!("({attrname} le {value})"), + Self::Not(expr) => format!("(not ({}))", expr.to_string()), + Self::NotEqual(attrname, value) => format!("({attrname} ne {value})"), + Self::Or(this, that) => format!("({} or {})", this.to_string(), that.to_string()), + Self::Present(attrname) => format!("({attrname} pr)"), + Self::StartsWith(attrname, value) => format!("({attrname} sw {value})"), + } + } +} + // separator()* "(" e:term() ")" separator()* { e } peg::parser! { @@ -213,6 +272,27 @@ peg::parser! { } } +impl FromStr for AttrPath { + type Err = peg::error::ParseError; + fn from_str(input: &str) -> Result { + scimfilter::attrpath(input) + } +} + +impl FromStr for ScimFilter { + type Err = peg::error::ParseError; + fn from_str(input: &str) -> Result { + scimfilter::parse(input) + } +} + +impl FromStr for ScimComplexFilter { + type Err = peg::error::ParseError; + fn from_str(input: &str) -> Result { + scimfilter::parse_complex(input) + } +} + #[cfg(test)] mod test { use super::*;