use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ValidationError {
code: &'static str,
message: &'static str,
}
impl ValidationError {
#[must_use]
pub const fn new(code: &'static str, message: &'static str) -> Self {
Self { code, message }
}
#[must_use]
pub const fn code(&self) -> &'static str {
self.code
}
#[must_use]
pub const fn message(&self) -> &'static str {
self.message
}
}
impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.code, self.message)
}
}
#[cfg(feature = "std")]
impl std::error::Error for ValidationError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_preserves_code_and_message() {
let err = ValidationError::new("non_empty", "value must not be empty");
assert_eq!(err.code(), "non_empty");
assert_eq!(err.message(), "value must not be empty");
}
#[test]
fn display_joins_code_and_message() {
use core::fmt::Write as _;
let err = ValidationError::new("out_of_range", "expected 1..=10");
let mut buf = Buf::new();
let _ = write!(buf, "{err}");
assert_eq!(buf.as_str(), "out_of_range: expected 1..=10");
}
#[test]
fn equal_errors_compare_equal() {
let a = ValidationError::new("c", "m");
let b = ValidationError::new("c", "m");
let c = ValidationError::new("c", "other");
assert_eq!(a, b);
assert_ne!(a, c);
}
struct Buf {
bytes: [u8; 64],
len: usize,
}
impl Buf {
fn new() -> Self {
Self {
bytes: [0; 64],
len: 0,
}
}
fn as_str(&self) -> &str {
core::str::from_utf8(&self.bytes[..self.len]).unwrap_or("")
}
}
impl core::fmt::Write for Buf {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for &byte in s.as_bytes() {
if self.len < self.bytes.len() {
self.bytes[self.len] = byte;
self.len += 1;
}
}
Ok(())
}
}
}