use crate::Error;
const SPRMIB: u8 = 0x80;
pub(crate) const SPRMIB_VALUE_MASK: u8 = 0x7F;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub(crate) struct SuppressablePositiveResponse<T: TryFrom<u8> + Into<u8> + Copy> {
suppress_positive_response: bool,
value: T,
}
impl<T: TryFrom<u8> + Into<u8> + Copy> SuppressablePositiveResponse<T> {
pub const fn new(suppress_positive_response: bool, value: T) -> Self {
Self {
suppress_positive_response,
value,
}
}
pub const fn value(&self) -> T {
self.value
}
pub const fn suppress_positive_response(&self) -> bool {
self.suppress_positive_response
}
}
impl<T: TryFrom<u8, Error = Error> + Into<u8> + Copy> TryFrom<u8>
for SuppressablePositiveResponse<T>
{
type Error = Error;
fn try_from(value: u8) -> Result<Self, Error> {
let suppress_positive_response = value & SPRMIB == SPRMIB;
let value = T::try_from(value & SPRMIB_VALUE_MASK)?;
Ok(Self {
suppress_positive_response,
value,
})
}
}
impl<T: TryFrom<u8> + Into<u8> + Copy> From<SuppressablePositiveResponse<T>> for u8 {
fn from(value: SuppressablePositiveResponse<T>) -> Self {
let mut result = value.value.into();
if value.suppress_positive_response {
result |= SPRMIB;
}
result
}
}
#[cfg(test)]
mod test {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct Testu8(u8);
impl TryFrom<u8> for Testu8 {
type Error = crate::Error;
fn try_from(value: u8) -> Result<Self, crate::Error> {
Ok(Self(value))
}
}
impl From<Testu8> for u8 {
fn from(test: Testu8) -> Self {
test.0
}
}
use super::*;
#[test]
fn test_all_u8_values() {
for i in 0..=u8::MAX {
let value: SuppressablePositiveResponse<Testu8> =
SuppressablePositiveResponse::try_from(i).unwrap();
if let 0x00..=0x7F = i {
assert_eq!(value.value().0, i);
assert!(!value.suppress_positive_response());
} else {
assert_eq!(value.value().0, i & SPRMIB_VALUE_MASK);
assert!(value.suppress_positive_response());
}
}
}
}