nextcloud_ocs/envelope/
status.rs1use std::fmt;
2
3use serde::de::{self, Deserializer, Visitor};
4use serde::{Serialize, Serializer};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13pub enum OcsStatus {
14 Ok,
16 Failure,
18}
19
20impl OcsStatus {
21 pub const fn from_statuscode(code: u16) -> Self {
25 match code {
26 100 | 200 => Self::Ok,
27 _ => Self::Failure,
28 }
29 }
30
31 pub fn from_status_text(value: &str) -> Option<Self> {
36 match value.trim().to_ascii_lowercase().as_str() {
37 "ok" => Some(Self::Ok),
38 "failure" => Some(Self::Failure),
39 _ => None,
40 }
41 }
42
43 pub const fn as_str(self) -> &'static str {
45 match self {
46 Self::Ok => "ok",
47 Self::Failure => "failure",
48 }
49 }
50
51 pub const fn is_ok(self) -> bool {
53 matches!(self, Self::Ok)
54 }
55}
56
57impl fmt::Display for OcsStatus {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.write_str(self.as_str())
60 }
61}
62
63impl Serialize for OcsStatus {
64 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
65 serializer.serialize_str(self.as_str())
66 }
67}
68
69impl<'de> de::Deserialize<'de> for OcsStatus {
70 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
71 deserializer.deserialize_str(StatusVisitor)
72 }
73}
74
75struct StatusVisitor;
76
77impl Visitor<'_> for StatusVisitor {
78 type Value = OcsStatus;
79
80 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81 formatter.write_str("`ok` or `failure`")
82 }
83
84 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
85 OcsStatus::from_status_text(value)
86 .ok_or_else(|| E::invalid_value(de::Unexpected::Str(value), &self))
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::OcsStatus;
93
94 #[test]
95 fn statuscodes_map_to_a_verdict() {
96 assert_eq!(OcsStatus::from_statuscode(100), OcsStatus::Ok);
97 assert_eq!(OcsStatus::from_statuscode(200), OcsStatus::Ok);
98 assert_eq!(OcsStatus::from_statuscode(997), OcsStatus::Failure);
99 assert_eq!(OcsStatus::from_statuscode(998), OcsStatus::Failure);
100 assert_eq!(OcsStatus::from_statuscode(999), OcsStatus::Failure);
101 assert!(OcsStatus::from_statuscode(200).is_ok());
102 }
103
104 #[test]
105 fn status_text_is_matched_case_insensitively() {
106 assert_eq!(OcsStatus::from_status_text("OK"), Some(OcsStatus::Ok));
107 assert_eq!(
108 OcsStatus::from_status_text("Failure"),
109 Some(OcsStatus::Failure)
110 );
111 assert_eq!(OcsStatus::from_status_text("maybe"), None);
112 }
113
114 #[test]
115 fn deserializes_from_status_text() {
116 let status: OcsStatus = serde_json::from_str("\"ok\"").unwrap();
117 assert_eq!(status, OcsStatus::Ok);
118 assert!(serde_json::from_str::<OcsStatus>("\"unknown\"").is_err());
119 }
120
121 #[test]
122 fn serializes_back_to_status_text() {
123 assert_eq!(
124 serde_json::to_string(&OcsStatus::Failure).unwrap(),
125 "\"failure\""
126 );
127 }
128}