use std::num::NonZeroU64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PictureType(u8);
impl PictureType {
pub const ZERO: PictureType = PictureType(0);
pub fn new(v: u32) -> Option<PictureType> {
let b = u8::try_from(v).ok()?;
if b > 20 { None } else { Some(PictureType(b)) }
}
pub fn get(self) -> u32 {
u32::from(self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BlobLen(NonZeroU64);
impl BlobLen {
pub fn new(v: u64) -> Option<BlobLen> {
NonZeroU64::new(v).map(BlobLen)
}
pub fn get(self) -> u64 {
self.0.get()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TagInput {
pub key: String,
pub value: String,
}
impl TagInput {
pub fn new(key: &str, value: &str) -> TagInput {
TagInput {
key: key.to_string(),
value: value.to_string(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArtInput {
pub art_id: i64,
pub mime: String,
pub description: String,
pub picture_type: PictureType,
pub width: u32,
pub height: u32,
pub data_len: BlobLen,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EmbeddedPicture {
pub mime: String,
pub picture_type: PictureType,
pub description: String,
pub width: u32,
pub height: u32,
pub data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BinaryTagInput {
pub key: String,
pub payload_id: i64,
pub len: BlobLen,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EmbeddedBinaryTag {
pub key: String,
pub payload: Vec<u8>,
}
#[cfg(test)]
mod tests {
use super::{BinaryTagInput, BlobLen};
#[test]
fn binary_tag_input_constructs() {
let b = BinaryTagInput {
key: "PRIV".into(),
payload_id: 7,
len: BlobLen::new(3).unwrap(),
};
assert_eq!(b.payload_id, 7);
assert_eq!(b.len.get(), 3);
}
#[test]
fn embedded_binary_tag_constructs() {
let e = super::EmbeddedBinaryTag {
key: "PRIV".into(),
payload: vec![1, 2, 3],
};
assert_eq!(e.key, "PRIV");
assert_eq!(e.payload.len(), 3);
}
#[test]
fn picture_type_accepts_full_range() {
for v in 0..=20u32 {
assert_eq!(super::PictureType::new(v).unwrap().get(), v);
}
}
#[test]
fn picture_type_rejects_out_of_range() {
assert!(super::PictureType::new(21).is_none());
assert!(super::PictureType::new(u32::MAX).is_none());
}
#[test]
fn blob_len_rejects_zero() {
assert!(super::BlobLen::new(0).is_none());
}
#[test]
fn blob_len_round_trips_nonzero() {
assert_eq!(super::BlobLen::new(1).unwrap().get(), 1);
assert_eq!(super::BlobLen::new(u64::MAX).unwrap().get(), u64::MAX);
}
}