mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-03 11:34:30 +00:00
api: WIP: don't depend on a specific Body type
For a T which is not directly a Body or Response<Body> type #[api] fn foo() -> T; should not require a specific Body type. Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
This commit is contained in:
parent
c8e11115d2
commit
916f9d945f
@ -18,6 +18,16 @@ pub trait ApiMethodInfo {
|
||||
fn call(&self, params: Value) -> super::ApiFuture<Self::Body>;
|
||||
}
|
||||
|
||||
impl<Body: 'static> dyn ApiMethodInfo<Body = Body> {
|
||||
pub fn call_as<ToBody>(&self, params: Value) -> super::ApiFuture<ToBody>
|
||||
where
|
||||
Body: Into<ToBody>,
|
||||
{
|
||||
use futures::future::TryFutureExt;
|
||||
Box::pin(self.call(params).map_ok(|res| res.map(|res| res.into())))
|
||||
}
|
||||
}
|
||||
|
||||
/// Shortcut to not having to type it out. This function signature is just a dummy and not yet
|
||||
/// stabalized!
|
||||
pub type CompleteFn = fn(&str) -> Vec<String>;
|
||||
@ -289,3 +299,26 @@ impl<Body> ApiType for Response<Body> {
|
||||
pub fn get_type_info<T: ApiType>() -> &'static TypeInfo {
|
||||
T::type_info()
|
||||
}
|
||||
|
||||
/// API methods can have different body types. For the CLI we don't care whether it is a
|
||||
/// hyper::Body or a bytes::Bytes (also because we don't care for partia bodies etc.), so the
|
||||
/// output needs to be wrapped to a common format. So basically the CLI will only ever see
|
||||
/// `ApiOutput<Bytes>`.
|
||||
pub trait UnifiedApiMethod<Body>: Send + Sync {
|
||||
fn parameters(&self) -> &'static [Parameter];
|
||||
fn call(&self, params: Value) -> super::ApiFuture<Body>;
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static, Body> UnifiedApiMethod<Body> for T
|
||||
where
|
||||
T: ApiMethodInfo,
|
||||
T::Body: 'static + Into<Body>,
|
||||
{
|
||||
fn parameters(&self) -> &'static [Parameter] {
|
||||
ApiMethodInfo::parameters(self)
|
||||
}
|
||||
|
||||
fn call(&self, params: Value) -> super::ApiFuture<Body> {
|
||||
(self as &dyn ApiMethodInfo<Body = T::Body>).call_as(params)
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ use failure::{bail, format_err, Error};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::{ApiMethodInfo, ApiOutput, Parameter};
|
||||
use super::{ApiMethodInfo, ApiOutput, Parameter, UnifiedApiMethod};
|
||||
|
||||
type MethodInfoRef = &'static dyn UnifiedApiMethod;
|
||||
type MethodInfoRef = &'static dyn UnifiedApiMethod<Bytes>;
|
||||
|
||||
/// A CLI root node.
|
||||
pub struct App {
|
||||
@ -146,30 +146,6 @@ impl SubCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/// API methods can have different body types. For the CLI we don't care whether it is a
|
||||
/// hyper::Body or a bytes::Bytes (also because we don't care for partia bodies etc.), so the
|
||||
/// output needs to be wrapped to a common format. So basically the CLI will only ever see
|
||||
/// `ApiOutput<Bytes>`.
|
||||
pub trait UnifiedApiMethod: Send + Sync {
|
||||
fn parameters(&self) -> &'static [Parameter];
|
||||
fn call(&self, params: Value) -> super::ApiFuture<Bytes>;
|
||||
}
|
||||
|
||||
impl<T: Send + Sync> UnifiedApiMethod for T
|
||||
where
|
||||
T: ApiMethodInfo,
|
||||
T::Body: 'static + Into<Bytes>,
|
||||
{
|
||||
fn parameters(&self) -> &'static [Parameter] {
|
||||
ApiMethodInfo::parameters(self)
|
||||
}
|
||||
|
||||
fn call(&self, params: Value) -> super::ApiFuture<Bytes> {
|
||||
use futures::future::TryFutureExt;
|
||||
Box::pin(ApiMethodInfo::call(self, params).map_ok(|res| res.map(|body| body.into())))
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an API method. Note that when coming from the command line, it is possible to
|
||||
/// match some parameters as positional parameters rather than argument switches, therefor this
|
||||
/// contains an ordered list of positional parameters.
|
||||
|
Loading…
Reference in New Issue
Block a user