1use crate::call::ApiCall;
2use crate::error::{Error, Result};
3use crate::types::{DeviceDescriptor, MethodDescriptor};
4use serde::de::{self, DeserializeOwned};
5use serde::Deserialize;
6use std::mem::MaybeUninit;
7use std::result::Result as StdResult;
8
9#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
10#[serde(rename_all = "lowercase", tag = "type", content = "data")]
11pub enum Response<T: ApiCall> {
12 #[serde(alias = "list", alias = "methods", rename = "result")]
13 Response(T::Response),
14 Error(String),
15}
16
17#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Deserialize)]
18pub struct List(pub Vec<DeviceDescriptor>);
19
20#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Deserialize)]
21pub struct Methods(pub Vec<MethodDescriptor>);
22
23#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
24pub struct Return<R>(pub R);
25
26impl<'de, R: DeserializeOwned + 'static> Deserialize<'de> for Return<R> {
27 fn deserialize<D>(deserializer: D) -> StdResult<Self, D::Error>
28 where
29 D: serde::Deserializer<'de>,
30 {
31 fn zst<T>() -> T {
39 assert!(std::mem::size_of::<T>() == 0, "`T` must be a ZST");
40
41 #[allow(clippy::uninit_assumed_init)]
44 unsafe {
45 MaybeUninit::uninit().assume_init()
46 }
47 }
48
49 let opt: Option<R> = Deserialize::deserialize(deserializer)?;
50
51 match opt {
52 Some(r) => Ok(Return(r)),
53 None if std::mem::size_of::<R>() == 0 => Ok(Return(zst())),
54 None => Err(de::Error::missing_field("data")),
58 }
59 }
60}
61
62impl<T: ApiCall> From<Response<T>> for Result<T::Response> {
63 fn from(value: Response<T>) -> Self {
64 match value {
65 Response::Response(t) => Ok(t),
66 Response::Error(e) => Err(Error::from(e)),
69 }
70 }
71}