#![doc(html_root_url = "http://docs.rs/qapi-spec/0.3.1")]
use std::{io, error, fmt, str};
use std::marker::PhantomData;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::DeserializeOwned;
pub use serde_json::Value as Any;
pub type Dictionary = serde_json::Map<String, Any>;
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Empty { }
pub enum Never { }
impl Serialize for Never {
fn serialize<S: Serializer>(&self, _: S) -> Result<S::Ok, S::Error> {
match *self { }
}
}
impl<'de> Deserialize<'de> for Never {
fn deserialize<D: Deserializer<'de>>(_: D) -> Result<Self, D::Error> {
use serde::de::Error;
Err(D::Error::custom("Cannot instantiate Never type"))
}
}
#[doc(hidden)]
pub mod base64 {
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Error, Unexpected};
use base64::{self, DecodeError};
pub fn serialize<S: Serializer>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
base64::encode(data).serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
let str = String::deserialize(deserializer)?;
base64::decode(&str)
.map_err(|e| de_err(&str, e))
}
pub fn de_err<E: Error>(str: &str, err: DecodeError) -> E {
match err {
DecodeError::InvalidByte(..) =>
E::invalid_value(Unexpected::Str(str), &"base64"),
DecodeError::InvalidLength =>
E::invalid_length(str.len(), &"valid base64 length"),
DecodeError::InvalidLastSymbol(..) =>
E::invalid_value(Unexpected::Str(str), &"truncated or corrupted base64"),
}
}
}
#[doc(hidden)]
pub mod base64_opt {
use serde::{Serializer, Deserialize, Deserializer};
use crate::base64;
use ::base64 as b64;
pub fn serialize<S: Serializer>(data: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
base64::serialize(data.as_ref().expect("use skip_serializing_with"), serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error> {
let str = <Option<String>>::deserialize(deserializer)?;
if let Some(ref str) = str {
b64::decode(str)
.map(Some)
.map_err(|e| base64::de_err(str, e))
} else {
Ok(None)
}
}
}
mod error_serde {
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use crate::{Error, ErrorClass, Any};
#[derive(Deserialize)]
pub struct ErrorValue {
pub class: ErrorClass,
pub desc: String,
}
#[derive(Deserialize)]
struct QapiError {
error: ErrorValue,
#[serde(default, skip_serializing_if = "Option::is_none")]
id: Option<Any>,
}
#[derive(Serialize)]
pub struct ErrorValueSer<'a> {
pub class: &'a ErrorClass,
pub desc: &'a str,
}
#[derive(Serialize)]
struct QapiErrorSer<'a> {
error: ErrorValueSer<'a>,
#[serde(default, skip_serializing_if = "Option::is_none")]
id: Option<&'a Any>,
}
impl Serialize for Error {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
QapiErrorSer {
error: ErrorValueSer {
class: &self.class,
desc: &self.desc[..],
},
id: self.id.as_ref(),
}.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Error {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
QapiError::deserialize(deserializer).map(|e| Error {
class: e.error.class,
desc: e.error.desc,
id: e.id,
})
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResponseValue<C> {
#[serde(rename = "return")]
return_: C,
#[serde(default, skip_serializing_if = "Option::is_none")]
id: Option<Any>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Response<C> {
Err(Error),
Ok(ResponseValue<C>),
}
impl<C> Response<C> {
pub fn result(self) -> Result<C, Error> {
match self {
Response::Ok(ResponseValue { return_, .. }) => Ok(return_),
Response::Err(e) => Err(e),
}
}
pub fn id(&self) -> Option<&Any> {
match self {
Response::Err(err) => err.id.as_ref(),
Response::Ok(value) => value.id.as_ref(),
}
}
}
pub trait Command: Serialize + Sync + Send {
type Ok: DeserializeOwned;
const NAME: &'static str;
const ALLOW_OOB: bool;
}
impl<'a, C: Command> Command for &'a C {
type Ok = C::Ok;
const NAME: &'static str = C::NAME;
const ALLOW_OOB: bool = C::ALLOW_OOB;
}
impl<'a, C: Command> Command for &'a mut C {
type Ok = C::Ok;
const NAME: &'static str = C::NAME;
const ALLOW_OOB: bool = C::ALLOW_OOB;
}
pub trait Event: DeserializeOwned {
const NAME: &'static str;
}
pub unsafe trait Enum: DeserializeOwned + str::FromStr + Copy + 'static {
fn discriminant(&self) -> usize;
fn name(&self) -> &'static str {
unsafe {
Self::NAMES.get_unchecked(self.discriminant())
}
}
fn from_name(s: &str) -> Option<Self> {
Self::NAMES.iter().zip(Self::VARIANTS)
.find(|&(&n, _)| n == s)
.map(|(_, &v)| v)
}
const COUNT: usize;
const VARIANTS: &'static [Self];
const NAMES: &'static [&'static str];
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum ErrorClass {
GenericError,
CommandNotFound,
DeviceNotActive,
DeviceNotFound,
KVMMissingCap,
}
impl From<ErrorClass> for io::ErrorKind {
fn from(e: ErrorClass) -> Self {
match e {
ErrorClass::GenericError => io::ErrorKind::Other,
ErrorClass::CommandNotFound => io::ErrorKind::InvalidInput,
ErrorClass::DeviceNotActive => io::ErrorKind::Other,
ErrorClass::DeviceNotFound => io::ErrorKind::NotFound,
ErrorClass::KVMMissingCap => io::ErrorKind::Other,
}
}
}
#[derive(Debug, Clone)]
pub struct Error {
pub class: ErrorClass,
pub desc: String,
pub id: Option<Any>,
}
pub type CommandResult<C> = Result<<C as Command>::Ok, Error>;
fn serialize_command_name<C: Command, S: Serializer>(_: &PhantomData<&'static str>, s: S) -> Result<S::Ok, S::Error> {
C::NAME.serialize(s)
}
#[derive(Serialize)]
pub struct Execute<C, I = Never> {
#[serde(serialize_with = "serialize_command_name::<C, _>", bound = "C: Command")]
pub execute: PhantomData<&'static str>,
pub arguments: C,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<I>,
}
#[derive(Serialize)]
pub struct ExecuteOob<C, I = Any> {
#[serde(rename = "exec-oob", serialize_with = "serialize_command_name::<C, _>", bound = "C: Command")]
pub execute_oob: PhantomData<&'static str>,
pub arguments: C,
pub id: I,
}
impl<C: Command, I> Execute<C, I> {
pub fn new(arguments: C, id: Option<I>) -> Self {
Self {
execute: PhantomData,
arguments,
id,
}
}
pub fn with_command(arguments: C) -> Self {
Self {
execute: PhantomData,
arguments,
id: None,
}
}
pub fn with_id(arguments: C, id: I) -> Self {
Self {
execute: PhantomData,
arguments,
id: Some(id),
}
}
}
impl<C: Command, I> From<C> for Execute<C, I> {
fn from(command: C) -> Self {
Self::with_command(command)
}
}
impl<C: Command, I> ExecuteOob<C, I> {
pub fn new(arguments: C, id: I) -> Self {
Self {
execute_oob: PhantomData,
arguments,
id,
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
&self.desc
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.desc, f)
}
}
impl From<Error> for io::Error {
fn from(e: Error) -> Self {
io::Error::new(e.class.into(), e.desc)
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Timestamp {
seconds: u64,
microseconds: u64,
}