use derive_more::{Display, From};
use serde::{Deserialize, Serialize};
use zarrs_metadata::ConfigurationSerialize;
#[allow(clippy::trivially_copy_pass_by_ref, clippy::ref_option)]
fn skip_padding_encoding(padding_encoding: &Option<PackBitsPaddingEncoding>) -> bool {
matches!(padding_encoding, None | Some(PackBitsPaddingEncoding::None))
}
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug, Display, From)]
#[non_exhaustive]
#[serde(untagged)]
pub enum PackBitsCodecConfiguration {
V1(PackBitsCodecConfigurationV1),
}
impl ConfigurationSerialize for PackBitsCodecConfiguration {}
#[derive(Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Debug, Display)]
#[serde(deny_unknown_fields)]
#[display("{}", serde_json::to_string(self).unwrap_or_default())]
pub struct PackBitsCodecConfigurationV1 {
#[serde(skip_serializing_if = "skip_padding_encoding")]
pub padding_encoding: Option<PackBitsPaddingEncoding>,
#[serde(skip_serializing_if = "Option::is_none")]
pub first_bit: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_bit: Option<u64>,
}
#[derive(Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Debug, Display, Default)]
#[serde(rename_all = "snake_case")]
pub enum PackBitsPaddingEncoding {
#[default]
None,
FirstByte,
LastByte,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn packbits_default() {
let configuration = serde_json::from_str::<PackBitsCodecConfigurationV1>(
r"
{
}
",
)
.unwrap();
assert_eq!(configuration.padding_encoding, None);
}
#[test]
fn packbits_none() {
let configuration = serde_json::from_str::<PackBitsCodecConfigurationV1>(
r#"
{
"padding_encoding": "none"
}
"#,
)
.unwrap();
assert_eq!(
configuration.padding_encoding,
Some(PackBitsPaddingEncoding::None)
);
}
#[test]
fn packbits_start_byte() {
let configuration = serde_json::from_str::<PackBitsCodecConfigurationV1>(
r#"
{
"padding_encoding": "first_byte"
}
"#,
)
.unwrap();
assert_eq!(
configuration.padding_encoding,
Some(PackBitsPaddingEncoding::FirstByte)
);
}
#[test]
fn packbits_end_byte() {
let configuration = serde_json::from_str::<PackBitsCodecConfigurationV1>(
r#"
{
"padding_encoding": "last_byte"
}
"#,
)
.unwrap();
assert_eq!(
configuration.padding_encoding,
Some(PackBitsPaddingEncoding::LastByte)
);
}
#[test]
fn packbits_serialize_skip_none() {
let configuration = PackBitsCodecConfigurationV1 {
padding_encoding: None,
first_bit: None,
last_bit: None,
};
let json = serde_json::to_string(&configuration).unwrap();
assert_eq!(json, "{}");
}
#[test]
fn packbits_serialize_skip_padding_none() {
let configuration = PackBitsCodecConfigurationV1 {
padding_encoding: Some(PackBitsPaddingEncoding::None),
first_bit: None,
last_bit: None,
};
let json = serde_json::to_string(&configuration).unwrap();
assert_eq!(json, "{}");
}
#[test]
fn packbits_serialize_first_byte() {
let configuration = PackBitsCodecConfigurationV1 {
padding_encoding: Some(PackBitsPaddingEncoding::FirstByte),
first_bit: None,
last_bit: None,
};
let json = serde_json::to_string(&configuration).unwrap();
assert_eq!(json, r#"{"padding_encoding":"first_byte"}"#);
}
#[test]
fn packbits_serialize_last_byte() {
let configuration = PackBitsCodecConfigurationV1 {
padding_encoding: Some(PackBitsPaddingEncoding::LastByte),
first_bit: None,
last_bit: None,
};
let json = serde_json::to_string(&configuration).unwrap();
assert_eq!(json, r#"{"padding_encoding":"last_byte"}"#);
}
}