1use std::fmt;
36use std::ops::Deref;
37
38pub use vld;
39
40#[derive(Debug, Clone)]
44pub enum VldSurrealError {
45 Validation(vld::error::VldError),
47 Serialization(String),
49}
50
51impl fmt::Display for VldSurrealError {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 match self {
54 VldSurrealError::Validation(e) => write!(f, "Validation error: {}", e),
55 VldSurrealError::Serialization(e) => write!(f, "Serialization error: {}", e),
56 }
57 }
58}
59
60impl std::error::Error for VldSurrealError {
61 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
62 match self {
63 VldSurrealError::Validation(e) => Some(e),
64 VldSurrealError::Serialization(_) => None,
65 }
66 }
67}
68
69impl From<vld::error::VldError> for VldSurrealError {
70 fn from(e: vld::error::VldError) -> Self {
71 VldSurrealError::Validation(e)
72 }
73}
74
75#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
80pub struct FieldError {
81 pub field: String,
82 pub message: String,
83}
84
85#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
89pub struct VldSurrealResponse {
90 pub error: String,
91 pub fields: Vec<FieldError>,
92}
93
94impl VldSurrealResponse {
95 pub fn from_vld_error(e: &vld::error::VldError) -> Self {
97 let fields = e
98 .issues
99 .iter()
100 .map(|issue: &vld::error::ValidationIssue| FieldError {
101 field: issue
102 .path
103 .iter()
104 .map(|p| p.to_string())
105 .collect::<Vec<_>>()
106 .join("."),
107 message: issue.message.clone(),
108 })
109 .collect();
110
111 Self {
112 error: "Validation failed".to_string(),
113 fields,
114 }
115 }
116
117 pub fn from_error(e: &VldSurrealError) -> Self {
119 match e {
120 VldSurrealError::Validation(ve) => Self::from_vld_error(ve),
121 VldSurrealError::Serialization(msg) => Self {
122 error: "Serialization error".to_string(),
123 fields: vec![FieldError {
124 field: String::new(),
125 message: msg.clone(),
126 }],
127 },
128 }
129 }
130
131 pub fn to_json(&self) -> serde_json::Value {
133 serde_json::to_value(self).unwrap_or_default()
134 }
135}
136
137pub struct Validated<S, T> {
163 inner: T,
164 _schema: std::marker::PhantomData<S>,
165}
166
167impl<S, T> Validated<S, T>
168where
169 S: vld::schema::VldParse,
170 T: serde::Serialize,
171{
172 pub fn new(value: T) -> Result<Self, VldSurrealError> {
174 let json = serde_json::to_value(&value)
175 .map_err(|e| VldSurrealError::Serialization(e.to_string()))?;
176 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
177 Ok(Self {
178 inner: value,
179 _schema: std::marker::PhantomData,
180 })
181 }
182
183 pub fn inner(&self) -> &T {
185 &self.inner
186 }
187
188 pub fn into_inner(self) -> T {
190 self.inner
191 }
192}
193
194impl<S, T> Deref for Validated<S, T> {
195 type Target = T;
196 fn deref(&self) -> &T {
197 &self.inner
198 }
199}
200
201impl<S, T: fmt::Debug> fmt::Debug for Validated<S, T> {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 f.debug_struct("Validated")
204 .field("inner", &self.inner)
205 .finish()
206 }
207}
208
209impl<S, T: Clone> Clone for Validated<S, T> {
210 fn clone(&self) -> Self {
211 Self {
212 inner: self.inner.clone(),
213 _schema: std::marker::PhantomData,
214 }
215 }
216}
217
218impl<S, T: serde::Serialize> serde::Serialize for Validated<S, T> {
219 fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
220 self.inner.serialize(serializer)
221 }
222}
223
224pub fn validate_content<S, T>(value: &T) -> Result<(), VldSurrealError>
248where
249 S: vld::schema::VldParse,
250 T: serde::Serialize,
251{
252 let json =
253 serde_json::to_value(value).map_err(|e| VldSurrealError::Serialization(e.to_string()))?;
254 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
255 Ok(())
256}
257
258pub fn validate_json<S>(value: &serde_json::Value) -> Result<(), VldSurrealError>
276where
277 S: vld::schema::VldParse,
278{
279 S::vld_parse_value(value).map_err(VldSurrealError::Validation)?;
280 Ok(())
281}
282
283pub fn validate_record<S, T>(value: &T) -> Result<(), VldSurrealError>
287where
288 S: vld::schema::VldParse,
289 T: serde::Serialize,
290{
291 validate_content::<S, T>(value)
292}
293
294pub fn validate_records<S, T>(rows: &[T]) -> Result<(), (usize, VldSurrealError)>
318where
319 S: vld::schema::VldParse,
320 T: serde::Serialize,
321{
322 for (i, row) in rows.iter().enumerate() {
323 validate_record::<S, T>(row).map_err(|e| (i, e))?;
324 }
325 Ok(())
326}
327
328pub fn validate_value<S: vld::schema::VldSchema>(
343 schema: &S,
344 value: &serde_json::Value,
345) -> Result<(), VldSurrealError> {
346 schema
347 .parse_value(value)
348 .map(|_| ())
349 .map_err(VldSurrealError::Validation)
350}
351
352pub struct VldText<S> {
373 value: String,
374 _schema: std::marker::PhantomData<S>,
375}
376
377impl<S> Clone for VldText<S> {
378 fn clone(&self) -> Self {
379 Self {
380 value: self.value.clone(),
381 _schema: std::marker::PhantomData,
382 }
383 }
384}
385
386impl<S> PartialEq for VldText<S> {
387 fn eq(&self, other: &Self) -> bool {
388 self.value == other.value
389 }
390}
391impl<S> Eq for VldText<S> {}
392
393impl<S: vld::schema::VldParse> VldText<S> {
394 pub fn new(input: impl Into<String>) -> Result<Self, VldSurrealError> {
395 let s = input.into();
396 let json = serde_json::json!({ "value": s });
397 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
398 Ok(Self {
399 value: s,
400 _schema: std::marker::PhantomData,
401 })
402 }
403
404 pub fn new_unchecked(input: impl Into<String>) -> Self {
405 Self {
406 value: input.into(),
407 _schema: std::marker::PhantomData,
408 }
409 }
410
411 pub fn as_str(&self) -> &str {
412 &self.value
413 }
414
415 pub fn into_inner(self) -> String {
416 self.value
417 }
418}
419
420impl<S> Deref for VldText<S> {
421 type Target = str;
422 fn deref(&self) -> &str {
423 &self.value
424 }
425}
426
427impl<S> AsRef<str> for VldText<S> {
428 fn as_ref(&self) -> &str {
429 &self.value
430 }
431}
432
433impl<S> fmt::Debug for VldText<S> {
434 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435 write!(f, "VldText({:?})", self.value)
436 }
437}
438
439impl<S> fmt::Display for VldText<S> {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 f.write_str(&self.value)
442 }
443}
444
445impl<S> serde::Serialize for VldText<S> {
446 fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
447 self.value.serialize(serializer)
448 }
449}
450
451impl<'de, S: vld::schema::VldParse> serde::Deserialize<'de> for VldText<S> {
452 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
453 let s = String::deserialize(deserializer)?;
454 VldText::<S>::new(&s).map_err(serde::de::Error::custom)
455 }
456}
457
458pub struct VldInt<S> {
480 value: i64,
481 _schema: std::marker::PhantomData<S>,
482}
483
484impl<S> Clone for VldInt<S> {
485 fn clone(&self) -> Self {
486 *self
487 }
488}
489impl<S> Copy for VldInt<S> {}
490
491impl<S> PartialEq for VldInt<S> {
492 fn eq(&self, other: &Self) -> bool {
493 self.value == other.value
494 }
495}
496impl<S> Eq for VldInt<S> {}
497
498impl<S: vld::schema::VldParse> VldInt<S> {
499 pub fn new(input: i64) -> Result<Self, VldSurrealError> {
500 let json = serde_json::json!({ "value": input });
501 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
502 Ok(Self {
503 value: input,
504 _schema: std::marker::PhantomData,
505 })
506 }
507
508 pub fn new_unchecked(input: i64) -> Self {
509 Self {
510 value: input,
511 _schema: std::marker::PhantomData,
512 }
513 }
514
515 pub fn get(&self) -> i64 {
516 self.value
517 }
518}
519
520impl<S> Deref for VldInt<S> {
521 type Target = i64;
522 fn deref(&self) -> &i64 {
523 &self.value
524 }
525}
526
527impl<S> fmt::Debug for VldInt<S> {
528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529 write!(f, "VldInt({})", self.value)
530 }
531}
532
533impl<S> fmt::Display for VldInt<S> {
534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535 write!(f, "{}", self.value)
536 }
537}
538
539impl<S> serde::Serialize for VldInt<S> {
540 fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
541 self.value.serialize(serializer)
542 }
543}
544
545impl<'de, S: vld::schema::VldParse> serde::Deserialize<'de> for VldInt<S> {
546 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
547 let v = i64::deserialize(deserializer)?;
548 VldInt::<S>::new(v).map_err(serde::de::Error::custom)
549 }
550}
551
552pub struct VldFloat<S> {
573 value: f64,
574 _schema: std::marker::PhantomData<S>,
575}
576
577impl<S> Clone for VldFloat<S> {
578 fn clone(&self) -> Self {
579 *self
580 }
581}
582impl<S> Copy for VldFloat<S> {}
583
584impl<S> PartialEq for VldFloat<S> {
585 fn eq(&self, other: &Self) -> bool {
586 self.value == other.value
587 }
588}
589
590impl<S: vld::schema::VldParse> VldFloat<S> {
591 pub fn new(input: f64) -> Result<Self, VldSurrealError> {
592 let json = serde_json::json!({ "value": input });
593 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
594 Ok(Self {
595 value: input,
596 _schema: std::marker::PhantomData,
597 })
598 }
599
600 pub fn new_unchecked(input: f64) -> Self {
601 Self {
602 value: input,
603 _schema: std::marker::PhantomData,
604 }
605 }
606
607 pub fn get(&self) -> f64 {
608 self.value
609 }
610}
611
612impl<S> Deref for VldFloat<S> {
613 type Target = f64;
614 fn deref(&self) -> &f64 {
615 &self.value
616 }
617}
618
619impl<S> fmt::Debug for VldFloat<S> {
620 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621 write!(f, "VldFloat({})", self.value)
622 }
623}
624
625impl<S> fmt::Display for VldFloat<S> {
626 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627 write!(f, "{}", self.value)
628 }
629}
630
631impl<S> serde::Serialize for VldFloat<S> {
632 fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
633 self.value.serialize(serializer)
634 }
635}
636
637impl<'de, S: vld::schema::VldParse> serde::Deserialize<'de> for VldFloat<S> {
638 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
639 let v = f64::deserialize(deserializer)?;
640 VldFloat::<S>::new(v).map_err(serde::de::Error::custom)
641 }
642}
643
644pub struct VldBool<S> {
664 value: bool,
665 _schema: std::marker::PhantomData<S>,
666}
667
668impl<S> Clone for VldBool<S> {
669 fn clone(&self) -> Self {
670 *self
671 }
672}
673impl<S> Copy for VldBool<S> {}
674
675impl<S> PartialEq for VldBool<S> {
676 fn eq(&self, other: &Self) -> bool {
677 self.value == other.value
678 }
679}
680impl<S> Eq for VldBool<S> {}
681
682impl<S: vld::schema::VldParse> VldBool<S> {
683 pub fn new(input: bool) -> Result<Self, VldSurrealError> {
684 let json = serde_json::json!({ "value": input });
685 S::vld_parse_value(&json).map_err(VldSurrealError::Validation)?;
686 Ok(Self {
687 value: input,
688 _schema: std::marker::PhantomData,
689 })
690 }
691
692 pub fn new_unchecked(input: bool) -> Self {
693 Self {
694 value: input,
695 _schema: std::marker::PhantomData,
696 }
697 }
698
699 pub fn get(&self) -> bool {
700 self.value
701 }
702}
703
704impl<S> Deref for VldBool<S> {
705 type Target = bool;
706 fn deref(&self) -> &bool {
707 &self.value
708 }
709}
710
711impl<S> fmt::Debug for VldBool<S> {
712 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
713 write!(f, "VldBool({})", self.value)
714 }
715}
716
717impl<S> fmt::Display for VldBool<S> {
718 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719 write!(f, "{}", self.value)
720 }
721}
722
723impl<S> serde::Serialize for VldBool<S> {
724 fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
725 self.value.serialize(serializer)
726 }
727}
728
729impl<'de, S: vld::schema::VldParse> serde::Deserialize<'de> for VldBool<S> {
730 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
731 let v = bool::deserialize(deserializer)?;
732 VldBool::<S>::new(v).map_err(serde::de::Error::custom)
733 }
734}
735
736#[macro_export]
754macro_rules! validate_fields {
755 ($($field:ident => $schema:expr),* $(,)?) => {{
756 let mut __vld_errors: Vec<$crate::FieldError> = Vec::new();
757 $(
758 {
759 let __vld_val = ::serde_json::to_value(&$field).ok();
760 let __vld_schema = $schema;
761 if let Some(ref val) = __vld_val {
762 use $crate::vld::schema::VldSchema;
763 if let Err(_) = __vld_schema.validate(val) {
764 let msg = format!("field '{}' failed validation", stringify!($field));
765 __vld_errors.push($crate::FieldError {
766 field: stringify!($field).to_string(),
767 message: msg,
768 });
769 }
770 }
771 }
772 )*
773 if __vld_errors.is_empty() {
774 ::std::result::Result::Ok::<(), $crate::VldSurrealError>(())
775 } else {
776 let mut __vld_err = $crate::vld::error::VldError::new();
777 for fe in &__vld_errors {
778 __vld_err.issues.push($crate::vld::error::ValidationIssue {
779 code: $crate::vld::error::IssueCode::Custom {
780 code: fe.field.clone(),
781 },
782 message: fe.message.clone(),
783 path: vec![
784 $crate::vld::error::PathSegment::Field(fe.field.clone()),
785 ],
786 received: None,
787 });
788 }
789 ::std::result::Result::Err($crate::VldSurrealError::Validation(__vld_err))
790 }
791 }};
792}
793
794pub mod prelude {
797 pub use crate::{
798 validate_content, validate_fields, validate_json, validate_record, validate_records,
799 validate_value, FieldError, Validated, VldBool, VldFloat, VldInt, VldSurrealError,
800 VldSurrealResponse, VldText,
801 };
802 pub use vld::prelude::*;
803}