1use super::ValidationRuleContext;
4use super::Validator;
5use crate::group::SegmentGroupIndexed;
6use crate::{EdifactError, Segment, ValidationIssue, ValidationReport, ValidationSeverity};
7use std::sync::Arc;
8
9pub trait ProfileRule: Send + Sync {
29 fn evaluate(
33 &self,
34 segments: &[Segment<'_>],
35 context: &ValidationRuleContext<'_>,
36 issues: &mut Vec<ValidationIssue>,
37 );
38}
39
40struct ClosureProfileRule<F>(F);
42
43impl<F> ProfileRule for ClosureProfileRule<F>
44where
45 F: for<'a> Fn(&[Segment<'a>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>)
46 + Send
47 + Sync,
48{
49 fn evaluate(
50 &self,
51 segments: &[Segment<'_>],
52 context: &ValidationRuleContext<'_>,
53 issues: &mut Vec<ValidationIssue>,
54 ) {
55 (self.0)(segments, context, issues);
56 }
57}
58
59struct StatelessClosureProfileRule<F>(F);
61
62impl<F> ProfileRule for StatelessClosureProfileRule<F>
63where
64 F: for<'a> Fn(&[Segment<'a>], &mut Vec<ValidationIssue>) + Send + Sync,
65{
66 fn evaluate(
67 &self,
68 segments: &[Segment<'_>],
69 _context: &ValidationRuleContext<'_>,
70 issues: &mut Vec<ValidationIssue>,
71 ) {
72 (self.0)(segments, issues);
73 }
74}
75
76pub(super) struct NamedRule {
82 pub(super) id: Option<Arc<str>>,
86 pub(super) rule: Arc<dyn ProfileRule + Send + Sync>,
87}
88
89impl Clone for NamedRule {
90 fn clone(&self) -> Self {
91 Self {
92 id: self.id.clone(),
93 rule: Arc::clone(&self.rule),
94 }
95 }
96}
97
98pub(super) struct NamedGroupRule {
109 pub(super) id: Option<Arc<str>>,
111 pub(super) group_scope: Option<Arc<str>>,
116 #[allow(clippy::type_complexity)]
118 pub(super) rule: Arc<
119 dyn Fn(
120 &SegmentGroupIndexed,
121 &[Segment<'_>],
122 &ValidationRuleContext<'_>,
123 &mut Vec<ValidationIssue>,
124 ) + Send
125 + Sync,
126 >,
127}
128
129impl Clone for NamedGroupRule {
130 fn clone(&self) -> Self {
131 Self {
132 id: self.id.clone(),
133 group_scope: self.group_scope.clone(),
134 rule: Arc::clone(&self.rule),
135 }
136 }
137}
138
139pub struct ProfileRulePack {
141 name: String,
142 message_types: smallvec::SmallVec<[String; 2]>,
147 release: Option<String>,
149 pub(super) rules: Vec<NamedRule>,
150 pub(super) group_rules: Vec<NamedGroupRule>,
151 pub(super) bail_on_first_error: bool,
152 pub(super) max_issues_per_rule: Option<usize>,
158}
159
160impl ProfileRulePack {
161 pub fn new(name: impl Into<String>) -> Self {
163 Self {
164 name: name.into(),
165 message_types: smallvec::SmallVec::new(),
166 release: None,
167 rules: Vec::new(),
168 group_rules: Vec::new(),
169 bail_on_first_error: false,
170 max_issues_per_rule: None,
171 }
172 }
173
174 pub fn name(&self) -> &str {
176 &self.name
177 }
178
179 pub fn message_types(&self) -> impl Iterator<Item = &str> {
181 self.message_types.iter().map(|s| s.as_str())
182 }
183
184 pub fn rule_count(&self) -> usize {
186 self.rules.len()
187 }
188
189 pub fn named_rule_count(&self) -> usize {
191 self.rules.iter().filter(|r| r.id.is_some()).count()
192 }
193
194 pub fn anonymous_rule_count(&self) -> usize {
196 self.rules.iter().filter(|r| r.id.is_none()).count()
197 }
198
199 pub fn rule_ids(&self) -> impl Iterator<Item = &str> {
201 self.rules.iter().filter_map(|r| r.id.as_deref())
202 }
203
204 pub fn release(&self) -> Option<&str> {
206 self.release.as_deref()
207 }
208
209 pub fn for_message_type(mut self, message_type: impl Into<String>) -> Self {
211 let s = message_type.into();
212 if !self.message_types.iter().any(|x| x == &s) {
213 self.message_types.push(s);
214 }
215 self
216 }
217
218 pub fn for_release(mut self, release: impl Into<String>) -> Self {
220 self.release = Some(release.into());
221 self
222 }
223
224 pub fn with_bail_on_first_error(mut self, bail: bool) -> Self {
227 self.bail_on_first_error = bail;
228 self
229 }
230
231 pub fn with_max_issues_per_rule(mut self, limit: impl Into<Option<usize>>) -> Self {
241 self.max_issues_per_rule = limit.into();
242 self
243 }
244
245 pub fn with_rule_fn<F>(mut self, rule: F) -> Self
247 where
248 F: for<'a> Fn(&[Segment<'a>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>)
249 + Send
250 + Sync
251 + 'static,
252 {
253 self.rules.push(NamedRule {
254 id: None,
255 rule: Arc::new(ClosureProfileRule(rule)),
256 });
257 self
258 }
259
260 pub fn with_named_rule_fn<F>(mut self, id: impl Into<Arc<str>>, rule: F) -> Self
262 where
263 F: for<'a> Fn(&[Segment<'a>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>)
264 + Send
265 + Sync
266 + 'static,
267 {
268 self.rules.push(NamedRule {
269 id: Some(id.into()),
270 rule: Arc::new(ClosureProfileRule(rule)),
271 });
272 self
273 }
274
275 pub fn with_stateless_rule_fn<F>(mut self, rule: F) -> Self
277 where
278 F: for<'a> Fn(&[Segment<'a>], &mut Vec<ValidationIssue>) + Send + Sync + 'static,
279 {
280 self.rules.push(NamedRule {
281 id: None,
282 rule: Arc::new(StatelessClosureProfileRule(rule)),
283 });
284 self
285 }
286
287 pub fn with_named_stateless_rule_fn<F>(mut self, id: impl Into<Arc<str>>, rule: F) -> Self
289 where
290 F: for<'a> Fn(&[Segment<'a>], &mut Vec<ValidationIssue>) + Send + Sync + 'static,
291 {
292 self.rules.push(NamedRule {
293 id: Some(id.into()),
294 rule: Arc::new(StatelessClosureProfileRule(rule)),
295 });
296 self
297 }
298
299 pub fn require_segment(self, tag: &'static str, rule_id: impl Into<Arc<str>>) -> Self {
311 let id: Arc<str> = rule_id.into();
312 self.with_named_stateless_rule_fn(id.clone(), move |segments, issues| {
313 if !segments.iter().any(|s| s.tag == tag) {
314 issues.push(
315 ValidationIssue::new(
316 ValidationSeverity::Error,
317 format!("mandatory segment {tag} is missing"),
318 )
319 .with_segment(tag)
320 .with_rule_id(id.as_ref()),
321 );
322 }
323 })
324 }
325
326 pub fn forbid_segment(self, tag: &'static str, rule_id: impl Into<Arc<str>>) -> Self {
330 let id: Arc<str> = rule_id.into();
331 self.with_named_stateless_rule_fn(id.clone(), move |segments, issues| {
332 for (occ, s) in segments.iter().filter(|s| s.tag == tag).enumerate() {
333 issues.push(
334 ValidationIssue::new(
335 ValidationSeverity::Error,
336 format!("segment {tag} must not appear"),
337 )
338 .with_span(s.span)
339 .with_segment(tag)
340 .with_segment_occurrence(u16::try_from(occ).unwrap_or(u16::MAX))
341 .with_rule_id(id.as_ref()),
342 );
343 }
344 })
345 }
346
347 pub fn require_qualifier(
350 self,
351 tag: &'static str,
352 element: u8,
353 component: u8,
354 qualifier: &'static str,
355 rule_id: impl Into<Arc<str>>,
356 ) -> Self {
357 let id: Arc<str> = rule_id.into();
358 self.with_named_stateless_rule_fn(id.clone(), move |segments, issues| {
359 for (occ, s) in segments.iter().filter(|s| s.tag == tag).enumerate() {
360 let actual = s
361 .get_element(element as usize)
362 .and_then(|e| e.get_component(component as usize));
363 if actual != Some(qualifier) {
364 issues.push(
365 ValidationIssue::new(
366 ValidationSeverity::Error,
367 format!(
368 "segment {tag} element {element} component {component} must be \
369 {qualifier:?} but found {:?}",
370 actual.unwrap_or("<absent>")
371 ),
372 )
373 .with_segment(tag)
374 .with_element_index(element)
375 .with_component_index(component)
376 .with_segment_occurrence(u16::try_from(occ).unwrap_or(u16::MAX))
377 .with_rule_id(id.as_ref()),
378 );
379 }
380 }
381 })
382 }
383
384 pub fn with_group_rule_fn<F>(mut self, rule: F) -> Self
402 where
403 F: Fn(
404 &SegmentGroupIndexed,
405 &[Segment<'_>],
406 &ValidationRuleContext<'_>,
407 &mut Vec<ValidationIssue>,
408 ) + Send
409 + Sync
410 + 'static,
411 {
412 self.group_rules.push(NamedGroupRule {
413 id: None,
414 group_scope: None,
415 rule: Arc::new(rule),
416 });
417 self
418 }
419
420 pub fn with_named_group_rule_fn<F>(mut self, id: impl Into<Arc<str>>, rule: F) -> Self
422 where
423 F: Fn(
424 &SegmentGroupIndexed,
425 &[Segment<'_>],
426 &ValidationRuleContext<'_>,
427 &mut Vec<ValidationIssue>,
428 ) + Send
429 + Sync
430 + 'static,
431 {
432 self.group_rules.push(NamedGroupRule {
433 id: Some(id.into()),
434 group_scope: None,
435 rule: Arc::new(rule),
436 });
437 self
438 }
439
440 pub fn with_scoped_group_rule_fn<F>(
463 mut self,
464 group_scope: impl Into<Arc<str>>,
465 id: impl Into<Arc<str>>,
466 rule: F,
467 ) -> Self
468 where
469 F: Fn(
470 &SegmentGroupIndexed,
471 &[Segment<'_>],
472 &ValidationRuleContext<'_>,
473 &mut Vec<ValidationIssue>,
474 ) + Send
475 + Sync
476 + 'static,
477 {
478 self.group_rules.push(NamedGroupRule {
479 id: Some(id.into()),
480 group_scope: Some(group_scope.into()),
481 rule: Arc::new(rule),
482 });
483 self
484 }
485
486 pub fn require_segment_in_group(
495 self,
496 group_scope: impl Into<Arc<str>>,
497 tag: &'static str,
498 rule_id: impl Into<Arc<str>>,
499 ) -> Self {
500 let scope: Arc<str> = group_scope.into();
501 let id: Arc<str> = rule_id.into();
502 let scope_msg = Arc::clone(&scope);
503 self.with_scoped_group_rule_fn(scope, id.clone(), move |_group, segs, _ctx, issues| {
504 if !segs.iter().any(|s| s.tag == tag) {
505 issues.push(
506 ValidationIssue::new(
507 ValidationSeverity::Error,
508 format!("mandatory segment {tag} is missing from group {scope_msg}"),
509 )
510 .with_segment(tag)
511 .with_rule_id(id.as_ref()),
512 );
513 }
514 })
515 }
516
517 pub fn forbid_segment_in_group(
523 self,
524 group_scope: impl Into<Arc<str>>,
525 tag: &'static str,
526 rule_id: impl Into<Arc<str>>,
527 ) -> Self {
528 let scope: Arc<str> = group_scope.into();
529 let id: Arc<str> = rule_id.into();
530 let scope_msg = Arc::clone(&scope);
531 self.with_scoped_group_rule_fn(scope, id.clone(), move |_group, segs, _ctx, issues| {
532 for (occ, s) in segs.iter().filter(|s| s.tag == tag).enumerate() {
533 issues.push(
534 ValidationIssue::new(
535 ValidationSeverity::Error,
536 format!("segment {tag} must not appear in group {scope_msg}"),
537 )
538 .with_span(s.span)
539 .with_segment(tag)
540 .with_segment_occurrence(u16::try_from(occ).unwrap_or(u16::MAX))
541 .with_rule_id(id.as_ref()),
542 );
543 }
544 })
545 }
546
547 pub fn require_qualifier_in_group(
552 self,
553 group_scope: impl Into<Arc<str>>,
554 tag: &'static str,
555 element: u8,
556 component: u8,
557 qualifier: &'static str,
558 rule_id: impl Into<Arc<str>>,
559 ) -> Self {
560 let scope: Arc<str> = group_scope.into();
561 let id: Arc<str> = rule_id.into();
562 let scope_msg = Arc::clone(&scope);
563 self.with_scoped_group_rule_fn(scope, id.clone(), move |_group, segs, _ctx, issues| {
564 for (occ, s) in segs.iter().filter(|s| s.tag == tag).enumerate() {
565 let actual = s
566 .get_element(element as usize)
567 .and_then(|e| e.get_component(component as usize));
568 if actual != Some(qualifier) {
569 issues.push(
570 ValidationIssue::new(
571 ValidationSeverity::Error,
572 format!(
573 "segment {tag} element {element} component {component} must be \
574 {qualifier:?} in group {scope_msg}, found {:?}",
575 actual.unwrap_or("<absent>")
576 ),
577 )
578 .with_segment(tag)
579 .with_element_index(element)
580 .with_component_index(component)
581 .with_segment_occurrence(u16::try_from(occ).unwrap_or(u16::MAX))
582 .with_rule_id(id.as_ref()),
583 );
584 }
585 }
586 })
587 }
588
589 pub fn group_rule_count(&self) -> usize {
591 self.group_rules.len()
592 }
593
594 fn walk_group_tree(
600 &self,
601 group: &SegmentGroupIndexed,
602 all_segments: &[Segment<'_>],
603 report: &mut ValidationReport,
604 context: &ValidationRuleContext<'_>,
605 ) {
606 let group_segs = all_segments.get(group.total_span.clone()).unwrap_or(&[]);
607 let mut rule_issues: Vec<ValidationIssue> = Vec::new();
608
609 for named in &self.group_rules {
610 if let Some(scope) = &named.group_scope {
612 if group.definition != scope.as_ref() {
613 continue;
614 }
615 }
616 let errors_before = report.errors.len();
617 (named.rule)(group, group_segs, context, &mut rule_issues);
618 if let Some(limit) = self.max_issues_per_rule {
622 rule_issues.truncate(limit);
623 }
624 for mut issue in rule_issues.drain(..) {
625 if issue.segment_group.is_none() {
627 issue = issue.with_segment_group(group.definition);
628 }
629 match issue.severity {
630 ValidationSeverity::Critical | ValidationSeverity::Error => {
631 report.add_error(issue);
632 }
633 ValidationSeverity::Warning => {
634 report.add_warning(issue);
635 }
636 ValidationSeverity::Info => {
637 report.add_info(issue);
638 }
639 }
640 }
641 if self.bail_on_first_error && report.errors.len() > errors_before {
642 return;
643 }
644 }
645
646 for child in &group.children {
647 let errors_before_child = report.errors.len();
648 self.walk_group_tree(child, all_segments, report, context);
649 if self.bail_on_first_error && report.errors.len() > errors_before_child {
650 return;
651 }
652 }
653 }
654
655 pub fn with_rule(mut self, rule: impl ProfileRule + 'static) -> Self {
657 self.rules.push(NamedRule {
658 id: None,
659 rule: Arc::new(rule),
660 });
661 self
662 }
663
664 pub fn with_named_rule(
666 mut self,
667 id: impl Into<Arc<str>>,
668 rule: impl ProfileRule + 'static,
669 ) -> Self {
670 self.rules.push(NamedRule {
671 id: Some(id.into()),
672 rule: Arc::new(rule),
673 });
674 self
675 }
676
677 pub fn extend_from(mut self, base: &ProfileRulePack) -> Result<Self, EdifactError> {
713 let mut combined = base.rules.clone();
714 combined.append(&mut self.rules);
715 self.rules = combined;
716 let mut combined_group = base.group_rules.clone();
718 combined_group.append(&mut self.group_rules);
719 self.group_rules = combined_group;
720 for mt in &base.message_types {
721 if !self.message_types.iter().any(|x| x == mt) {
722 self.message_types.push(mt.clone());
723 }
724 }
725 self.release = merge_release_scopes(self.release.take(), base.release.clone())?;
726 Ok(self)
727 }
728
729 pub fn merge_with_override(mut self, mut other: Self) -> Result<Self, EdifactError> {
758 let mut id_to_index: std::collections::HashMap<Arc<str>, usize> = Default::default();
759 for (idx, rule) in self.rules.iter().enumerate() {
760 if let Some(id) = &rule.id {
761 id_to_index.insert(id.clone(), idx);
762 }
763 }
764
765 let mut replacements: Vec<(usize, NamedRule)> = Vec::new();
766 let mut to_append = Vec::new();
767
768 for other_rule in other.rules.drain(..) {
769 if let Some(id) = &other_rule.id {
770 if let Some(&idx) = id_to_index.get(id) {
771 replacements.push((idx, other_rule));
772 } else {
773 to_append.push(other_rule);
774 }
775 } else {
776 to_append.push(other_rule);
777 }
778 }
779
780 for (idx, rule) in replacements {
781 if idx < self.rules.len() {
782 self.rules[idx] = rule;
783 }
784 }
785
786 self.rules.append(&mut to_append);
787 for mt in other.message_types.drain(..) {
788 if !self.message_types.contains(&mt) {
789 self.message_types.push(mt);
790 }
791 }
792 let mut group_id_to_index: std::collections::HashMap<Arc<str>, usize> = Default::default();
794 for (idx, rule) in self.group_rules.iter().enumerate() {
795 if let Some(id) = &rule.id {
796 group_id_to_index.insert(id.clone(), idx);
797 }
798 }
799 let mut group_replacements: Vec<(usize, NamedGroupRule)> = Vec::new();
800 let mut group_to_append = Vec::new();
801 for other_rule in other.group_rules.drain(..) {
802 if let Some(id) = &other_rule.id {
803 if let Some(&idx) = group_id_to_index.get(id) {
804 group_replacements.push((idx, other_rule));
805 } else {
806 group_to_append.push(other_rule);
807 }
808 } else {
809 group_to_append.push(other_rule);
810 }
811 }
812 for (idx, rule) in group_replacements {
813 if idx < self.group_rules.len() {
814 self.group_rules[idx] = rule;
815 }
816 }
817 self.group_rules.append(&mut group_to_append);
818 self.release = merge_release_scopes(self.release.take(), other.release.take())?;
819 Ok(self)
820 }
821}
822
823pub(super) fn merge_release_scopes(
824 current: Option<String>,
825 incoming: Option<String>,
826) -> Result<Option<String>, EdifactError> {
827 match (current, incoming) {
828 (Some(x), Some(y)) if x != y => Err(EdifactError::IncompatibleReleaseScopes {
829 current: x,
830 incoming: y,
831 }),
832 (Some(x), Some(_)) => Ok(Some(x)),
833 (Some(x), None) => Ok(Some(x)),
834 (None, incoming) => Ok(incoming),
835 }
836}
837
838impl Validator for ProfileRulePack {
839 fn validate_batch(
840 &self,
841 segments: &[Segment<'_>],
842 report: &mut ValidationReport,
843 context: &ValidationRuleContext<'_>,
844 ) {
845 let unh_e1_storage;
848 let unh_e1: Option<&crate::model::Element<'_>> = if context.message_type.is_some() {
849 None
850 } else {
851 unh_e1_storage = segments
852 .iter()
853 .find(|s| s.tag == "UNH")
854 .and_then(|s| s.get_element(1));
855 unh_e1_storage
856 };
857
858 let message_type = context
859 .message_type
860 .or_else(|| unh_e1.and_then(|e| e.get_component(0)));
861
862 if !self.message_types.is_empty()
863 && !message_type.is_some_and(|mt| self.message_types.iter().any(|x| x.as_str() == mt))
864 {
865 return;
866 }
867
868 if let Some(bound_release) = &self.release {
869 let msg_association = segments
870 .iter()
871 .find(|s| s.tag == "UNH")
872 .and_then(|s| s.get_element(1))
873 .and_then(|e| e.get_component(4));
874 if msg_association != Some(bound_release.as_str()) {
875 return;
876 }
877 }
878
879 let mut rule_issues: Vec<ValidationIssue> = Vec::new();
880
881 for named in &self.rules {
882 let errors_before = report.errors.len();
883 named.rule.evaluate(segments, context, &mut rule_issues);
884 if let Some(limit) = self.max_issues_per_rule {
886 rule_issues.truncate(limit);
887 }
888 for issue in rule_issues.drain(..) {
889 match issue.severity {
890 ValidationSeverity::Critical | ValidationSeverity::Error => {
891 report.add_error(issue);
892 }
893 ValidationSeverity::Warning => {
894 report.add_warning(issue);
895 }
896 ValidationSeverity::Info => {
897 report.add_info(issue);
898 }
899 }
900 }
901 if self.bail_on_first_error && report.errors.len() > errors_before {
902 return;
903 }
904 }
905 }
906
907 fn validate_group_batch(
908 &self,
909 root: &SegmentGroupIndexed,
910 all_segments: &[Segment<'_>],
911 report: &mut ValidationReport,
912 context: &ValidationRuleContext<'_>,
913 ) {
914 if self.group_rules.is_empty() {
915 return;
916 }
917
918 let unh_e1_storage;
920 let unh_e1: Option<&crate::model::Element<'_>> = if context.message_type.is_some() {
921 None
922 } else {
923 unh_e1_storage = all_segments
924 .iter()
925 .find(|s| s.tag == "UNH")
926 .and_then(|s| s.get_element(1));
927 unh_e1_storage
928 };
929 let message_type = context
930 .message_type
931 .or_else(|| unh_e1.and_then(|e| e.get_component(0)));
932
933 if !self.message_types.is_empty()
934 && !message_type.is_some_and(|mt| self.message_types.iter().any(|x| x.as_str() == mt))
935 {
936 return;
937 }
938
939 if let Some(bound_release) = &self.release {
940 let msg_association = all_segments
941 .iter()
942 .find(|s| s.tag == "UNH")
943 .and_then(|s| s.get_element(1))
944 .and_then(|e| e.get_component(4));
945 if msg_association != Some(bound_release.as_str()) {
946 return;
947 }
948 }
949
950 self.walk_group_tree(root, all_segments, report, context);
951 }
952
953 fn has_group_rules(&self) -> bool {
954 !self.group_rules.is_empty()
955 }
956
957 fn fork(&self) -> Option<Box<dyn Validator + Send + Sync>> {
958 Some(Box::new(self.clone()))
959 }
960}
961
962impl Clone for ProfileRulePack {
963 fn clone(&self) -> Self {
964 Self {
965 name: self.name.clone(),
966 message_types: self.message_types.clone(),
967 release: self.release.clone(),
968 rules: self.rules.clone(),
969 group_rules: self.group_rules.clone(),
970 bail_on_first_error: self.bail_on_first_error,
971 max_issues_per_rule: self.max_issues_per_rule,
972 }
973 }
974}
975
976impl std::fmt::Debug for ProfileRulePack {
977 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
978 f.debug_struct("ProfileRulePack")
979 .field("name", &self.name)
980 .field("message_types", &self.message_types)
981 .field("release", &self.release)
982 .field("rule_count", &self.rules.len())
983 .field("group_rule_count", &self.group_rules.len())
984 .field("bail_on_first_error", &self.bail_on_first_error)
985 .finish()
986 }
987}
988
989impl Validator for Arc<ProfileRulePack> {
1014 fn validate_batch(
1015 &self,
1016 segments: &[Segment<'_>],
1017 report: &mut ValidationReport,
1018 context: &ValidationRuleContext<'_>,
1019 ) {
1020 self.as_ref().validate_batch(segments, report, context);
1021 }
1022
1023 fn validate_group_batch(
1024 &self,
1025 root: &SegmentGroupIndexed,
1026 all_segments: &[Segment<'_>],
1027 report: &mut ValidationReport,
1028 context: &ValidationRuleContext<'_>,
1029 ) {
1030 self.as_ref()
1031 .validate_group_batch(root, all_segments, report, context);
1032 }
1033
1034 fn has_group_rules(&self) -> bool {
1035 self.as_ref().has_group_rules()
1036 }
1037
1038 fn fork(&self) -> Option<Box<dyn Validator + Send + Sync>> {
1039 Some(Box::new(Arc::clone(self)))
1040 }
1041}