qapi_spec/
lib.rs

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        // TODO: deserialize to borrowed &str
42        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        // TODO: deserialize to borrowed &str
72        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    /// this is used for errors that don’t require a specific error class. This should be the default case for most errors
215    GenericError,
216    /// the requested command has not been found
217    CommandNotFound,
218    /// a device has failed to be become active
219    DeviceNotActive,
220    /// the requested device has not been found
221    DeviceNotFound,
222    /// the requested operation can’t be fulfilled because a required KVM capability is missing
223    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}