systemprompt_traits/
validation.rs1use std::fmt::Debug;
2
3#[derive(Debug, Clone)]
4pub struct ValidationError {
5 pub field: String,
6 pub message: String,
7 pub context: Option<String>,
8}
9
10impl ValidationError {
11 #[must_use]
12 pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
13 Self {
14 field: field.into(),
15 message: message.into(),
16 context: None,
17 }
18 }
19
20 #[must_use]
21 pub fn with_context(mut self, context: impl Into<String>) -> Self {
22 self.context = Some(context.into());
23 self
24 }
25}
26
27impl std::fmt::Display for ValidationError {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 if let Some(ref ctx) = self.context {
30 write!(
31 f,
32 "VALIDATION ERROR [{}]: {} (context: {})",
33 self.field, self.message, ctx
34 )
35 } else {
36 write!(f, "VALIDATION ERROR [{}]: {}", self.field, self.message)
37 }
38 }
39}
40
41impl std::error::Error for ValidationError {}
42
43pub type ValidationResult<T> = Result<T, ValidationError>;
44
45pub trait Validate: Debug {
46 fn validate(&self) -> ValidationResult<()>;
47}
48
49pub trait MetadataValidation: Validate {
50 fn required_string_fields(&self) -> Vec<(&'static str, &str)>;
51
52 fn validate_required_fields(&self) -> ValidationResult<()> {
53 for (field_name, field_value) in self.required_string_fields() {
54 if field_value.is_empty() {
55 return Err(ValidationError::new(
56 field_name,
57 format!("{field_name} cannot be empty"),
58 ));
59 }
60 }
61 Ok(())
62 }
63}