use nutype::nutype;
#[nutype(
validate(greater = 0),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
Display,
TryFrom,
AsRef,
Deref,
Serialize,
Deserialize
)
)]
pub struct WindowSize(u64);
impl WindowSize {
pub const DEFAULT: u64 = 100;
#[inline]
#[must_use]
pub fn get(&self) -> u64 {
self.into_inner()
}
}
#[nutype(
validate(greater = 0),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
Display,
TryFrom,
AsRef,
Deref,
Serialize,
Deserialize
)
)]
pub struct BufferSize(usize);
impl BufferSize {
pub const COMMAND: usize = 512;
pub const DEFAULT: usize = 8192;
pub const MEDIUM: usize = 256 * 1024;
pub const LARGE: usize = 4 * 1024 * 1024;
#[inline]
#[must_use]
pub fn get(&self) -> usize {
self.into_inner()
}
#[must_use]
pub fn command() -> Self {
Self::try_new(Self::COMMAND).unwrap()
}
#[must_use]
pub fn medium() -> Self {
Self::try_new(Self::MEDIUM).unwrap()
}
#[must_use]
pub fn large() -> Self {
Self::try_new(Self::LARGE).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn valid_buffer_sizes_roundtrip(size in 1usize..10_000_000usize) {
let buffer = BufferSize::try_new(size).unwrap();
prop_assert_eq!(buffer.get(), size);
}
#[test]
fn buffer_size_display_shows_value(size in 1usize..10_000_000usize) {
let buffer = BufferSize::try_new(size).unwrap();
let display = format!("{buffer}");
prop_assert!(display.contains(&size.to_string()));
}
#[test]
fn buffer_size_debug_shows_value(size in 1usize..10_000_000usize) {
let buffer = BufferSize::try_new(size).unwrap();
let debug = format!("{buffer:?}");
prop_assert!(debug.contains("BufferSize"));
prop_assert!(debug.contains(&size.to_string()));
}
#[test]
fn buffer_size_serde_json_roundtrip(size in 1usize..10_000_000usize) {
let original = BufferSize::try_new(size).unwrap();
let json = serde_json::to_string(&original).unwrap();
let deserialized: BufferSize = serde_json::from_str(&json).unwrap();
prop_assert_eq!(original, deserialized);
}
#[test]
fn buffer_size_clone_equality(size in 1usize..10_000_000usize) {
let original = BufferSize::try_new(size).unwrap();
let cloned = original;
prop_assert_eq!(original, cloned);
prop_assert_eq!(original.get(), cloned.get());
}
#[test]
fn buffer_size_equality_same_value(size in 1usize..10_000_000usize) {
let buffer1 = BufferSize::try_new(size).unwrap();
let buffer2 = BufferSize::try_new(size).unwrap();
prop_assert_eq!(buffer1, buffer2);
}
}
proptest! {
#[test]
fn valid_window_sizes_roundtrip(size in 1u64..100_000u64) {
let window = WindowSize::try_new(size).unwrap();
prop_assert_eq!(window.get(), size);
}
#[test]
fn window_size_display_shows_value(size in 1u64..100_000u64) {
let window = WindowSize::try_new(size).unwrap();
let display = format!("{window}");
prop_assert!(display.contains(&size.to_string()));
}
#[test]
fn window_size_serde_json_roundtrip(size in 1u64..100_000u64) {
let original = WindowSize::try_new(size).unwrap();
let json = serde_json::to_string(&original).unwrap();
let deserialized: WindowSize = serde_json::from_str(&json).unwrap();
prop_assert_eq!(original, deserialized);
}
#[test]
fn window_size_clone_equality(size in 1u64..100_000u64) {
let original = WindowSize::try_new(size).unwrap();
let cloned = original;
prop_assert_eq!(original, cloned);
}
}
#[test]
fn buffer_size_zero_is_invalid() {
assert!(BufferSize::try_new(0).is_err());
}
#[test]
fn buffer_size_one_is_valid() {
let size = BufferSize::try_new(1).unwrap();
assert_eq!(size.get(), 1);
}
#[test]
fn window_size_zero_is_invalid() {
assert!(WindowSize::try_new(0).is_err());
}
#[test]
fn buffer_size_constants_correct_values() {
assert_eq!(BufferSize::COMMAND, 512);
assert_eq!(BufferSize::DEFAULT, 8192);
assert_eq!(BufferSize::MEDIUM, 262_144);
assert_eq!(BufferSize::LARGE, 4_194_304);
}
#[test]
fn window_size_default_constant() {
assert_eq!(WindowSize::DEFAULT, 100);
}
}