diff options
Diffstat (limited to 'src/session.rs')
| -rw-r--r-- | src/session.rs | 113 |
1 files changed, 97 insertions, 16 deletions
diff --git a/src/session.rs b/src/session.rs index 82a3563..b9e508e 100644 --- a/src/session.rs +++ b/src/session.rs @@ -3,7 +3,7 @@ use std::any::Any; use std::collections::BTreeMap; use std::collections::btree_map::{Iter, Keys}; -use crate::capabilities::{AccountCapabilities, CapabilityParsers, ServerCapabilities}; +use crate::capabilities::{AccountCapabilities, CapabilityRegistry, ServerCapabilities}; use crate::*; // 2: JMAP Session Resource {{{ @@ -50,13 +50,13 @@ pub struct JMAPSession { impl JMAPSession { /// Get session from the json - pub fn from_json(json: &str, parsers: CapabilityParsers) -> Result<Self, serde_json::Error> { + pub fn from_json(json: &str, parsers: CapabilityRegistry) -> Result<Self, serde_json::Error> { let session: ISession = serde_json::from_str(json)?; Ok(Self::from_intermediate(session, parsers)) } /// Get session from the ISession object - pub fn from_intermediate(session: ISession, parsers: CapabilityParsers) -> Self { + pub fn from_intermediate(session: ISession, parsers: CapabilityRegistry) -> Self { let mut accounts = BTreeMap::new(); for acc in session.accounts.keys() { accounts.insert(acc.clone(), None); @@ -155,12 +155,63 @@ impl JMAPSession { // Appendix A: tests {{{ #[cfg(test)] mod test { - use crate::JMAPId; + use serde::{Deserialize, Serialize}; + use serde_json::Value; + use crate::capabilities::{ - Capability, CapabilityCollection, JMAPCoreCapability, URN_JMAP_CORE, + AccountCapabilities, Capability, CapabilityCollection, CapabilityDyn, JMAPCoreCapability, }; + use crate::{JArr, JDate, JMAPId, JNumber, JObj, JUTCDate, JUnknown, from_junknown}; use std::assert_matches; + enum DeserializeTestCapability { + Session(DTC_Session), + Account(DTC_Session, DTC_Account), + } + + #[derive(Serialize, Deserialize, Clone)] + struct DTC_Session { + num: JNumber, + numArr: JArr<JNumber>, + bool: bool, + str: String, + boolObj: JObj<JMAPId, bool>, + date: JDate, + } + + #[derive(Serialize, Deserialize, Clone)] + struct DTC_Account { + #[serde(skip)] + account_id: Option<JMAPId>, + utc_date: JUTCDate, + } + + impl Capability for DeserializeTestCapability { + const URN: &str = "urn:xyz:wilkuu:deser_test"; + + fn from_object(obj: &crate::JObject) -> Self { + Self::Session(from_junknown(obj.clone()).unwrap()) + } + + fn account_cap(&self, account_id: JMAPId, obj: &crate::JObject) -> Self { + let session_cap = (match self { + Self::Session(s) => s, + Self::Account(s, _) => s, + }) + .clone(); + let mut acc: DTC_Account = from_junknown(obj.clone()).unwrap(); + acc.account_id = Some(account_id); + Self::Account(session_cap, acc) + } + + fn account(&self) -> Option<JMAPId> { + match self { + Self::Session(_) => None, + Self::Account(_, a) => Some(a.account_id.clone().expect("This should always be Some, considering that we create it with the account_id in account_cap")), + } + } + } + #[test] fn intermediate_parse_test() { let in1 = r#" @@ -254,6 +305,14 @@ mod test { "urn:ietf:params:jmap:contacts": {}, "https://example.com/apis/foobar": { "maxFoosFinangled": 42 + }, + "urn:xyz:wilkuu:deser_test": { + "num": 12.0, + "numArr": [1,2.0,3.0], + "bool": true, + "str": "string", + "boolObj": { "a": true, "b": false }, + "date": "2026-08-10T10:00:00+02:00" } }, "accounts": { @@ -267,13 +326,17 @@ mod test { "maxMailboxDepth": 10 }, "urn:ietf:params:jmap:contacts": { - } + }, + "urn:xyz:wilkuu:deser_test": { + "utc_date": "2026-08-10T12:00:00Z" + } } } }, "primaryAccounts": { "urn:ietf:params:jmap:mail": "A13824", - "urn:ietf:params:jmap:contacts": "A13824" + "urn:ietf:params:jmap:contacts": "A13824", + "urn:xyz:wilkuu_deser_test": "A13824" }, "username": "john@example.com", "apiUrl": "https://jmap.example.com/api/", @@ -284,7 +347,9 @@ mod test { } "#; - let parsers = crate::session::CapabilityParsers::default(); + let mut parsers = crate::session::CapabilityRegistry::default(); + parsers.add_capability::<DeserializeTestCapability>(); + let mut session = match crate::session::JMAPSession::from_json(in1, parsers) { Ok(i) => i, Err(e) => unreachable!("Error in parsing json {:?}", e), @@ -296,13 +361,13 @@ mod test { assert!( session .capabilities - .get_capability::<JMAPCoreCapability>(URN_JMAP_CORE) + .get_capability::<JMAPCoreCapability>() .is_some() ); let account = session.get_account(&crate::JMAPId("A13824".to_string())); - assert_matches!(account, None); + assert!(account.is_none()); let account_opt = session.eval_get_account(&crate::JMAPId("A13824".to_string())); - assert_matches!(account_opt, Some(_)); + assert!(account_opt.is_some()); let account_opt = session.eval_get_account_mut(&crate::JMAPId("A13824".to_string())); let account = account_opt.unwrap(); assert_eq!( @@ -312,13 +377,29 @@ mod test { .keys() .map(Clone::clone) .collect::<Vec<String>>(), - vec![URN_JMAP_CORE] + vec![JMAPCoreCapability::URN, DeserializeTestCapability::URN] ); - let cap: &mut JMAPCoreCapability = account - .capabilities - .get_capability_mut(URN_JMAP_CORE) - .unwrap(); + let cap: &mut JMAPCoreCapability = account.capabilities.get_capability_mut().unwrap(); assert_eq!(cap.account(), Some(JMAPId("A13824".to_string()))); + + let deser_cap: &mut DeserializeTestCapability = + account.capabilities.get_capability_mut().unwrap(); + assert_eq!(deser_cap.account(), Some(JMAPId("A13824".to_string()))); + match deser_cap { + DeserializeTestCapability::Session(_) => unreachable!("This should be an account cap"), + DeserializeTestCapability::Account(s, _a) => { + assert_eq!(s.num, 12.0); + assert_eq!(s.numArr, vec![1.0, 2.0, 3.0]); + assert!(s.bool); + assert_eq!(s.str, "string"); + assert_eq!(s.boolObj.get(&JMAPId("a".to_string())), Some(true).as_ref()); + assert_eq!( + s.boolObj.get(&JMAPId("b".to_string())), + Some(false).as_ref() + ); + // TODO: Test dates + } + } } } // }}} |
