wip: field parsing

This commit is contained in:
Greg Heartsfield 2022-10-15 10:24:20 -05:00
parent cf997e0ffb
commit 0ae6292c1c

View File

@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
//use serde_json::Number; //use serde_json::Number;
//use std::collections::HashMap; //use std::collections::HashMap;
//use std::collections::HashSet; //use std::collections::HashSet;
//use std::str::FromStr; use std::str::FromStr;
//use tracing::{debug, info}; //use tracing::{debug, info};
// This handles everything related to delegation, in particular the // This handles everything related to delegation, in particular the
@ -38,15 +38,14 @@ use serde::{Deserialize, Serialize};
// condition string. We will then map that with a deserializer that // condition string. We will then map that with a deserializer that
// maps to a ConditionQuery. // maps to a ConditionQuery.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub enum Field { pub enum Field {
Kind, Kind,
CreatedAt, CreatedAt,
} }
impl TryFrom<&str> for Field { impl FromStr for Field {
type Error = Error; type Err = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> { fn from_str(value: &str) -> Result<Self, Self::Err> {
if value == "kind" { if value == "kind" {
Ok(Field::Kind) Ok(Field::Kind)
} else if value == "created_at" { } else if value == "created_at" {
@ -57,7 +56,6 @@ impl TryFrom<&str> for Field {
} }
} }
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub enum Operator { pub enum Operator {
LessThan, LessThan,
@ -85,7 +83,6 @@ pub struct Delegation {
pub(crate) signature: String, pub(crate) signature: String,
} }
/// Parsed delegation condition /// Parsed delegation condition
/// see https://github.com/nostr-protocol/nips/pull/28#pullrequestreview-1084903800 /// see https://github.com/nostr-protocol/nips/pull/28#pullrequestreview-1084903800
/// An example complex condition would be: kind=1,2,3&created_at<1665265999 /// An example complex condition would be: kind=1,2,3&created_at<1665265999
@ -99,35 +96,34 @@ pub struct Condition {
fn str_to_condition(cs: &str) -> Option<Condition> { fn str_to_condition(cs: &str) -> Option<Condition> {
// a condition is a string (alphanum+underscore), an operator (<>=!), and values (num+comma) // a condition is a string (alphanum+underscore), an operator (<>=!), and values (num+comma)
lazy_static! { lazy_static! {
static ref RE: Regex = Regex::new("([[:word:]])([<>=!]+)([,[[:digit:]]]+))").unwrap(); static ref RE: Regex = Regex::new("([[:word:]])([<>=!]+)([,[[:digit:]]]+)").unwrap();
} }
// match against the regex // match against the regex
let caps = RE.captures(cs)?; let caps = RE.captures(cs)?;
let field = caps.get(1)?.as_str().try_into().ok()?; let field = caps.get(1)?.as_str().parse::<Field>().ok()?;
let _op = caps.get(2)?.as_str(); let _op = caps.get(2)?.as_str();
let _vals = caps.get(3)?.as_str(); let _vals = caps.get(3)?.as_str();
// convert field string into Field // convert field string into Field
Some(Condition {field: field, operator: Operator::GreaterThan, values: vec![]}) Some(Condition {
field,
operator: Operator::GreaterThan,
values: vec![],
})
} }
/// Parse a condition query from a string slice /// Parse a condition query from a string slice
impl TryFrom<&str> for ConditionQuery { impl FromStr for ConditionQuery {
type Error = Error; type Err = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> { fn from_str(value: &str) -> Result<Self, Self::Err> {
// split the string with '&' // split the string with '&'
let conds = value.split('&'); let conds = value.split_terminator('&');
// parse each individual condition // parse each individual condition
for c in conds.into_iter() { for c in conds {
str_to_condition(c).ok_or(Error::DelegationParseError)?; str_to_condition(c).ok_or(Error::DelegationParseError)?;
} }
Ok(ConditionQuery { conditions: vec![] }) Ok(ConditionQuery { conditions: vec![] })
} }
} }
#[cfg(test)] #[cfg(test)]
@ -136,8 +132,11 @@ mod tests {
// parse condition strings // parse condition strings
#[test] #[test]
fn parse_empty() { fn parse_empty() -> Result<()> {
// given an empty condition query, produce an empty vector // given an empty condition query, produce an empty vector
assert_eq!(Delegation::from(""), vec![]); let empty_cq = ConditionQuery { conditions: vec![] };
let parsed = "".parse::<ConditionQuery>()?;
assert_eq!(parsed, empty_cq);
Ok(())
} }
} }