1#![doc(html_root_url = "https://docs.rs/qapi-spec/0.3.2")]
2
3use std::{io, error, fmt, str};
4use std::marker::PhantomData;
5use serde::{Serialize, Serializer, Deserialize, Deserializer};
6use serde::de::DeserializeOwned;
7
8pub use serde_json::Value as Any;
9pub type Dictionary = serde_json::Map<String, Any>;
10
11#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
12pub struct Empty { }
13
14pub enum Never { }
15
16impl Serialize for Never {
17 fn serialize<S: Serializer>(&self, _: S) -> Result<S::Ok, S::Error> {
18 match *self { }
19 }
20}
21
22impl<'de> Deserialize<'de> for Never {
23 fn deserialize<D: Deserializer<'de>>(_: D) -> Result<Self, D::Error> {
24 use serde::de::Error;
25
26 Err(D::Error::custom("Cannot instantiate Never type"))
27 }
28}
29
30#[doc(hidden)]
31pub mod base64 {
32 use serde::{Serialize, Serializer, Deserialize, Deserializer};
33 use serde::de::{Error, Unexpected};
34 use base64::{prelude::*, DecodeError};
35
36 pub fn serialize<S: Serializer>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
37 BASE64_STANDARD.encode(data).serialize(serializer)
38 }
39
40 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
41 let str = String::deserialize(deserializer)?;
43
44 BASE64_STANDARD.decode(&str)
45 .map_err(|e| de_err(&str, e))
46 }
47
48 pub fn de_err<E: Error>(str: &str, err: DecodeError) -> E {
49 match err {
50 DecodeError::InvalidByte(..) | DecodeError::InvalidPadding =>
51 E::invalid_value(Unexpected::Str(str), &"base64"),
52 DecodeError::InvalidLength(len) =>
53 E::invalid_length(len, &"valid base64 length"),
54 DecodeError::InvalidLastSymbol(..) =>
55 E::invalid_value(Unexpected::Str(str), &"truncated or corrupted base64"),
56 }
57 }
58}
59
60#[doc(hidden)]
61pub mod base64_opt {
62 use serde::{Serializer, Deserialize, Deserializer};
63 use crate::base64;
64 use ::base64::prelude::*;
65
66 pub fn serialize<S: Serializer>(data: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
67 base64::serialize(data.as_ref().expect("use skip_serializing_with"), serializer)
68 }
69
70 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error> {
71 let str = <Option<String>>::deserialize(deserializer)?;
73 if let Some(ref str) = str {
74 BASE64_STANDARD.decode(str)
75 .map(Some)
76 .map_err(|e| base64::de_err(str, e))
77 } else {
78 Ok(None)
79 }
80 }
81}
82
83mod error_serde {
84 use serde::{Serialize, Serializer, Deserialize, Deserializer};
85 use crate::{Error, ErrorClass, Any};
86
87 #[derive(Deserialize)]
88 pub struct ErrorValue {
89 pub class: ErrorClass,
90 pub desc: String,
91 }
92
93 #[derive(Deserialize)]
94 struct QapiError {
95 error: ErrorValue,
96 #[serde(default, skip_serializing_if = "Option::is_none")]
97 id: Option<Any>,
98 }
99
100 #[derive(Serialize)]
101 pub struct ErrorValueSer<'a> {
102 pub class: &'a ErrorClass,
103 pub desc: &'a str,
104 }
105
106 #[derive(Serialize)]
107 struct QapiErrorSer<'a> {
108 error: ErrorValueSer<'a>,
109 #[serde(default, skip_serializing_if = "Option::is_none")]
110 id: Option<&'a Any>,
111 }
112
113 impl Serialize for Error {
114 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
115 QapiErrorSer {
116 error: ErrorValueSer {
117 class: &self.class,
118 desc: &self.desc[..],
119 },
120 id: self.id.as_ref(),
121 }.serialize(serializer)
122 }
123 }
124
125 impl<'de> Deserialize<'de> for Error {
126 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
127 QapiError::deserialize(deserializer).map(|e| Error {
128 class: e.error.class,
129 desc: e.error.desc,
130 id: e.id,
131 })
132 }
133 }
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct ResponseValue<C> {
138 #[serde(rename = "return")]
139 return_: C,
140 #[serde(default, skip_serializing_if = "Option::is_none")]
141 id: Option<Any>,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145#[serde(untagged)]
146pub enum Response<C> {
147 Err(Error),
148 Ok(ResponseValue<C>),
149}
150
151impl<C> Response<C> {
152 pub fn result(self) -> Result<C, Error> {
153 match self {
154 Response::Ok(ResponseValue { return_, .. }) => Ok(return_),
155 Response::Err(e) => Err(e),
156 }
157 }
158
159 pub fn id(&self) -> Option<&Any> {
160 match self {
161 Response::Err(err) => err.id.as_ref(),
162 Response::Ok(value) => value.id.as_ref(),
163 }
164 }
165}
166
167pub trait Command: Serialize + Sync + Send {
168 type Ok: DeserializeOwned;
169
170 const NAME: &'static str;
171 const ALLOW_OOB: bool;
172}
173
174impl<'a, C: Command> Command for &'a C {
175 type Ok = C::Ok;
176
177 const NAME: &'static str = C::NAME;
178 const ALLOW_OOB: bool = C::ALLOW_OOB;
179}
180
181impl<'a, C: Command> Command for &'a mut C {
182 type Ok = C::Ok;
183
184 const NAME: &'static str = C::NAME;
185 const ALLOW_OOB: bool = C::ALLOW_OOB;
186}
187
188pub trait Event: DeserializeOwned {
189 const NAME: &'static str;
190}
191
192pub unsafe trait Enum: DeserializeOwned + str::FromStr + Copy + 'static {
193 fn discriminant(&self) -> usize;
194
195 fn name(&self) -> &'static str {
196 unsafe {
197 Self::NAMES.get_unchecked(self.discriminant())
198 }
199 }
200
201 fn from_name(s: &str) -> Option<Self> {
202 Self::NAMES.iter().zip(Self::VARIANTS)
203 .find(|&(&n, _)| n == s)
204 .map(|(_, &v)| v)
205 }
206
207 const COUNT: usize;
208 const VARIANTS: &'static [Self];
209 const NAMES: &'static [&'static str];
210}
211
212#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
213pub enum ErrorClass {
214 GenericError,
216 CommandNotFound,
218 DeviceNotActive,
220 DeviceNotFound,
222 KVMMissingCap,
224}
225
226impl From<ErrorClass> for io::ErrorKind {
227 fn from(e: ErrorClass) -> Self {
228 match e {
229 ErrorClass::GenericError => io::ErrorKind::Other,
230 ErrorClass::CommandNotFound => io::ErrorKind::InvalidInput,
231 ErrorClass::DeviceNotActive => io::ErrorKind::Other,
232 ErrorClass::DeviceNotFound => io::ErrorKind::NotFound,
233 ErrorClass::KVMMissingCap => io::ErrorKind::Other,
234 }
235 }
236}
237
238#[derive(Debug, Clone)]
239pub struct Error {
240 pub class: ErrorClass,
241 pub desc: String,
242 pub id: Option<Any>,
243}
244
245pub type CommandResult<C> = Result<<C as Command>::Ok, Error>;
246
247fn serialize_command_name<C: Command, S: Serializer>(_: &PhantomData<&'static str>, s: S) -> Result<S::Ok, S::Error> {
248 C::NAME.serialize(s)
249}
250
251#[derive(Serialize)]
252pub struct Execute<C, I = Never> {
253 #[serde(serialize_with = "serialize_command_name::<C, _>", bound = "C: Command")]
254 pub execute: PhantomData<&'static str>,
255 pub arguments: C,
256 #[serde(skip_serializing_if = "Option::is_none")]
257 pub id: Option<I>,
258}
259
260#[derive(Serialize)]
261pub struct ExecuteOob<C, I = Any> {
262 #[serde(rename = "exec-oob", serialize_with = "serialize_command_name::<C, _>", bound = "C: Command")]
263 pub execute_oob: PhantomData<&'static str>,
264 pub arguments: C,
265 pub id: I,
266}
267
268impl<C: Command, I> Execute<C, I> {
269 pub fn new(arguments: C, id: Option<I>) -> Self {
270 Self {
271 execute: PhantomData,
272 arguments,
273 id,
274 }
275 }
276
277 pub fn with_command(arguments: C) -> Self {
278 Self {
279 execute: PhantomData,
280 arguments,
281 id: None,
282 }
283 }
284
285 pub fn with_id(arguments: C, id: I) -> Self {
286 Self {
287 execute: PhantomData,
288 arguments,
289 id: Some(id),
290 }
291 }
292}
293
294impl<C: Command, I> From<C> for Execute<C, I> {
295 fn from(command: C) -> Self {
296 Self::with_command(command)
297 }
298}
299
300impl<C: Command, I> ExecuteOob<C, I> {
301 pub fn new(arguments: C, id: I) -> Self {
302 Self {
303 execute_oob: PhantomData,
304 arguments,
305 id,
306 }
307 }
308}
309
310impl error::Error for Error {
311 fn description(&self) -> &str {
312 &self.desc
313 }
314}
315
316impl fmt::Display for Error {
317 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318 fmt::Display::fmt(&self.desc, f)
319 }
320}
321
322impl From<Error> for io::Error {
323 fn from(e: Error) -> Self {
324 io::Error::new(e.class.into(), e.desc)
325 }
326}
327
328#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
329pub struct Timestamp {
330 seconds: u64,
331 microseconds: u64,
332}