brewlog/src/domain/images.rs
Jon Seager f7b210f234
test: add unit tests for all reviewed domain modules
Add 57 unit tests across auth (sessions, registration tokens, API
tokens, username validation), coffee (roasters, cafes, brews, gear),
listing (pagination, sort keys, page calculations), analytics
(country stats), images (debug redaction), and entity type (roundtrip
serialization).
2026-02-13 16:20:18 +00:00

64 lines
1.5 KiB
Rust

use std::fmt;
use serde::Deserialize;
use crate::domain::entity_type::EntityType;
/// An image associated with an entity (roaster, roast, gear, or cafe).
pub struct EntityImage {
pub entity_type: EntityType,
pub entity_id: i64,
pub content_type: String,
pub image_data: Vec<u8>,
pub thumbnail_data: Vec<u8>,
}
/// Wrapper for image data URLs that redacts content in `Debug` output,
/// allowing payloads to be traced without logging raw base64 image data.
#[derive(Default, Deserialize)]
#[serde(transparent)]
pub struct ImageData(Option<String>);
impl ImageData {
pub fn into_inner(self) -> Option<String> {
self.0
}
pub fn as_deref(&self) -> Option<&str> {
self.0.as_deref()
}
pub fn take(&mut self) -> Option<String> {
self.0.take()
}
pub fn cloned(&self) -> Option<String> {
self.0.clone()
}
}
impl fmt::Debug for ImageData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 {
Some(_) => write!(f, "Some(<image>)"),
None => write!(f, "None"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn image_data_debug_redacts_some() {
let data: ImageData = serde_json::from_str(r#""data:image/png;base64,abc""#).unwrap();
assert_eq!(format!("{data:?}"), "Some(<image>)");
}
#[test]
fn image_data_debug_shows_none() {
let data = ImageData::default();
assert_eq!(format!("{data:?}"), "None");
}
}