use super::Device;
use crate::{ASCOMError, ASCOMResult};
use macro_rules_attribute::apply;
#[apply(rpc_trait)]
pub trait FilterWheel: Device + Send + Sync {
#[http("focusoffsets", method = Get)]
async fn focus_offsets(&self) -> ASCOMResult<Vec<i32>>;
#[http("names", method = Get)]
async fn names(&self) -> ASCOMResult<Vec<String>>;
#[http("position", method = Get, via = OptionalPosition, device_state = "Position")]
async fn position(&self) -> ASCOMResult<Option<usize>>;
#[http("position", method = Put)]
async fn set_position(&self, #[http("Position")] position: usize) -> ASCOMResult<()> {
Err(ASCOMError::NOT_IMPLEMENTED)
}
#[http("interfaceversion", method = Get)]
async fn interface_version(&self) -> ASCOMResult<u16> {
Ok(3)
}
}
#[derive(derive_more::From, derive_more::Into)]
pub(super) struct OptionalPosition(Option<usize>);
impl serde::Serialize for OptionalPosition {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.map_or(-1, usize::cast_signed).serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for OptionalPosition {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = i64::deserialize(deserializer)?;
Ok(Self(match value {
-1 => None,
_ => Some(value.try_into().map_err(|_err| {
serde::de::Error::invalid_value(
serde::de::Unexpected::Signed(value),
&"-1 (moving) or or a non-negative filter wheel position",
)
})?),
}))
}
}