zlink_core/varlink_service/
api.rs1use mayheap::string::String;
2#[cfg(feature = "std")]
3use serde::Deserialize;
4use serde::Serialize;
5
6#[cfg(feature = "introspection")]
7use crate::introspect;
8
9use crate::ReplyError;
10
11use super::Info;
12#[cfg(feature = "idl")]
13use super::InterfaceDescription;
14
15#[derive(Debug, Serialize)]
17#[cfg_attr(feature = "std", derive(Deserialize))]
18#[serde(tag = "method", content = "parameters")]
19pub enum Method<'a> {
20 #[serde(rename = "org.varlink.service.GetInfo")]
22 GetInfo,
23 #[serde(rename = "org.varlink.service.GetInterfaceDescription")]
25 GetInterfaceDescription {
26 interface: &'a str,
28 },
29}
30
31#[derive(Debug, Serialize)]
35#[cfg_attr(feature = "idl-parse", derive(Deserialize))]
36#[serde(untagged)]
37pub enum Reply<'a> {
38 #[serde(borrow)]
40 Info(Info<'a>),
41 #[cfg(feature = "idl")]
44 InterfaceDescription(InterfaceDescription<'static>),
45}
46
47#[derive(Debug, Clone, PartialEq, ReplyError)]
49#[cfg_attr(feature = "introspection", derive(introspect::ReplyError))]
50#[zlink(interface = "org.varlink.service")]
51#[cfg_attr(feature = "introspection", zlink(crate = "crate"))]
52pub enum Error {
53 InterfaceNotFound {
55 interface: String<MAX_INTERFACE_NAME_LENGTH>,
57 },
58 MethodNotFound {
60 method: String<MAX_METHOD_NAME_LENGTH>,
62 },
63 MethodNotImplemented {
65 method: String<MAX_METHOD_NAME_LENGTH>,
67 },
68 InvalidParameter {
70 parameter: String<MAX_PARAMETER_NAME_LENGTH>,
72 },
73 PermissionDenied,
75 ExpectedMore,
77}
78
79impl core::error::Error for Error {
80 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
81 None
82 }
83}
84
85impl core::fmt::Display for Error {
86 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
87 match self {
88 Error::InterfaceNotFound { interface } => {
89 write!(f, "Interface not found: {interface}")
90 }
91 Error::MethodNotFound { method } => {
92 write!(f, "Method not found: {method}")
93 }
94 Error::InvalidParameter { parameter } => {
95 write!(f, "Invalid parameter: {parameter}")
96 }
97 Error::PermissionDenied => {
98 write!(f, "Permission denied")
99 }
100 Error::ExpectedMore => {
101 write!(f, "Expected more")
102 }
103 Error::MethodNotImplemented { method } => {
104 write!(f, "Method not implemented: {method}")
105 }
106 }
107 }
108}
109
110pub type Result<T> = core::result::Result<T, Error>;
112
113const MAX_INTERFACE_NAME_LENGTH: usize = 64;
114const MAX_METHOD_NAME_LENGTH: usize = 64;
115const MAX_PARAMETER_NAME_LENGTH: usize = 24;
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use core::str::FromStr;
121
122 #[test]
123 fn error_serialization() {
124 let err = Error::InterfaceNotFound {
125 interface: String::from_str("com.example.missing").unwrap(),
126 };
127
128 let json = serialize_error(&err);
129 assert!(json.contains("org.varlink.service.InterfaceNotFound"));
130 assert!(json.contains("com.example.missing"));
131
132 let err = Error::PermissionDenied;
133
134 let json = serialize_error(&err);
135 assert!(json.contains("org.varlink.service.PermissionDenied"));
136 }
137
138 #[test]
139 fn error_deserialization() {
140 let json = r#"{"error":"org.varlink.service.InterfaceNotFound","parameters":{"interface":"com.example.missing"}}"#;
142 let err = deserialize_error(json);
143 assert_eq!(
144 err,
145 Error::InterfaceNotFound {
146 interface: String::from_str("com.example.missing").unwrap()
147 }
148 );
149
150 let json = r#"{"error":"org.varlink.service.PermissionDenied"}"#;
152 let err = deserialize_error(json);
153 assert_eq!(err, Error::PermissionDenied);
154
155 let json = r#"{"error":"org.varlink.service.MethodNotFound","parameters":{"method":"NonExistentMethod"}}"#;
157 let err = deserialize_error(json);
158 assert_eq!(
159 err,
160 Error::MethodNotFound {
161 method: String::from_str("NonExistentMethod").unwrap()
162 }
163 );
164
165 let json = r#"{"error":"org.varlink.service.InvalidParameter","parameters":{"parameter":"invalid_param"}}"#;
167 let err = deserialize_error(json);
168 assert_eq!(
169 err,
170 Error::InvalidParameter {
171 parameter: String::from_str("invalid_param").unwrap()
172 }
173 );
174
175 let json = r#"{"error":"org.varlink.service.MethodNotImplemented","parameters":{"method":"UnimplementedMethod"}}"#;
177 let err = deserialize_error(json);
178 assert_eq!(
179 err,
180 Error::MethodNotImplemented {
181 method: String::from_str("UnimplementedMethod").unwrap()
182 }
183 );
184
185 let json = r#"{"error":"org.varlink.service.ExpectedMore"}"#;
187 let err = deserialize_error(json);
188 assert_eq!(err, Error::ExpectedMore);
189 }
190
191 #[test]
192 fn error_round_trip_serialization() {
193 let original = Error::InterfaceNotFound {
195 interface: String::from_str("com.example.missing").unwrap(),
196 };
197
198 test_round_trip_serialize(&original);
199
200 let original = Error::PermissionDenied;
202
203 test_round_trip_serialize(&original);
204 }
205
206 fn serialize_error(err: &Error) -> mayheap::string::String<256> {
208 #[cfg(feature = "std")]
209 {
210 mayheap::string::String::from_str(&serde_json::to_string(err).unwrap()).unwrap()
211 }
212 #[cfg(not(feature = "std"))]
213 {
214 use mayheap::string::String;
215 let mut buffer = [0u8; 256];
216 let len = serde_json_core::to_slice(err, &mut buffer).unwrap();
217 let vec = mayheap::Vec::<_, 256>::from_slice(&buffer[..len]).unwrap();
218 String::<256>::from_utf8(vec).unwrap()
219 }
220 }
221
222 fn deserialize_error(json: &str) -> Error {
224 #[cfg(feature = "std")]
225 {
226 serde_json::from_str(json).unwrap()
227 }
228 #[cfg(not(feature = "std"))]
229 {
230 let (err, _): (Error, usize) = serde_json_core::from_str(json).unwrap();
231 err
232 }
233 }
234
235 fn test_round_trip_serialize(original: &Error) {
237 #[cfg(feature = "std")]
238 {
239 let json = serde_json::to_string(original).unwrap();
240 let deserialized: Error = serde_json::from_str(&json).unwrap();
241 assert_eq!(*original, deserialized);
242 }
243 #[cfg(not(feature = "std"))]
244 {
245 let mut buffer = [0u8; 256];
246 let len = serde_json_core::to_slice(original, &mut buffer).unwrap();
247 let json_bytes = &buffer[..len];
248 let (deserialized, _): (Error, usize) =
249 serde_json_core::from_slice(json_bytes).unwrap();
250 assert_eq!(*original, deserialized);
251 }
252 }
253}