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_offset(s.span.start)
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_offset(s.span.start)
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 for mut issue in rule_issues.drain(..) {
619 if issue.segment_group.is_none() {
621 issue = issue.with_segment_group(group.definition);
622 }
623 match issue.severity {
624 ValidationSeverity::Critical | ValidationSeverity::Error => {
625 report.add_error(issue);
626 }
627 ValidationSeverity::Warning => {
628 report.add_warning(issue);
629 }
630 ValidationSeverity::Info => {
631 report.add_info(issue);
632 }
633 }
634 }
635 if self.bail_on_first_error && report.errors.len() > errors_before {
636 return;
637 }
638 }
639
640 for child in &group.children {
641 let errors_before_child = report.errors.len();
642 self.walk_group_tree(child, all_segments, report, context);
643 if self.bail_on_first_error && report.errors.len() > errors_before_child {
644 return;
645 }
646 }
647 }
648
649 pub fn with_rule(mut self, rule: impl ProfileRule + 'static) -> Self {
651 self.rules.push(NamedRule {
652 id: None,
653 rule: Arc::new(rule),
654 });
655 self
656 }
657
658 pub fn with_named_rule(
660 mut self,
661 id: impl Into<Arc<str>>,
662 rule: impl ProfileRule + 'static,
663 ) -> Self {
664 self.rules.push(NamedRule {
665 id: Some(id.into()),
666 rule: Arc::new(rule),
667 });
668 self
669 }
670
671 pub fn extend_from(mut self, base: &ProfileRulePack) -> Result<Self, EdifactError> {
707 let mut combined = base.rules.clone();
708 combined.append(&mut self.rules);
709 self.rules = combined;
710 let mut combined_group = base.group_rules.clone();
712 combined_group.append(&mut self.group_rules);
713 self.group_rules = combined_group;
714 for mt in &base.message_types {
715 if !self.message_types.iter().any(|x| x == mt) {
716 self.message_types.push(mt.clone());
717 }
718 }
719 self.release = merge_release_scopes(self.release.take(), base.release.clone())?;
720 Ok(self)
721 }
722
723 pub fn merge_with_override(mut self, mut other: Self) -> Result<Self, EdifactError> {
752 let mut id_to_index: std::collections::HashMap<Arc<str>, usize> = Default::default();
753 for (idx, rule) in self.rules.iter().enumerate() {
754 if let Some(id) = &rule.id {
755 id_to_index.insert(id.clone(), idx);
756 }
757 }
758
759 let mut replacements: Vec<(usize, NamedRule)> = Vec::new();
760 let mut to_append = Vec::new();
761
762 for other_rule in other.rules.drain(..) {
763 if let Some(id) = &other_rule.id {
764 if let Some(&idx) = id_to_index.get(id) {
765 replacements.push((idx, other_rule));
766 } else {
767 to_append.push(other_rule);
768 }
769 } else {
770 to_append.push(other_rule);
771 }
772 }
773
774 for (idx, rule) in replacements {
775 if idx < self.rules.len() {
776 self.rules[idx] = rule;
777 }
778 }
779
780 self.rules.append(&mut to_append);
781 for mt in other.message_types.drain(..) {
782 if !self.message_types.iter().any(|x| *x == mt) {
783 self.message_types.push(mt);
784 }
785 }
786 let mut group_id_to_index: std::collections::HashMap<Arc<str>, usize> = Default::default();
788 for (idx, rule) in self.group_rules.iter().enumerate() {
789 if let Some(id) = &rule.id {
790 group_id_to_index.insert(id.clone(), idx);
791 }
792 }
793 let mut group_replacements: Vec<(usize, NamedGroupRule)> = Vec::new();
794 let mut group_to_append = Vec::new();
795 for other_rule in other.group_rules.drain(..) {
796 if let Some(id) = &other_rule.id {
797 if let Some(&idx) = group_id_to_index.get(id) {
798 group_replacements.push((idx, other_rule));
799 } else {
800 group_to_append.push(other_rule);
801 }
802 } else {
803 group_to_append.push(other_rule);
804 }
805 }
806 for (idx, rule) in group_replacements {
807 if idx < self.group_rules.len() {
808 self.group_rules[idx] = rule;
809 }
810 }
811 self.group_rules.append(&mut group_to_append);
812 self.release = merge_release_scopes(self.release.take(), other.release.take())?;
813 Ok(self)
814 }
815}
816
817pub(super) fn merge_release_scopes(
818 current: Option<String>,
819 incoming: Option<String>,
820) -> Result<Option<String>, EdifactError> {
821 match (current, incoming) {
822 (Some(x), Some(y)) if x != y => Err(EdifactError::IncompatibleReleaseScopes {
823 current: x,
824 incoming: y,
825 }),
826 (Some(x), Some(_)) => Ok(Some(x)),
827 (Some(x), None) => Ok(Some(x)),
828 (None, incoming) => Ok(incoming),
829 }
830}
831
832impl Validator for ProfileRulePack {
833 fn validate_batch(
834 &self,
835 segments: &[Segment<'_>],
836 report: &mut ValidationReport,
837 context: &ValidationRuleContext<'_>,
838 ) {
839 let unh_e1_storage;
842 let unh_e1: Option<&crate::model::Element<'_>> = if context.message_type.is_some() {
843 None
844 } else {
845 unh_e1_storage = segments
846 .iter()
847 .find(|s| s.tag == "UNH")
848 .and_then(|s| s.get_element(1));
849 unh_e1_storage
850 };
851
852 let message_type = context
853 .message_type
854 .or_else(|| unh_e1.and_then(|e| e.get_component(0)));
855
856 if !self.message_types.is_empty()
857 && !message_type.is_some_and(|mt| self.message_types.iter().any(|x| x.as_str() == mt))
858 {
859 return;
860 }
861
862 if let Some(bound_release) = &self.release {
863 let msg_association = segments
864 .iter()
865 .find(|s| s.tag == "UNH")
866 .and_then(|s| s.get_element(1))
867 .and_then(|e| e.get_component(4));
868 if msg_association != Some(bound_release.as_str()) {
869 return;
870 }
871 }
872
873 let mut rule_issues: Vec<ValidationIssue> = Vec::new();
874
875 for named in &self.rules {
876 let errors_before = report.errors.len();
877 named.rule.evaluate(segments, context, &mut rule_issues);
878 if let Some(limit) = self.max_issues_per_rule {
880 rule_issues.truncate(limit);
881 }
882 for issue in rule_issues.drain(..) {
883 match issue.severity {
884 ValidationSeverity::Critical | ValidationSeverity::Error => {
885 report.add_error(issue);
886 }
887 ValidationSeverity::Warning => {
888 report.add_warning(issue);
889 }
890 ValidationSeverity::Info => {
891 report.add_info(issue);
892 }
893 }
894 }
895 if self.bail_on_first_error && report.errors.len() > errors_before {
896 return;
897 }
898 }
899 }
900
901 fn validate_group_batch(
902 &self,
903 root: &SegmentGroupIndexed,
904 all_segments: &[Segment<'_>],
905 report: &mut ValidationReport,
906 context: &ValidationRuleContext<'_>,
907 ) {
908 if self.group_rules.is_empty() {
909 return;
910 }
911
912 let unh_e1_storage;
914 let unh_e1: Option<&crate::model::Element<'_>> = if context.message_type.is_some() {
915 None
916 } else {
917 unh_e1_storage = all_segments
918 .iter()
919 .find(|s| s.tag == "UNH")
920 .and_then(|s| s.get_element(1));
921 unh_e1_storage
922 };
923 let message_type = context
924 .message_type
925 .or_else(|| unh_e1.and_then(|e| e.get_component(0)));
926
927 if !self.message_types.is_empty()
928 && !message_type.is_some_and(|mt| self.message_types.iter().any(|x| x.as_str() == mt))
929 {
930 return;
931 }
932
933 if let Some(bound_release) = &self.release {
934 let msg_association = all_segments
935 .iter()
936 .find(|s| s.tag == "UNH")
937 .and_then(|s| s.get_element(1))
938 .and_then(|e| e.get_component(4));
939 if msg_association != Some(bound_release.as_str()) {
940 return;
941 }
942 }
943
944 self.walk_group_tree(root, all_segments, report, context);
945 }
946
947 fn has_group_rules(&self) -> bool {
948 !self.group_rules.is_empty()
949 }
950
951 fn fork(&self) -> Option<Box<dyn Validator + Send + Sync>> {
952 Some(Box::new(self.clone()))
953 }
954}
955
956impl Clone for ProfileRulePack {
957 fn clone(&self) -> Self {
958 Self {
959 name: self.name.clone(),
960 message_types: self.message_types.clone(),
961 release: self.release.clone(),
962 rules: self.rules.clone(),
963 group_rules: self.group_rules.clone(),
964 bail_on_first_error: self.bail_on_first_error,
965 max_issues_per_rule: self.max_issues_per_rule,
966 }
967 }
968}
969
970impl std::fmt::Debug for ProfileRulePack {
971 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
972 f.debug_struct("ProfileRulePack")
973 .field("name", &self.name)
974 .field("message_types", &self.message_types)
975 .field("release", &self.release)
976 .field("rule_count", &self.rules.len())
977 .field("group_rule_count", &self.group_rules.len())
978 .field("bail_on_first_error", &self.bail_on_first_error)
979 .finish()
980 }
981}
982
983impl Validator for Arc<ProfileRulePack> {
1008 fn validate_batch(
1009 &self,
1010 segments: &[Segment<'_>],
1011 report: &mut ValidationReport,
1012 context: &ValidationRuleContext<'_>,
1013 ) {
1014 self.as_ref().validate_batch(segments, report, context);
1015 }
1016
1017 fn validate_group_batch(
1018 &self,
1019 root: &SegmentGroupIndexed,
1020 all_segments: &[Segment<'_>],
1021 report: &mut ValidationReport,
1022 context: &ValidationRuleContext<'_>,
1023 ) {
1024 self.as_ref()
1025 .validate_group_batch(root, all_segments, report, context);
1026 }
1027
1028 fn has_group_rules(&self) -> bool {
1029 self.as_ref().has_group_rules()
1030 }
1031
1032 fn fork(&self) -> Option<Box<dyn Validator + Send + Sync>> {
1033 Some(Box::new(Arc::clone(self)))
1034 }
1035}