diff --git a/proxmox-api/src/api_type.rs b/proxmox-api/src/api_type.rs index 7d9063bd..e4a61f56 100644 --- a/proxmox-api/src/api_type.rs +++ b/proxmox-api/src/api_type.rs @@ -18,6 +18,16 @@ pub trait ApiMethodInfo { fn call(&self, params: Value) -> super::ApiFuture; } +impl dyn ApiMethodInfo { + pub fn call_as(&self, params: Value) -> super::ApiFuture + where + Body: Into, + { + 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; @@ -289,3 +299,26 @@ impl ApiType for Response { pub fn get_type_info() -> &'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`. +pub trait UnifiedApiMethod: Send + Sync { + fn parameters(&self) -> &'static [Parameter]; + fn call(&self, params: Value) -> super::ApiFuture; +} + +impl UnifiedApiMethod for T +where + T: ApiMethodInfo, + T::Body: 'static + Into, +{ + fn parameters(&self) -> &'static [Parameter] { + ApiMethodInfo::parameters(self) + } + + fn call(&self, params: Value) -> super::ApiFuture { + (self as &dyn ApiMethodInfo).call_as(params) + } +} diff --git a/proxmox-api/src/cli.rs b/proxmox-api/src/cli.rs index e9491ac4..416ba4e2 100644 --- a/proxmox-api/src/cli.rs +++ b/proxmox-api/src/cli.rs @@ -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; /// 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`. -pub trait UnifiedApiMethod: Send + Sync { - fn parameters(&self) -> &'static [Parameter]; - fn call(&self, params: Value) -> super::ApiFuture; -} - -impl UnifiedApiMethod for T -where - T: ApiMethodInfo, - T::Body: 'static + Into, -{ - fn parameters(&self) -> &'static [Parameter] { - ApiMethodInfo::parameters(self) - } - - fn call(&self, params: Value) -> super::ApiFuture { - 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.