diff --git a/src/lib.rs b/src/lib.rs index 9e10d70..a51deab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ pub mod error; pub mod event; pub mod proto; +pub mod request; diff --git a/src/request.rs b/src/request.rs index 2afa416..68c40b5 100644 --- a/src/request.rs +++ b/src/request.rs @@ -3,17 +3,17 @@ use serde::{Deserialize, Deserializer, Serialize}; //use serde_json::json; //use serde_json::Result; - // Container for a request filter #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] +#[serde(transparent)] pub struct ReqCmd { - cmds: Vec + cmds: Vec, } -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone)] pub struct Subscription { id: String, - Vec + filters: Vec, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] @@ -28,3 +28,97 @@ pub struct ReqFilter { since: Option, authors: Option>, } + +impl<'de> Deserialize<'de> for Subscription { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let r: ReqCmd = Deserialize::deserialize(deserializer)?; + let elems = r.cmds; + // ensure we have at least 3 fields + if elems.len() < 3 { + Err(serde::de::Error::custom("not enough fields")) + } else { + // divide into req/sub-id vector, and filter vector + let (header, filter_strs) = elems.split_at(2); + let req_cmd = header.get(0).unwrap(); + let sub_id = header.get(1).unwrap(); + if req_cmd != "REQ" { + return Err(serde::de::Error::custom("missing REQ command")); + } + let mut filters = vec![]; + for e in filter_strs.iter() { + let des_res = serde_json::from_str::(e); + match des_res { + Ok(f) => filters.push(f), + Err(_) => return Err(serde::de::Error::custom("could not parse filter")), + } + } + Ok(Subscription { + id: sub_id.to_owned(), + filters, + }) + } + } +} + +// impl Subscription { +// pub fn parse(json: &str) -> Result { +// use serde to parse the ReqCmd, and then extract elements +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + // fn simple_req() -> Event { + // super::Event { + // id: 0, + // pubkey: 0, + // created_at: 0, + // kind: 0, + // tags: vec![], + // content: "".to_owned(), + // sig: 0, + // } + // } + + #[test] + fn empty_request_parse() -> Result<()> { + let raw_json = "[\"REQ\",\"some-id\",\"{}\"]"; + let s: Subscription = serde_json::from_str(raw_json)?; + assert_eq!(s.id, "some-id"); + assert_eq!(s.filters.len(), 1); + assert_eq!(s.filters.get(0).unwrap().author, None); + Ok(()) + } + + #[test] + fn incorrect_header() { + let raw_json = "[\"REQUEST\",\"some-id\",\"{}\"]"; + assert!(serde_json::from_str::(raw_json).is_err()); + } + + #[test] + fn req_missing_filters() { + let raw_json = "[\"REQ\",\"some-id\"]"; + assert!(serde_json::from_str::(raw_json).is_err()); + } + + #[test] + fn invalid_filter() { + // unrecognized field in filter + let raw_json = "[\"REQ\",\"some-id\",\"{\"foo\": 3}\"]"; + assert!(serde_json::from_str::(raw_json).is_err()); + } + + // #[test] + // fn author_filter() -> Result<()> { + // let raw_json = "[\"REQ\",\"some-id\",\"{\"author\": \"test-author-id\"}\"]"; + // let s: Subscription = serde_json::from_str(raw_json)?; + // assert_eq!(s.id, "some-id"); + // assert_eq!(s.filters.len(), 1); + // Ok(()) + // } +}