reovim_kernel/core/option/
constraint.rs1use std::fmt;
4
5use super::value::OptionValue;
6
7#[derive(Debug, Clone, Default, PartialEq, Eq)]
12pub struct OptionConstraint {
13 pub min: Option<i64>,
15 pub max: Option<i64>,
17 pub min_length: Option<usize>,
19 pub max_length: Option<usize>,
21}
22
23impl OptionConstraint {
24 #[must_use]
26 pub const fn none() -> Self {
27 Self {
28 min: None,
29 max: None,
30 min_length: None,
31 max_length: None,
32 }
33 }
34
35 #[must_use]
37 pub const fn range(min: i64, max: i64) -> Self {
38 Self {
39 min: Some(min),
40 max: Some(max),
41 min_length: None,
42 max_length: None,
43 }
44 }
45
46 #[must_use]
48 pub const fn min(min: i64) -> Self {
49 Self {
50 min: Some(min),
51 max: None,
52 min_length: None,
53 max_length: None,
54 }
55 }
56
57 #[must_use]
59 pub const fn max(max: i64) -> Self {
60 Self {
61 min: None,
62 max: Some(max),
63 min_length: None,
64 max_length: None,
65 }
66 }
67
68 #[must_use]
70 pub const fn string_length(min_length: usize, max_length: usize) -> Self {
71 Self {
72 min: None,
73 max: None,
74 min_length: Some(min_length),
75 max_length: Some(max_length),
76 }
77 }
78
79 pub fn validate(&self, value: &OptionValue) -> Result<(), ConstraintError> {
85 match value {
86 OptionValue::Integer(i) => {
87 if let Some(min) = self.min
88 && *i < min
89 {
90 return Err(ConstraintError::BelowMinimum { value: *i, min });
91 }
92 if let Some(max) = self.max
93 && *i > max
94 {
95 return Err(ConstraintError::AboveMaximum { value: *i, max });
96 }
97 }
98 OptionValue::String(s) => {
99 if let Some(min_len) = self.min_length
100 && s.len() < min_len
101 {
102 return Err(ConstraintError::StringTooShort {
103 len: s.len(),
104 min: min_len,
105 });
106 }
107 if let Some(max_len) = self.max_length
108 && s.len() > max_len
109 {
110 return Err(ConstraintError::StringTooLong {
111 len: s.len(),
112 max: max_len,
113 });
114 }
115 }
116 OptionValue::Choice { value, choices } => {
117 if !choices.contains(value) {
118 return Err(ConstraintError::InvalidChoice {
119 value: value.clone(),
120 choices: choices.clone(),
121 });
122 }
123 }
124 OptionValue::Bool(_) => {
125 }
127 }
128 Ok(())
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum ConstraintError {
135 BelowMinimum {
137 value: i64,
139 min: i64,
141 },
142 AboveMaximum {
144 value: i64,
146 max: i64,
148 },
149 StringTooShort {
151 len: usize,
153 min: usize,
155 },
156 StringTooLong {
158 len: usize,
160 max: usize,
162 },
163 InvalidChoice {
165 value: String,
167 choices: Vec<String>,
169 },
170}
171
172impl fmt::Display for ConstraintError {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 match self {
175 Self::BelowMinimum { value, min } => {
176 write!(f, "value {value} is below minimum {min}")
177 }
178 Self::AboveMaximum { value, max } => {
179 write!(f, "value {value} is above maximum {max}")
180 }
181 Self::StringTooShort { len, min } => {
182 write!(f, "string length {len} is below minimum {min}")
183 }
184 Self::StringTooLong { len, max } => {
185 write!(f, "string length {len} is above maximum {max}")
186 }
187 Self::InvalidChoice { value, choices } => {
188 write!(f, "'{value}' is not a valid choice (valid: {choices:?})")
189 }
190 }
191 }
192}
193
194impl std::error::Error for ConstraintError {}