use crate::Bmc;
use crate::ModificationResponse;
use core::fmt::Debug;
use core::fmt::Display;
use core::fmt::Formatter;
use core::fmt::Result as FmtResult;
use serde::Deserialize;
use serde::Serialize;
use std::marker::PhantomData;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ActionTarget(String);
impl ActionTarget {
#[must_use]
pub const fn new(v: String) -> Self {
Self(v)
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Display for ActionTarget {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(&self.0, f)
}
}
#[derive(Deserialize)]
pub struct Action<T, R> {
#[serde(rename = "target")]
pub target: ActionTarget,
#[serde(skip_deserializing)]
_marker: PhantomData<T>,
#[serde(skip_deserializing)]
_marker_retval: PhantomData<R>,
}
impl<T, R> Debug for Action<T, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("Action")
.field("target", &self.target)
.finish()
}
}
pub trait ActionError {
fn not_supported() -> Self;
}
impl<T: Send + Sync + Serialize, R: Send + Sync + Sized + for<'de> Deserialize<'de>> Action<T, R> {
pub async fn run<B: Bmc>(
&self,
bmc: &B,
params: &T,
) -> Result<ModificationResponse<R>, B::Error> {
bmc.action::<T, R>(self, params).await
}
}
#[cfg(test)]
mod tests {
use super::Action;
use super::ActionTarget;
use std::marker::PhantomData;
struct NotDebug;
#[test]
fn debug_does_not_require_parameter_or_result_debug() {
let action: Action<NotDebug, NotDebug> = Action {
target: ActionTarget::new("/redfish/v1/Actions/Test".into()),
_marker: PhantomData,
_marker_retval: PhantomData,
};
assert_eq!(
format!("{action:?}"),
"Action { target: ActionTarget(\"/redfish/v1/Actions/Test\") }"
);
}
}