retailops_sdk/proto/api/
reference.rs

1use serde::{Deserialize, Serialize};
2
3/// serialized format of a reference is "/client/concept/id"
4/// looks like "/tnk/po/1471106" or "//user/1234"
5#[derive(Debug)]
6pub struct Reference {
7    pub clientkey: Option<String>,
8    pub concept: String,
9    pub id: u32,
10}
11
12impl Serialize for Reference {
13    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
14    where
15        S: serde::Serializer,
16    {
17        let path = match &self.clientkey {
18            Some(client) => format!("/{}/{}/{}", client, self.concept, self.id),
19            None => format!("//{}/{}", self.concept, self.id),
20        };
21        serializer.serialize_str(&path)
22    }
23}
24
25impl<'de> Deserialize<'de> for Reference {
26    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27    where
28        D: serde::Deserializer<'de>,
29    {
30        let path = String::deserialize(deserializer)?;
31        let parts: Vec<&str> = path.split('/').collect();
32
33        match parts.as_slice() {
34            ["", "", concept, id] => Ok(Reference {
35                clientkey: None,
36                concept: concept.to_string(),
37                id: id.parse().map_err(serde::de::Error::custom)?,
38            }),
39            ["", client, concept, id] => Ok(Reference {
40                clientkey: Some(client.to_string()),
41                concept: concept.to_string(),
42                id: id.parse().map_err(serde::de::Error::custom)?,
43            }),
44            _ => Err(serde::de::Error::custom("Invalid reference path format")),
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use serde_json;
53
54    #[test]
55    fn test_reference_with_client() {
56        let reference = Reference {
57            clientkey: Some("tnk".to_string()),
58            concept: "po".to_string(),
59            id: 1471106,
60        };
61
62        let serialized = serde_json::to_string(&reference).unwrap();
63        assert_eq!(serialized, "\"/tnk/po/1471106\"");
64
65        let deserialized: Reference = serde_json::from_str(&serialized).unwrap();
66        assert_eq!(deserialized.clientkey, Some("tnk".to_string()));
67        assert_eq!(deserialized.concept, "po");
68        assert_eq!(deserialized.id, 1471106);
69    }
70
71    #[test]
72    fn test_reference_without_client() {
73        let reference = Reference {
74            clientkey: None,
75            concept: "user".to_string(),
76            id: 1234,
77        };
78
79        let serialized = serde_json::to_string(&reference).unwrap();
80        assert_eq!(serialized, "\"//user/1234\"");
81
82        let deserialized: Reference = serde_json::from_str(&serialized).unwrap();
83        assert_eq!(deserialized.clientkey, None);
84        assert_eq!(deserialized.concept, "user");
85        assert_eq!(deserialized.id, 1234);
86    }
87
88    #[test]
89    fn test_invalid_reference() {
90        let result = serde_json::from_str::<Reference>("\"/invalid/format\"");
91        assert!(result.is_err());
92
93        let result = serde_json::from_str::<Reference>("\"/too/many/parts/here\"");
94        assert!(result.is_err());
95
96        let result = serde_json::from_str::<Reference>("\"/not/enough\"");
97        assert!(result.is_err());
98    }
99}