Skip to main content

made_core/value_objects/
output_field_rule.rs

1use std::collections::BTreeSet;
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::DomainError;
6
7use super::output_contract_validation::{
8    validate_text, MAX_ALLOWED_VALUES_PER_FIELD, MAX_ALLOWED_VALUE_LEN,
9};
10
11/// Validation rules for one named field in a structured output object.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
13pub struct OutputFieldRule {
14    required: bool,
15    #[serde(default)]
16    allowed_string_values: BTreeSet<String>,
17}
18
19impl OutputFieldRule {
20    pub fn new(
21        required: bool,
22        allowed_string_values: impl IntoIterator<Item = impl Into<String>>,
23    ) -> Result<Self, DomainError> {
24        let values = allowed_string_values
25            .into_iter()
26            .map(|value| {
27                validate_text(
28                    &value.into(),
29                    "output_contract.field.allowed_value",
30                    MAX_ALLOWED_VALUE_LEN,
31                )
32            })
33            .collect::<Result<BTreeSet<_>, _>>()?;
34        if values.len() > MAX_ALLOWED_VALUES_PER_FIELD {
35            return Err(DomainError::OutOfRange {
36                field: "output_contract.field.allowed_values",
37                value: values.len() as f64,
38                min: 0.0,
39                max: MAX_ALLOWED_VALUES_PER_FIELD as f64,
40            });
41        }
42        Ok(Self {
43            required,
44            allowed_string_values: values,
45        })
46    }
47
48    #[must_use]
49    pub const fn required(&self) -> bool {
50        self.required
51    }
52
53    #[must_use]
54    pub fn allowed_string_values(&self) -> &BTreeSet<String> {
55        &self.allowed_string_values
56    }
57}