promxox-router: add SerializableReturn Trait

this will be useful as a generic return type for api calls which
must implement Serialize.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Dominik Csapak 2022-04-08 11:56:01 +02:00 committed by Wolfgang Bumiller
parent 27c8106d7b
commit 2c9272945e
3 changed files with 66 additions and 0 deletions

View File

@ -15,6 +15,7 @@ hyper = { version = "0.14", features = [ "full" ] }
nix = "0.19.1" nix = "0.19.1"
percent-encoding = "2.1" percent-encoding = "2.1"
serde_json = "1.0" serde_json = "1.0"
serde = "1.0"
unicode-width ="0.1.8" unicode-width ="0.1.8"
# cli: # cli:
@ -24,6 +25,7 @@ libc = { version = "0.2", optional = true }
proxmox-lang = { path = "../proxmox-lang", version = "1.1" } proxmox-lang = { path = "../proxmox-lang", version = "1.1" }
proxmox-schema = { path = "../proxmox-schema", version = "1.1" } proxmox-schema = { path = "../proxmox-schema", version = "1.1" }
proxmox-async = { path = "../proxmox-async", version = "0.4" }
[features] [features]
default = [ "cli" ] default = [ "cli" ]

View File

@ -12,6 +12,7 @@ pub mod error;
mod permission; mod permission;
mod router; mod router;
mod rpc_environment; mod rpc_environment;
mod serializable_return;
#[doc(inline)] #[doc(inline)]
pub use error::HttpError; pub use error::HttpError;
@ -19,6 +20,7 @@ pub use error::HttpError;
pub use permission::*; pub use permission::*;
pub use router::*; pub use router::*;
pub use rpc_environment::{RpcEnvironment, RpcEnvironmentType}; pub use rpc_environment::{RpcEnvironment, RpcEnvironmentType};
pub use serializable_return::SerializableReturn;
// make list_subdirs_api_method! work without an explicit proxmox-schema dependency: // make list_subdirs_api_method! work without an explicit proxmox-schema dependency:
#[doc(hidden)] #[doc(hidden)]

View File

@ -0,0 +1,62 @@
use serde::Serializer;
use serde_json::Value;
/// This defines a *fixed* serializer (iow. also where/how to write out the data).
///
/// (Note that `serde::Serializer` is implemented for `__&mut__ serde_json::Serializer`.
type SenderSerializer<'a> = &'a mut serde_json::Serializer<
&'a mut std::io::BufWriter<proxmox_async::blocking::SenderWriter>,
>;
/// This is an object-safe trait which requires the ability to serialize into particular
/// Serializer instances.
pub trait SerializableReturn {
/// Serializes self into a [`proxmox_async::blocking::SenderWriter`] wrapped
/// into a [`std::io::BufWriter`]
///
/// If `value` is an Object/Map, serializes that first and puts the value of
/// `self` into the `data` property.
fn sender_serialize(
&self,
serializer: SenderSerializer,
value: Value,
) -> Result<
<SenderSerializer as serde::Serializer>::Ok,
<SenderSerializer as serde::Serializer>::Error,
>;
/// Returns a value again from self
fn to_value(&self) -> Result<Value, serde_json::error::Error>;
}
impl<T> SerializableReturn for T
where
T: serde::Serialize,
{
fn sender_serialize(
&self,
serializer: SenderSerializer,
value: Value,
) -> Result<
<SenderSerializer as serde::Serializer>::Ok,
<SenderSerializer as serde::Serializer>::Error,
> {
use serde::ser::SerializeMap;
if let Some(original) = value.as_object() {
let mut map = serializer.serialize_map(None)?;
for (k, v) in original {
map.serialize_entry(k, v)?;
}
map.serialize_key("data")?;
map.serialize_value(&self)?;
map.end()
} else {
self.serialize(serializer)
}
}
fn to_value(&self) -> Result<Value, serde_json::error::Error> {
serde_json::to_value(self)
}
}