Skip to main content

systemprompt_traits/
validation.rs

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