1use crate::prelude::*;
30use core::ops::{Deref, DerefMut};
31
32#[cfg(feature = "garde")]
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52pub struct Validated<T>(pub T);
53
54#[cfg(feature = "validator")]
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74pub struct ValidatedValidator<T>(pub T);
75
76#[cfg(feature = "garde")]
77impl<T> Validated<T> {
78 #[inline]
88 pub fn into_inner(self) -> T {
89 self.0
90 }
91}
92
93#[cfg(feature = "validator")]
94impl<T> ValidatedValidator<T> {
95 #[inline]
105 pub fn into_inner(self) -> T {
106 self.0
107 }
108}
109
110#[cfg(feature = "garde")]
111impl<T> Deref for Validated<T> {
112 type Target = T;
113 #[inline]
114 fn deref(&self) -> &T {
115 &self.0
116 }
117}
118
119#[cfg(feature = "validator")]
120impl<T> Deref for ValidatedValidator<T> {
121 type Target = T;
122 #[inline]
123 fn deref(&self) -> &T {
124 &self.0
125 }
126}
127
128#[cfg(feature = "garde")]
129impl<T> DerefMut for Validated<T> {
130 #[inline]
131 fn deref_mut(&mut self) -> &mut T {
132 &mut self.0
133 }
134}
135
136#[cfg(feature = "validator")]
137impl<T> DerefMut for ValidatedValidator<T> {
138 #[inline]
139 fn deref_mut(&mut self) -> &mut T {
140 &mut self.0
141 }
142}
143
144#[cfg(feature = "garde")]
145impl<T> From<T> for Validated<T> {
146 #[inline]
147 fn from(v: T) -> Self {
148 Self(v)
149 }
150}
151
152#[cfg(feature = "validator")]
153impl<T> From<T> for ValidatedValidator<T> {
154 #[inline]
155 fn from(v: T) -> Self {
156 Self(v)
157 }
158}
159
160#[cfg(feature = "garde")]
161impl<'de, T> serde_core::Deserialize<'de> for Validated<T>
162where
163 T: serde_core::Deserialize<'de> + garde::Validate<Context = ()>,
164{
165 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
166 where
167 D: serde_core::Deserializer<'de>,
168 {
169 use serde_core::de::Error as _;
170 let inner = T::deserialize(deserializer)?;
171 match inner.validate_with(&()) {
172 Ok(()) => Ok(Self(inner)),
173 Err(report) => Err(D::Error::custom(format_report(&report))),
174 }
175 }
176}
177
178#[cfg(feature = "validator")]
179impl<'de, T> serde_core::Deserialize<'de> for ValidatedValidator<T>
180where
181 T: serde_core::Deserialize<'de> + validator::Validate,
182{
183 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
184 where
185 D: serde_core::Deserializer<'de>,
186 {
187 use serde_core::de::Error as _;
188 let inner = T::deserialize(deserializer)?;
189 match inner.validate() {
190 Ok(()) => Ok(Self(inner)),
191 Err(errors) => Err(D::Error::custom(format_validator_errors(&errors))),
192 }
193 }
194}
195
196#[cfg(feature = "garde")]
197impl<T: serde_core::Serialize> serde_core::Serialize for Validated<T> {
198 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
199 where
200 S: serde_core::Serializer,
201 {
202 self.0.serialize(serializer)
203 }
204}
205
206#[cfg(feature = "validator")]
207impl<T: serde_core::Serialize> serde_core::Serialize for ValidatedValidator<T> {
208 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
209 where
210 S: serde_core::Serializer,
211 {
212 self.0.serialize(serializer)
213 }
214}
215
216#[cfg(feature = "garde")]
218fn format_report(report: &garde::Report) -> String {
219 use core::fmt::Write as _;
220 let mut out = String::with_capacity(64);
221 out.push_str("validation failed: ");
222 let mut first = true;
223 for (path, error) in report.iter() {
224 if !first {
225 out.push_str("; ");
226 }
227 first = false;
228 let _ = write!(out, "{path}: {error}");
229 }
230 if first {
231 out.push_str("<no details>");
232 }
233 out
234}
235
236#[cfg(feature = "validator")]
238fn format_validator_errors(errors: &validator::ValidationErrors) -> String {
239 use core::fmt::Write as _;
240 let mut out = String::with_capacity(64);
241 out.push_str("validation failed: ");
242 let mut first = true;
243 for (field, errs) in errors.field_errors() {
244 if !first {
245 out.push_str("; ");
246 }
247 first = false;
248 let _ = write!(out, "{field}: ");
249 let mut f_first = true;
250 for e in errs {
251 if !f_first {
252 out.push_str(", ");
253 }
254 f_first = false;
255 let _ = write!(out, "{e}");
256 }
257 }
258 if first {
259 out.push_str("<no details>");
260 }
261 out
262}