yang_rs/
arg.rs

1//
2// YANG - YANG statement args.
3//  Copyright (C) 2021 Toshiaki Takada
4//
5
6use std::fmt;
7use std::iter::Iterator;
8use std::str::FromStr;
9use std::string::ToString;
10use url::Url;
11
12use derive_getters::Getters;
13
14use super::core::*;
15use super::error::*;
16use super::parser::*;
17
18// Aliases.
19pub type Prefix = Identifier;
20
21// TBD
22//
23//   yang-string         = *yang-char
24//
25//   ;; any Unicode or ISO/IEC 10646 character, including tab, carriage
26//   ;; return, and line feed but excluding the other C0 control
27//   ;; characters, the surrogate blocks, and the noncharacters
28//   yang-char = %x09 / %x0A / %x0D / %x20-D7FF /
29//                               ; exclude surrogate blocks %xD800-DFFF
30//              %xE000-FDCF /    ; exclude noncharacters %xFDD0-FDEF
31//              %xFDF0-FFFD /    ; exclude noncharacters %xFFFE-FFFF
32//              %x10000-1FFFD /  ; exclude noncharacters %x1FFFE-1FFFF
33//              %x20000-2FFFD /  ; exclude noncharacters %x2FFFE-2FFFF
34//              %x30000-3FFFD /  ; exclude noncharacters %x3FFFE-3FFFF
35//              %x40000-4FFFD /  ; exclude noncharacters %x4FFFE-4FFFF
36//              %x50000-5FFFD /  ; exclude noncharacters %x5FFFE-5FFFF
37//              %x60000-6FFFD /  ; exclude noncharacters %x6FFFE-6FFFF
38//              %x70000-7FFFD /  ; exclude noncharacters %x7FFFE-7FFFF
39//              %x80000-8FFFD /  ; exclude noncharacters %x8FFFE-8FFFF
40//              %x90000-9FFFD /  ; exclude noncharacters %x9FFFE-9FFFF
41//              %xA0000-AFFFD /  ; exclude noncharacters %xAFFFE-AFFFF
42//              %xB0000-BFFFD /  ; exclude noncharacters %xBFFFE-BFFFF
43//              %xC0000-CFFFD /  ; exclude noncharacters %xCFFFE-CFFFF
44//              %xD0000-DFFFD /  ; exclude noncharacters %xDFFFE-DFFFF
45//              %xE0000-EFFFD /  ; exclude noncharacters %xEFFFE-EFFFF
46//              %xF0000-FFFFD /  ; exclude noncharacters %xFFFFE-FFFFF
47//              %x100000-10FFFD  ; exclude noncharacters %x10FFFE-10FFFF
48//
49// YANG string, quoted or unquoted.
50fn parse_string(parser: &mut Parser) -> Result<String, YangError> {
51    let token = parser.get_token()?;
52    match token {
53        // Statement argument.
54        Token::Identifier(s) | Token::QuotedString(s) => Ok(s),
55        // End of Input.
56        Token::EndOfInput => Err(YangError::UnexpectedEof),
57        // Unexpected Token.
58        _ => Err(YangError::UnexpectedToken(token.to_string())),
59    }
60}
61
62///
63/// Trait for statement arg.
64///
65pub trait StmtArg {
66    /// Parse token and return StmtArg if it is valid.
67    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError>
68    where
69        Self: Sized;
70}
71
72///
73/// No Arg (for "input-stmt", "output-stmt").
74///
75#[derive(Debug, Clone, PartialEq)]
76pub struct NoArg;
77
78impl StmtArg for NoArg {
79    fn parse_arg(_parser: &mut Parser) -> Result<Self, YangError> {
80        Ok(NoArg)
81    }
82}
83
84///
85/// Yang Identifier.
86///
87#[derive(Debug, Clone, PartialEq, Getters)]
88pub struct Identifier {
89    str: String,
90}
91
92impl fmt::Display for Identifier {
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        write!(f, "{}", self.str)
95    }
96}
97
98impl FromStr for Identifier {
99    type Err = ArgError;
100
101    fn from_str(s: &str) -> Result<Self, Self::Err> {
102        if is_identifier(s) {
103            Ok(Identifier { str: s.to_string() })
104        } else {
105            Err(ArgError::new("identifier"))
106        }
107    }
108}
109
110impl StmtArg for Identifier {
111    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
112        let str = parse_string(parser)?;
113
114        match Identifier::from_str(&str) {
115            Ok(arg) => Ok(arg),
116            Err(e) => Err(YangError::ArgumentParseError(e.str)),
117        }
118    }
119}
120
121///
122/// "identity-ref".
123///
124#[derive(Clone, PartialEq, Getters)]
125pub struct IdentifierRef {
126    prefix: Option<Prefix>,
127    identifier: Identifier,
128}
129
130impl fmt::Debug for IdentifierRef {
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        match &self.prefix {
133            Some(prefix) => write!(f, "{}:{}", prefix, self.identifier),
134            None => write!(f, "{}", self.identifier),
135        }
136    }
137}
138
139impl ToString for IdentifierRef {
140    fn to_string(&self) -> String {
141        match &self.prefix {
142            Some(prefix) => format!("{}:{}", prefix, self.identifier),
143            None => format!("{}", self.identifier),
144        }
145    }
146}
147
148impl FromStr for IdentifierRef {
149    type Err = ArgError;
150
151    fn from_str(str: &str) -> Result<Self, Self::Err> {
152        match str.find(":") {
153            Some(p) => {
154                let prefix = Identifier::from_str(&str[..p])?;
155                let identifier = Identifier::from_str(&str[p + 1..])?;
156
157                Ok(IdentifierRef {
158                    prefix: Some(prefix),
159                    identifier,
160                })
161            }
162            None => {
163                let identifier = Identifier::from_str(&str)?;
164                Ok(IdentifierRef {
165                    prefix: None,
166                    identifier,
167                })
168            }
169        }
170    }
171}
172
173impl StmtArg for IdentifierRef {
174    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
175        let str = parse_string(parser)?;
176        IdentifierRef::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))
177    }
178}
179
180///
181/// "node-identifier".
182///
183#[derive(Clone, PartialEq, Getters)]
184pub struct NodeIdentifier {
185    prefix: Option<Prefix>,
186    identifier: Identifier,
187}
188
189impl fmt::Debug for NodeIdentifier {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        match &self.prefix {
192            Some(prefix) => write!(f, "{}:{}", prefix, self.identifier),
193            None => write!(f, "{}", self.identifier),
194        }
195    }
196}
197
198impl FromStr for NodeIdentifier {
199    type Err = ArgError;
200
201    fn from_str(s: &str) -> Result<Self, Self::Err> {
202        match s.find(":") {
203            Some(p) => {
204                let prefix = Identifier::from_str(&s[..p])?;
205                let identifier = Identifier::from_str(&s[p + 1..])?;
206
207                Ok(NodeIdentifier {
208                    prefix: Some(prefix),
209                    identifier,
210                })
211            }
212            None => {
213                let identifier = Identifier::from_str(&s)?;
214                Ok(NodeIdentifier {
215                    prefix: None,
216                    identifier,
217                })
218            }
219        }
220    }
221}
222
223impl ToString for NodeIdentifier {
224    fn to_string(&self) -> String {
225        match &self.prefix {
226            Some(prefix) => format!("{}:{}", prefix, self.identifier),
227            None => format!("{}", self.identifier),
228        }
229    }
230}
231
232impl StmtArg for NodeIdentifier {
233    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
234        let str = parse_string(parser)?;
235        NodeIdentifier::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))
236    }
237}
238
239///
240/// "unknown-stmt" keyword.
241///
242#[derive(Clone, PartialEq, Getters)]
243pub struct UnknownStmtKeyword {
244    prefix: Prefix,
245    identifier: Identifier,
246}
247
248impl fmt::Debug for UnknownStmtKeyword {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        write!(f, "{}:{}", self.prefix, self.identifier)
251    }
252}
253
254impl ToString for UnknownStmtKeyword {
255    fn to_string(&self) -> String {
256        format!("{}:{}", self.prefix, self.identifier)
257    }
258}
259
260impl FromStr for UnknownStmtKeyword {
261    type Err = ArgError;
262
263    fn from_str(str: &str) -> Result<Self, Self::Err> {
264        match str.find(":") {
265            Some(p) => {
266                let prefix = Identifier::from_str(&str[..p])?;
267                let identifier = Identifier::from_str(&str[p + 1..])?;
268
269                Ok(UnknownStmtKeyword { prefix, identifier })
270            }
271            None => Err(ArgError::new("unknown-stmt keyword")),
272        }
273    }
274}
275
276// Yang String.
277impl StmtArg for String {
278    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
279        Ok(parse_string(parser)?)
280    }
281}
282
283// URL string.
284impl StmtArg for Url {
285    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
286        let s = parse_string(parser)?;
287
288        match Url::parse(&s) {
289            Ok(url) => Ok(url),
290            Err(_) => Err(YangError::ArgumentParseError("url")),
291        }
292    }
293}
294
295///
296/// "yang-version-arg".
297///
298#[derive(Debug, Clone, PartialEq, Getters)]
299pub struct YangVersionArg {
300    str: String,
301}
302
303impl StmtArg for YangVersionArg {
304    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
305        let str = parse_string(parser)?;
306
307        // According to RFC7950, the version should be "1.1", but we relax it.
308
309        match parser.config().yang_version() {
310            Some(yang_version) => {
311                if str == yang_version {
312                    Ok(YangVersionArg { str })
313                } else {
314                    Err(YangError::ArgumentParseError("yang-version"))
315                }
316            }
317            None => Ok(YangVersionArg { str }),
318        }
319    }
320}
321
322///
323/// "date-arg".
324///
325#[derive(Debug, Clone, PartialEq, Getters)]
326pub struct DateArg {
327    str: String,
328}
329
330impl ToString for DateArg {
331    fn to_string(&self) -> String {
332        self.str.clone()
333    }
334}
335
336impl FromStr for DateArg {
337    type Err = ArgError;
338
339    fn from_str(s: &str) -> Result<Self, Self::Err> {
340        Ok(DateArg { str: s.to_string() })
341    }
342}
343
344impl StmtArg for DateArg {
345    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
346        let str = parse_string(parser)?;
347
348        if str.chars().count() == 10 {
349            if let Some(_) = &str[0..4].find(|c: char| !c.is_ascii_digit()) {
350                Err(YangError::ArgumentParseError("date-arg"))
351            } else if str.chars().nth(4).unwrap() != '-' {
352                Err(YangError::ArgumentParseError("date-arg"))
353            } else if let Some(_) = &str[5..7].find(|c: char| !c.is_ascii_digit()) {
354                Err(YangError::ArgumentParseError("date-arg"))
355            } else if str.chars().nth(7).unwrap() != '-' {
356                Err(YangError::ArgumentParseError("date-arg"))
357            } else if let Some(_) = &str[8..10].find(|c: char| !c.is_ascii_digit()) {
358                Err(YangError::ArgumentParseError("date-arg"))
359            } else {
360                Ok(DateArg { str })
361            }
362        } else {
363            Err(YangError::ArgumentParseError("date-arg"))
364        }
365    }
366}
367
368///
369/// "yin-element-arg".
370///
371#[derive(Debug, Clone, PartialEq, Getters)]
372pub struct YinElementArg {
373    arg: bool,
374}
375
376impl FromStr for YinElementArg {
377    type Err = ArgError;
378
379    fn from_str(s: &str) -> Result<Self, Self::Err> {
380        if s == "true" {
381            Ok(YinElementArg { arg: true })
382        } else if s == "false" {
383            Ok(YinElementArg { arg: false })
384        } else {
385            Err(ArgError::new("yin-element-arg"))
386        }
387    }
388}
389
390impl StmtArg for YinElementArg {
391    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
392        let str = parse_string(parser)?;
393
394        YinElementArg::from_str(&str).map_err(|_| YangError::ArgumentParseError("yin-element-arg"))
395    }
396}
397
398///
399/// "fraction-digits-arg".
400///
401#[derive(Debug, Clone, PartialEq, Getters)]
402pub struct FractionDigitsArg {
403    digits: u8,
404}
405
406impl ToString for FractionDigitsArg {
407    fn to_string(&self) -> String {
408        format!("{}", self.digits())
409    }
410}
411
412impl StmtArg for FractionDigitsArg {
413    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
414        let str = parse_string(parser)?;
415        match str.parse::<u8>() {
416            Ok(num) if num >= 1 && num <= 18 => Ok(FractionDigitsArg { digits: num }),
417            _ => Err(YangError::ArgumentParseError("fraction-digits-arg")),
418        }
419    }
420}
421
422#[derive(Debug, Copy, Clone, PartialEq)]
423pub enum Status {
424    Current,
425    Obsolete,
426    Deprecated,
427}
428
429///
430/// "status-arg".
431///
432#[derive(Debug, Clone, PartialEq, Getters)]
433pub struct StatusArg {
434    arg: Status,
435}
436
437impl StmtArg for StatusArg {
438    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
439        let str = parse_string(parser)?;
440        if str == "current" {
441            Ok(StatusArg {
442                arg: Status::Current,
443            })
444        } else if str == "obsolete" {
445            Ok(StatusArg {
446                arg: Status::Obsolete,
447            })
448        } else if str == "deprecated" {
449            Ok(StatusArg {
450                arg: Status::Deprecated,
451            })
452        } else {
453            Err(YangError::ArgumentParseError("status-arg"))
454        }
455    }
456}
457
458///
459/// "config-arg".
460///
461#[derive(Debug, Clone, PartialEq, Getters)]
462pub struct ConfigArg {
463    arg: bool,
464}
465
466impl StmtArg for ConfigArg {
467    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
468        let str = parse_string(parser)?;
469        if str == "true" {
470            Ok(ConfigArg { arg: true })
471        } else if str == "false" {
472            Ok(ConfigArg { arg: false })
473        } else {
474            Err(YangError::ArgumentParseError("config-arg"))
475        }
476    }
477}
478
479///
480/// "mandatory-arg".
481///
482#[derive(Debug, Clone, PartialEq, Getters)]
483pub struct MandatoryArg {
484    arg: bool,
485}
486
487impl StmtArg for MandatoryArg {
488    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
489        let str = parse_string(parser)?;
490        if str == "true" {
491            Ok(MandatoryArg { arg: true })
492        } else if str == "false" {
493            Ok(MandatoryArg { arg: false })
494        } else {
495            Err(YangError::ArgumentParseError("mandatory-arg"))
496        }
497    }
498}
499
500#[derive(Debug, Copy, Clone, PartialEq)]
501pub enum OrderedBy {
502    User,
503    System,
504}
505
506///
507/// "order-by-arg".
508///
509#[derive(Debug, Clone, PartialEq, Getters)]
510pub struct OrderedByArg {
511    arg: OrderedBy,
512}
513
514impl StmtArg for OrderedByArg {
515    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
516        let str = parse_string(parser)?;
517        if str == "user" {
518            Ok(OrderedByArg {
519                arg: OrderedBy::User,
520            })
521        } else if str == "system" {
522            Ok(OrderedByArg {
523                arg: OrderedBy::System,
524            })
525        } else {
526            Err(YangError::ArgumentParseError("ordered-by-arg"))
527        }
528    }
529}
530
531///
532/// "min-value-arg".
533///
534#[derive(Debug, Clone, PartialEq, Getters)]
535pub struct MinValueArg {
536    val: u64,
537}
538
539impl StmtArg for MinValueArg {
540    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
541        let str = parse_string(parser)?;
542        if is_non_negative_integer_value(&str) {
543            match str.parse::<u64>() {
544                Ok(num) => Ok(MinValueArg { val: num }),
545                Err(_) => Err(YangError::ArgumentParseError("min-value-arg")),
546            }
547        } else {
548            Err(YangError::ArgumentParseError("min-value-arg"))
549        }
550    }
551}
552
553#[derive(Clone, PartialEq)]
554pub enum MaxValue {
555    Unbounded,
556    Value(u64),
557}
558
559impl fmt::Debug for MaxValue {
560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561        match &self {
562            MaxValue::Unbounded => write!(f, "unbounded"),
563            MaxValue::Value(num) => write!(f, "{}", num),
564        }
565    }
566}
567
568///
569/// "max-value-arg".
570///
571#[derive(Debug, Clone, PartialEq, Getters)]
572pub struct MaxValueArg {
573    val: MaxValue,
574}
575
576impl StmtArg for MaxValueArg {
577    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
578        let str = parse_string(parser)?;
579
580        if str == "unbounded" {
581            Ok(MaxValueArg {
582                val: MaxValue::Unbounded,
583            })
584        } else if is_positive_integer_value(&str) {
585            match str.parse::<u64>() {
586                Ok(num) => Ok(MaxValueArg {
587                    val: MaxValue::Value(num),
588                }),
589                Err(_) => Err(YangError::ArgumentParseError("max-value-arg")),
590            }
591        } else {
592            Err(YangError::ArgumentParseError("max-value-arg"))
593        }
594    }
595}
596
597///
598/// "integer-value".
599///
600#[derive(Debug, Clone, PartialEq, Getters)]
601pub struct IntegerValue {
602    val: i64,
603}
604
605impl StmtArg for IntegerValue {
606    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
607        let str = parse_string(parser)?;
608        if is_integer_value(&str) {
609            match str.parse::<i64>() {
610                Ok(num) => Ok(IntegerValue { val: num }),
611                Err(_) => Err(YangError::ArgumentParseError("integer-value")),
612            }
613        } else {
614            Err(YangError::ArgumentParseError("integer-value"))
615        }
616    }
617}
618
619#[derive(Debug, Copy, Clone, PartialEq)]
620pub enum RangeBoundary {
621    Min,
622    Max,
623    Integer(i64),
624    Decimal(f64),
625}
626
627impl FromStr for RangeBoundary {
628    type Err = ArgError;
629
630    fn from_str(s: &str) -> Result<Self, Self::Err> {
631        let rb = s.trim();
632
633        if rb == "min" {
634            Ok(RangeBoundary::Min)
635        } else if rb == "max" {
636            Ok(RangeBoundary::Max)
637        } else if is_decimal_value(rb) {
638            match rb.parse::<f64>() {
639                Ok(num) => Ok(RangeBoundary::Decimal(num)),
640                Err(_) => Err(ArgError::new("range-arg")),
641            }
642        } else if is_integer_value(rb) {
643            match rb.parse::<i64>() {
644                Ok(num) => Ok(RangeBoundary::Integer(num)),
645                Err(_) => Err(ArgError::new("range-arg")),
646            }
647        } else {
648            Err(ArgError::new("range-arg"))
649        }
650    }
651}
652
653pub type RangePart = (RangeBoundary, Option<RangeBoundary>);
654
655///
656/// "range-arg".
657///
658#[derive(Debug, Clone, PartialEq, Getters)]
659pub struct RangeArg {
660    parts: Vec<RangePart>,
661}
662
663impl StmtArg for RangeArg {
664    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
665        let str = parse_string(parser)?;
666        let parts: Vec<_> = str.split('|').collect();
667        let mut v = Vec::new();
668
669        for p in parts {
670            let lower;
671            let upper;
672
673            let bounds: Vec<_> = p.split("..").collect();
674            if bounds.len() == 1 {
675                if bounds[0] == "" {
676                    return Err(YangError::ArgumentParseError("range-arg"));
677                }
678
679                lower = RangeBoundary::from_str(bounds[0])
680                    .map_err(|e| YangError::ArgumentParseError(e.str))?;
681                upper = None;
682            } else if bounds.len() == 2 {
683                if bounds[0] == "" || bounds[1] == "" {
684                    return Err(YangError::ArgumentParseError("range-arg"));
685                }
686                lower = RangeBoundary::from_str(bounds[0])
687                    .map_err(|e| YangError::ArgumentParseError(e.str))?;
688                upper = Some(
689                    RangeBoundary::from_str(bounds[1])
690                        .map_err(|e| YangError::ArgumentParseError(e.str))?,
691                );
692            } else {
693                return Err(YangError::ArgumentParseError("range-arg"));
694            }
695
696            v.push((lower, upper));
697        }
698
699        Ok(RangeArg { parts: v })
700    }
701}
702
703#[derive(Debug, Copy, Clone, PartialEq)]
704pub enum LengthBoundary {
705    Min,
706    Max,
707    Integer(u64),
708}
709
710impl FromStr for LengthBoundary {
711    type Err = ArgError;
712
713    fn from_str(s: &str) -> Result<Self, Self::Err> {
714        let lb = s.trim();
715
716        if lb == "min" {
717            Ok(LengthBoundary::Min)
718        } else if lb == "max" {
719            Ok(LengthBoundary::Max)
720        } else if is_integer_value(lb) {
721            match lb.parse::<u64>() {
722                Ok(num) => Ok(LengthBoundary::Integer(num)),
723                Err(_) => Err(ArgError::new("length-arg")),
724            }
725        } else {
726            Err(ArgError::new("length-arg"))
727        }
728    }
729}
730
731pub type LengthPart = (LengthBoundary, Option<LengthBoundary>);
732
733///
734/// "length-arg".
735///
736#[derive(Debug, Clone, PartialEq, Getters)]
737pub struct LengthArg {
738    parts: Vec<LengthPart>,
739}
740
741impl StmtArg for LengthArg {
742    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
743        let str = parse_string(parser)?;
744        let parts: Vec<_> = str.split('|').collect();
745        let mut v = Vec::new();
746
747        for p in parts {
748            let lower;
749            let upper;
750
751            let bounds: Vec<_> = p.split("..").collect();
752            if bounds.len() == 1 {
753                if bounds[0] == "" {
754                    return Err(YangError::ArgumentParseError("length-arg"));
755                }
756
757                lower = LengthBoundary::from_str(bounds[0])
758                    .map_err(|e| YangError::ArgumentParseError(e.str))?;
759                upper = None;
760            } else if bounds.len() == 2 {
761                if bounds[0] == "" || bounds[1] == "" {
762                    return Err(YangError::ArgumentParseError("length-arg"));
763                }
764                lower = LengthBoundary::from_str(bounds[0])
765                    .map_err(|e| YangError::ArgumentParseError(e.str))?;
766                upper = Some(
767                    LengthBoundary::from_str(bounds[1])
768                        .map_err(|e| YangError::ArgumentParseError(e.str))?,
769                );
770            } else {
771                return Err(YangError::ArgumentParseError("length-arg"));
772            }
773
774            v.push((lower, upper));
775        }
776
777        Ok(LengthArg { parts: v })
778    }
779}
780
781///
782/// "modifier-arg".
783///
784#[derive(Debug, Clone, PartialEq, Getters)]
785pub struct ModifierArg {}
786
787impl StmtArg for ModifierArg {
788    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
789        let str = parse_string(parser)?;
790        if str == "invert-match" {
791            Ok(ModifierArg {})
792        } else {
793            Err(YangError::ArgumentParseError("modifier-arg"))
794        }
795    }
796}
797
798///
799/// "position-value-arg".
800///
801#[derive(Debug, Clone, PartialEq, Getters)]
802pub struct PositionValueArg {
803    val: u64,
804}
805
806impl StmtArg for PositionValueArg {
807    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
808        let str = parse_string(parser)?;
809        if is_non_negative_integer_value(&str) {
810            match str.parse::<u64>() {
811                Ok(num) => Ok(PositionValueArg { val: num }),
812                Err(_) => Err(YangError::ArgumentParseError("position-value-arg")),
813            }
814        } else {
815            Err(YangError::ArgumentParseError("position-value-arg"))
816        }
817    }
818}
819
820///
821/// "path-arg".
822///
823#[derive(Debug, Clone, PartialEq)]
824pub enum PathArg {
825    AbsolutePath(AbsolutePath),
826    RelativePath(RelativePath),
827}
828
829impl StmtArg for PathArg {
830    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
831        let str = parse_string(parser)?;
832
833        if str.starts_with('/') {
834            Ok(PathArg::AbsolutePath(
835                AbsolutePath::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))?,
836            ))
837        } else if str.starts_with("..") {
838            Ok(PathArg::RelativePath(
839                RelativePath::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))?,
840            ))
841        } else {
842            Err(YangError::ArgumentParseError("path-arg"))
843        }
844    }
845}
846
847/// "absolute-path".
848#[derive(Debug, Clone, PartialEq, Getters)]
849pub struct AbsolutePath {
850    nodes: Vec<PathNode>,
851}
852
853impl FromStr for AbsolutePath {
854    type Err = ArgError;
855
856    fn from_str(s: &str) -> Result<Self, Self::Err> {
857        let mut s = &s[..];
858        let mut nodes = Vec::new();
859
860        while s.len() > 0 {
861            if !s.starts_with('/') {
862                return Err(ArgError::new("absolute-path"));
863            }
864            s = &s[1..];
865
866            let node_identifier;
867            let mut path_predicate = Vec::new();
868
869            match s.find(|c: char| c == '[' || c == '/') {
870                Some(pos) => {
871                    node_identifier = NodeIdentifier::from_str(&s[..pos])?;
872                    s = &s[pos..];
873
874                    if s.starts_with('[') {
875                        // do while.
876                        while {
877                            let pos = match s.find(']') {
878                                Some(p) => Ok(p + 1),
879                                None => Err(ArgError::new("absolute-path")),
880                            }?;
881
882                            path_predicate.push(PathPredicate::from_str(&s[..pos])?);
883                            s = &s[pos..];
884
885                            s.len() > 0 && s.starts_with('[')
886                        } {}
887                    }
888                }
889                None => {
890                    node_identifier = NodeIdentifier::from_str(&s)?;
891                    nodes.push(PathNode {
892                        node_identifier,
893                        path_predicate,
894                    });
895                    break;
896                }
897            }
898
899            nodes.push(PathNode {
900                node_identifier,
901                path_predicate,
902            });
903        }
904
905        Ok(AbsolutePath { nodes })
906    }
907}
908
909#[derive(Debug, Clone, PartialEq, Getters)]
910pub struct PathNode {
911    node_identifier: NodeIdentifier,
912    path_predicate: Vec<PathPredicate>,
913}
914
915/// "relative-path".
916#[derive(Debug, Clone, PartialEq, Getters)]
917pub struct RelativePath {
918    up: u32,
919    descendant_path: DescendantPath,
920}
921
922impl FromStr for RelativePath {
923    type Err = ArgError;
924
925    fn from_str(s: &str) -> Result<Self, Self::Err> {
926        let mut s = &s[..];
927        let mut up = 0;
928
929        if !s.starts_with("../") {
930            return Err(ArgError::new("relative-path"));
931        }
932
933        while {
934            up += 1;
935            s = &s[3..];
936            s.len() > 0 && s.starts_with("../")
937        } {}
938
939        let descendant_path = DescendantPath::from_str(s)?;
940        Ok(RelativePath {
941            up,
942            descendant_path,
943        })
944    }
945}
946
947/// "descendant-path".
948#[derive(Debug, Clone, PartialEq, Getters)]
949pub struct DescendantPath {
950    node_identifier: NodeIdentifier,
951    path_predicate: Vec<PathPredicate>,
952    absolute_path: Option<AbsolutePath>,
953}
954
955impl FromStr for DescendantPath {
956    type Err = ArgError;
957
958    fn from_str(s: &str) -> Result<Self, Self::Err> {
959        let mut s = &s[..];
960        let node_identifier;
961        let mut path_predicate = Vec::new();
962        let mut absolute_path = None;
963
964        if s.len() == 0 {
965            return Err(ArgError::new("descendant-path"));
966        }
967
968        match s.find(|c: char| c == '[' || c == '/') {
969            Some(pos) => {
970                node_identifier = NodeIdentifier::from_str(&s[..pos])?;
971                s = &s[pos..];
972
973                if s.starts_with('[') {
974                    // do while.
975                    while {
976                        let pos = match s.find(']') {
977                            Some(p) => Ok(p + 1),
978                            None => Err(ArgError::new("descendant-path")),
979                        }?;
980
981                        path_predicate.push(PathPredicate::from_str(&s[..pos])?);
982                        s = &s[pos..];
983
984                        s.len() > 0 && s.starts_with('[')
985                    } {}
986                }
987
988                if s.len() > 0 {
989                    absolute_path = Some(AbsolutePath::from_str(s)?);
990                }
991            }
992            None => {
993                node_identifier = NodeIdentifier::from_str(s)?;
994            }
995        }
996
997        Ok(DescendantPath {
998            node_identifier,
999            path_predicate,
1000            absolute_path,
1001        })
1002    }
1003}
1004
1005/// "path-predicate".
1006#[derive(Debug, Clone, PartialEq, Getters)]
1007pub struct PathPredicate {
1008    path_equality_expr: PathEqualityExpr,
1009}
1010
1011impl FromStr for PathPredicate {
1012    type Err = ArgError;
1013
1014    fn from_str(s: &str) -> Result<Self, Self::Err> {
1015        if !s.starts_with('[') || !s.ends_with(']') {
1016            Err(ArgError::new("path-predicate"))
1017        } else {
1018            Ok(PathPredicate {
1019                path_equality_expr: PathEqualityExpr::from_str(&s[1..s.len() - 1])?,
1020            })
1021        }
1022    }
1023}
1024
1025/// "path-equality-expr".
1026#[derive(Debug, Clone, PartialEq, Getters)]
1027pub struct PathEqualityExpr {
1028    node_identifier: NodeIdentifier,
1029    path_key_expr: PathKeyExpr,
1030}
1031
1032impl FromStr for PathEqualityExpr {
1033    type Err = ArgError;
1034
1035    fn from_str(s: &str) -> Result<Self, Self::Err> {
1036        match s.find('=') {
1037            Some(p) => Ok(PathEqualityExpr {
1038                node_identifier: NodeIdentifier::from_str(&s[0..p].trim())?,
1039                path_key_expr: PathKeyExpr::from_str(&s[p + 1..].trim())?,
1040            }),
1041            None => Err(ArgError::new("path-equality-expr")),
1042        }
1043    }
1044}
1045
1046/// "path-key-expr".
1047///
1048/// path-key-expr       = current-function-invocation *WSP "/" *WSP
1049///                       rel-path-keyexpr
1050///
1051/// rel-path-keyexpr    = 1*(".." *WSP "/" *WSP)
1052///                       *(node-identifier *WSP "/" *WSP)
1053///                       node-identifier
1054///
1055#[derive(Debug, Clone, PartialEq, Getters)]
1056pub struct PathKeyExpr {
1057    rel_path_keyexpr: String,
1058}
1059
1060impl FromStr for PathKeyExpr {
1061    type Err = ArgError;
1062
1063    fn from_str(str: &str) -> Result<Self, Self::Err> {
1064        // TBD: Validation only.
1065        let paths: Vec<_> = str.split("/").map(|s| s.trim()).collect();
1066        // Minimum of "current() / .. / node-identifier".
1067        if paths.len() < 3 {
1068            return Err(ArgError::new("path-key-expr"));
1069        // Invalid current function invocation.
1070        } else if !is_current_function_invocation(&paths[0]) {
1071            return Err(ArgError::new("path-key-expr"));
1072        // Validate rel-path-keyexpr.
1073        } else {
1074            let mut i = 1;
1075
1076            if paths[i] != ".." {
1077                Err(ArgError::new("path-key-expr"))
1078            } else {
1079                i += 1;
1080                while i < paths.len() && paths[i] == ".." {
1081                    i += 1;
1082                }
1083                if i >= paths.len() {
1084                    return Err(ArgError::new("path-key-expr"));
1085                }
1086
1087                if !is_node_identifier(paths[i]) {
1088                    return Err(ArgError::new("path-key-expr"));
1089                }
1090
1091                while i < paths.len() {
1092                    if !is_node_identifier(paths[i]) {
1093                        return Err(ArgError::new("path-key-expr"));
1094                    }
1095                    i += 1;
1096                }
1097
1098                Ok(PathKeyExpr {
1099                    rel_path_keyexpr: str.to_string(),
1100                })
1101            }
1102        }
1103    }
1104}
1105
1106///
1107/// Tokenizer for "if-feature".
1108///
1109pub enum IfFeatureToken {
1110    Init,
1111    ParenBegin,
1112    ParenEnd,
1113    Not,
1114    And,
1115    Or,
1116    IdentifierRef(String),
1117    EndOfLine,
1118}
1119
1120pub struct Tokenizer {
1121    str: String,
1122    pos: usize,
1123}
1124
1125impl Tokenizer {
1126    pub fn new(s: String) -> Tokenizer {
1127        Tokenizer { str: s, pos: 0 }
1128    }
1129
1130    pub fn line(&mut self) -> &str {
1131        &self.str[self.pos..]
1132    }
1133
1134    pub fn get_token(&mut self) -> IfFeatureToken {
1135        if let Some(p) = self.line().find(|c: char| !c.is_whitespace()) {
1136            self.pos += p;
1137        }
1138
1139        if self.line().len() == 0 {
1140            IfFeatureToken::EndOfLine
1141        } else if self.line().starts_with('(') {
1142            self.pos += 1;
1143            IfFeatureToken::ParenBegin
1144        } else if self.line().starts_with(')') {
1145            self.pos += 1;
1146            IfFeatureToken::ParenEnd
1147        } else if self.line().starts_with("not") {
1148            self.pos += 3;
1149            IfFeatureToken::Not
1150        } else if self.line().starts_with("and") {
1151            self.pos += 3;
1152            IfFeatureToken::And
1153        } else if self.line().starts_with("or") {
1154            self.pos += 2;
1155            IfFeatureToken::Or
1156        } else {
1157            let p = match self.line().find(|c: char| {
1158                !c.is_alphanumeric() && c != '-' && c != '_' && c != '.' && c != ':'
1159            }) {
1160                Some(p) => p,
1161                None => self.str.len() - self.pos,
1162            };
1163            let token = &self.str[self.pos..self.pos + p];
1164
1165            self.pos += p;
1166            IfFeatureToken::IdentifierRef(token.to_string())
1167        }
1168    }
1169}
1170
1171/// "if-feature-expr".
1172#[derive(Clone, PartialEq, Getters)]
1173pub struct IfFeatureExpr {
1174    terms: Vec<IfFeatureTerm>,
1175}
1176
1177impl fmt::Debug for IfFeatureExpr {
1178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1179        write!(f, "{}", self.to_string())
1180    }
1181}
1182
1183impl ToString for IfFeatureExpr {
1184    fn to_string(&self) -> String {
1185        let vec: Vec<_> = self.terms.iter().map(|t| t.to_string()).collect();
1186        format!("{}", vec.join(" or "))
1187    }
1188}
1189
1190impl IfFeatureExpr {
1191    /// Recursively parse "if-feature" arg string.
1192    pub fn parse(tokenizer: &mut Tokenizer) -> Result<Self, ArgError> {
1193        let mut terms: Vec<IfFeatureTerm> = Vec::new();
1194        let mut factors: Vec<IfFeatureFactor> = Vec::new();
1195        let mut not: Option<bool> = None;
1196        let mut prev = IfFeatureToken::Init;
1197
1198        loop {
1199            let mut token = tokenizer.get_token();
1200            match token {
1201                IfFeatureToken::Init => {}
1202                IfFeatureToken::ParenBegin => {
1203                    match prev {
1204                        IfFeatureToken::ParenBegin
1205                        | IfFeatureToken::ParenEnd
1206                        | IfFeatureToken::IdentifierRef(_) => {
1207                            return Err(ArgError::new("if-feature-expr"))
1208                        }
1209                        _ => {}
1210                    }
1211
1212                    let expr = Box::new(IfFeatureExpr::parse(tokenizer)?);
1213                    factors.push(IfFeatureFactor::IfFeatureExpr((not.take(), expr)));
1214
1215                    token = IfFeatureToken::ParenEnd;
1216                }
1217                IfFeatureToken::ParenEnd => {
1218                    match prev {
1219                        IfFeatureToken::ParenBegin
1220                        | IfFeatureToken::Not
1221                        | IfFeatureToken::And
1222                        | IfFeatureToken::Or => return Err(ArgError::new("if-feature-expr")),
1223                        _ => {}
1224                    }
1225
1226                    break;
1227                }
1228                IfFeatureToken::Or => {
1229                    match prev {
1230                        IfFeatureToken::Init
1231                        | IfFeatureToken::ParenBegin
1232                        | IfFeatureToken::Not
1233                        | IfFeatureToken::And
1234                        | IfFeatureToken::Or => return Err(ArgError::new("if-feature-expr")),
1235                        _ => {}
1236                    }
1237
1238                    terms.push(IfFeatureTerm {
1239                        factors: factors.drain(..).collect(),
1240                    });
1241                    factors = Vec::new();
1242                }
1243                IfFeatureToken::And => match prev {
1244                    IfFeatureToken::Init
1245                    | IfFeatureToken::ParenBegin
1246                    | IfFeatureToken::Not
1247                    | IfFeatureToken::And
1248                    | IfFeatureToken::Or => return Err(ArgError::new("if-feature-expr")),
1249                    _ => {}
1250                },
1251                IfFeatureToken::Not => {
1252                    match prev {
1253                        IfFeatureToken::ParenEnd
1254                        | IfFeatureToken::Not
1255                        | IfFeatureToken::IdentifierRef(_) => {
1256                            return Err(ArgError::new("if-feature-expr"))
1257                        }
1258                        _ => {}
1259                    }
1260
1261                    not.replace(true);
1262                }
1263                IfFeatureToken::IdentifierRef(ref str) => {
1264                    match prev {
1265                        IfFeatureToken::ParenEnd | IfFeatureToken::IdentifierRef(_) => {
1266                            return Err(ArgError::new("if-feature-expr"))
1267                        }
1268                        _ => {}
1269                    }
1270
1271                    let identifier_ref = IdentifierRef::from_str(&str)?;
1272                    factors.push(IfFeatureFactor::IdentifierRef((not.take(), identifier_ref)));
1273                }
1274                IfFeatureToken::EndOfLine => break,
1275            }
1276
1277            prev = token;
1278        }
1279
1280        terms.push(IfFeatureTerm {
1281            factors: factors.drain(..).collect(),
1282        });
1283        Ok(IfFeatureExpr { terms })
1284    }
1285}
1286
1287impl StmtArg for IfFeatureExpr {
1288    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1289        let str = parse_string(parser)?;
1290        let mut tokenizer = Tokenizer::new(str);
1291
1292        IfFeatureExpr::parse(&mut tokenizer).map_err(|e| YangError::ArgumentParseError(e.str))
1293    }
1294}
1295
1296/// "if-feature-term".
1297#[derive(Debug, Clone, PartialEq, Getters)]
1298pub struct IfFeatureTerm {
1299    factors: Vec<IfFeatureFactor>,
1300}
1301
1302impl ToString for IfFeatureTerm {
1303    fn to_string(&self) -> String {
1304        let vec: Vec<_> = self.factors.iter().map(|f| f.to_string()).collect();
1305        format!("{}", vec.join(" and "))
1306    }
1307}
1308
1309/// "if-feature-factor".
1310#[derive(Debug, Clone, PartialEq)]
1311pub enum IfFeatureFactor {
1312    IfFeatureExpr((Option<bool>, Box<IfFeatureExpr>)),
1313    IdentifierRef((Option<bool>, IdentifierRef)),
1314}
1315
1316impl ToString for IfFeatureFactor {
1317    fn to_string(&self) -> String {
1318        match self {
1319            IfFeatureFactor::IfFeatureExpr((not, expr)) => {
1320                if let Some(_) = not {
1321                    format!("not ({:?})", expr)
1322                } else {
1323                    format!("({:?})", expr)
1324                }
1325            }
1326            IfFeatureFactor::IdentifierRef((not, identifier_ref)) => {
1327                if let Some(_) = not {
1328                    format!("not {:?}", identifier_ref)
1329                } else {
1330                    format!("{:?}", identifier_ref)
1331                }
1332            }
1333        }
1334    }
1335}
1336
1337///
1338/// "require-instance-arg".
1339///
1340#[derive(Debug, Clone, PartialEq, Getters)]
1341pub struct RequireInstanceArg {
1342    arg: bool,
1343}
1344
1345impl StmtArg for RequireInstanceArg {
1346    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1347        let str = parse_string(parser)?;
1348        if str == "true" {
1349            Ok(RequireInstanceArg { arg: true })
1350        } else if str == "false" {
1351            Ok(RequireInstanceArg { arg: false })
1352        } else {
1353            Err(YangError::ArgumentParseError("require-instance-arg"))
1354        }
1355    }
1356}
1357
1358///
1359/// "key-arg".
1360///
1361#[derive(Debug, Clone, PartialEq, Getters)]
1362pub struct KeyArg {
1363    keys: Vec<NodeIdentifier>,
1364}
1365
1366impl StmtArg for KeyArg {
1367    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1368        let str = parse_string(parser)?;
1369        let mut keys = Vec::new();
1370        let mut s = &str[..];
1371
1372        while {
1373            let pos = match s.find(char::is_whitespace) {
1374                Some(p) => p,
1375                None => s.len(),
1376            };
1377
1378            let node_identifier = NodeIdentifier::from_str(&s[..pos])
1379                .map_err(|e| YangError::ArgumentParseError(e.str))?;
1380            keys.push(node_identifier);
1381
1382            s = &s[pos..].trim();
1383            s.len() > 0
1384        } {}
1385
1386        Ok(KeyArg { keys })
1387    }
1388}
1389
1390///
1391/// "schema-nodeid".
1392///
1393#[derive(Debug, Clone, PartialEq)]
1394pub enum SchemaNodeid {
1395    Absolute(AbsoluteSchemaNodeid),
1396    Descendant(DescendantSchemaNodeid),
1397}
1398
1399impl StmtArg for SchemaNodeid {
1400    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1401        let str = parse_string(parser)?;
1402        if str.starts_with('/') {
1403            Ok(SchemaNodeid::Absolute(
1404                AbsoluteSchemaNodeid::from_str(&str)
1405                    .map_err(|e| YangError::ArgumentParseError(e.str))?,
1406            ))
1407        } else {
1408            Ok(SchemaNodeid::Descendant(
1409                DescendantSchemaNodeid::from_str(&str)
1410                    .map_err(|e| YangError::ArgumentParseError(e.str))?,
1411            ))
1412        }
1413    }
1414}
1415
1416#[derive(Debug, Clone, PartialEq, Getters)]
1417pub struct AbsoluteSchemaNodeid {
1418    nodes: Vec<NodeIdentifier>,
1419}
1420
1421#[derive(Debug, Clone, PartialEq, Getters)]
1422pub struct DescendantSchemaNodeid {
1423    nodes: Vec<NodeIdentifier>,
1424}
1425
1426impl FromStr for AbsoluteSchemaNodeid {
1427    type Err = ArgError;
1428
1429    fn from_str(str: &str) -> Result<Self, Self::Err> {
1430        if let Some(_) = str.find(char::is_whitespace) {
1431            Err(ArgError::new("absolute-schema-nodeid"))
1432        } else if let Some(_) = str.find("//") {
1433            Err(ArgError::new("absolute-schema-nodeid"))
1434        } else if str.starts_with('/') {
1435            let mut nodes: Vec<NodeIdentifier> = Vec::new();
1436            for n in (&str[1..]).split('/') {
1437                nodes.push(NodeIdentifier::from_str(n)?);
1438            }
1439            Ok(AbsoluteSchemaNodeid { nodes })
1440        } else {
1441            Err(ArgError::new("absolute-schema-nodeid"))
1442        }
1443    }
1444}
1445
1446impl FromStr for DescendantSchemaNodeid {
1447    type Err = ArgError;
1448
1449    fn from_str(str: &str) -> Result<Self, Self::Err> {
1450        if let Some(_) = str.find(char::is_whitespace) {
1451            Err(ArgError::new("descendant-schema-nodeid"))
1452        } else if let Some(_) = str.find("//") {
1453            Err(ArgError::new("descendant-schema-nodeid"))
1454        } else if !str.starts_with('/') {
1455            let mut nodes: Vec<NodeIdentifier> = Vec::new();
1456            for n in str.split('/') {
1457                nodes.push(NodeIdentifier::from_str(n)?);
1458            }
1459            Ok(DescendantSchemaNodeid { nodes })
1460        } else {
1461            Err(ArgError::new("descendant-schema-nodeid"))
1462        }
1463    }
1464}
1465
1466impl StmtArg for AbsoluteSchemaNodeid {
1467    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1468        let str = parse_string(parser)?;
1469
1470        AbsoluteSchemaNodeid::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))
1471    }
1472}
1473
1474impl StmtArg for DescendantSchemaNodeid {
1475    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1476        let str = parse_string(parser)?;
1477
1478        DescendantSchemaNodeid::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))
1479    }
1480}
1481
1482impl ToString for AbsoluteSchemaNodeid {
1483    fn to_string(&self) -> String {
1484        format!(
1485            "/{}",
1486            self.nodes
1487                .iter()
1488                .map(|n| n.to_string())
1489                .collect::<Vec<String>>()
1490                .join("/")
1491        )
1492    }
1493}
1494
1495impl ToString for DescendantSchemaNodeid {
1496    fn to_string(&self) -> String {
1497        self.nodes
1498            .iter()
1499            .map(|n| n.to_string())
1500            .collect::<Vec<String>>()
1501            .join("/")
1502    }
1503}
1504
1505///
1506/// "unique-arg".
1507///
1508#[derive(Debug, Clone, PartialEq, Getters)]
1509pub struct UniqueArg {
1510    nodeids: Vec<DescendantSchemaNodeid>,
1511}
1512
1513impl StmtArg for UniqueArg {
1514    fn parse_arg(parser: &mut Parser) -> Result<Self, YangError> {
1515        let str = parse_string(parser)?;
1516        UniqueArg::from_str(&str).map_err(|e| YangError::ArgumentParseError(e.str))
1517    }
1518}
1519
1520impl FromStr for UniqueArg {
1521    type Err = ArgError;
1522
1523    fn from_str(str: &str) -> Result<Self, Self::Err> {
1524        let mut nodeids = Vec::new();
1525
1526        for n in str.split_whitespace() {
1527            nodeids.push(DescendantSchemaNodeid::from_str(n)?);
1528        }
1529
1530        Ok(UniqueArg { nodeids })
1531    }
1532}
1533
1534/// "refine-arg".
1535pub type RefineArg = DescendantSchemaNodeid;
1536
1537/// "uses-augment-arg".
1538pub type UsesAugmentArg = DescendantSchemaNodeid;
1539
1540/// "augment-arg".
1541pub type AugmentArg = AbsoluteSchemaNodeid;
1542
1543/// "deviation-arg".
1544pub type DeviationArg = AbsoluteSchemaNodeid;
1545
1546#[cfg(test)]
1547mod tests {
1548    use super::*;
1549
1550    #[test]
1551    pub fn test_identifier() {
1552        let s = " hello-world ";
1553        let mut parser = Parser::new(s.to_string());
1554
1555        match Identifier::parse_arg(&mut parser) {
1556            Ok(arg) => assert_eq!(
1557                arg,
1558                Identifier {
1559                    str: String::from("hello-world")
1560                }
1561            ),
1562            Err(err) => panic!("{:?}", err.to_string()),
1563        }
1564
1565        let s = " _123.IdEnT.456-789_ ";
1566        let mut parser = Parser::new(s.to_string());
1567
1568        match Identifier::parse_arg(&mut parser) {
1569            Ok(arg) => assert_eq!(
1570                arg,
1571                Identifier {
1572                    str: String::from("_123.IdEnT.456-789_")
1573                }
1574            ),
1575            Err(err) => panic!("{:?}", err.to_string()),
1576        }
1577
1578        let s = " 123 ";
1579        let mut parser = Parser::new(s.to_string());
1580
1581        match Identifier::parse_arg(&mut parser) {
1582            Ok(_) => assert!(false),
1583            Err(err) => assert_eq!(err.to_string(), "Argument parse error identifier"),
1584        }
1585
1586        let s = " 123$ ";
1587        let mut parser = Parser::new(s.to_string());
1588
1589        match Identifier::parse_arg(&mut parser) {
1590            Ok(_) => assert!(false),
1591            Err(err) => assert_eq!(err.to_string(), "Argument parse error identifier"),
1592        }
1593    }
1594
1595    #[test]
1596    pub fn test_identifier_ref() {
1597        let s = " prefix:hello-world ";
1598        let mut parser = Parser::new(s.to_string());
1599
1600        match IdentifierRef::parse_arg(&mut parser) {
1601            Ok(arg) => assert_eq!(arg.to_string(), "prefix:hello-world"),
1602            Err(err) => panic!("{:?}", err.to_string()),
1603        }
1604
1605        let s = " _prefix_:_123.IdEnT.456-789_ ";
1606        let mut parser = Parser::new(s.to_string());
1607
1608        match IdentifierRef::parse_arg(&mut parser) {
1609            Ok(arg) => assert_eq!(arg.to_string(), "_prefix_:_123.IdEnT.456-789_"),
1610            Err(err) => panic!("{:?}", err.to_string()),
1611        }
1612
1613        let s = " 123:456 ";
1614        let mut parser = Parser::new(s.to_string());
1615
1616        match IdentifierRef::parse_arg(&mut parser) {
1617            Ok(_) => assert!(false),
1618            Err(err) => assert_eq!(err.to_string(), "Argument parse error identifier"),
1619        }
1620
1621        let s = " _123:_456 ";
1622        let mut parser = Parser::new(s.to_string());
1623
1624        match IdentifierRef::parse_arg(&mut parser) {
1625            Ok(arg) => assert_eq!(arg.to_string(), "_123:_456"),
1626            Err(err) => panic!("{:?}", err.to_string()),
1627        }
1628
1629        let s = " _123: ";
1630        let mut parser = Parser::new(s.to_string());
1631
1632        match IdentifierRef::parse_arg(&mut parser) {
1633            Ok(_) => assert!(false),
1634            Err(err) => assert_eq!(err.to_string(), "Argument parse error identifier"),
1635        }
1636    }
1637
1638    #[test]
1639    pub fn test_date_arg() {
1640        let s = " 2021-08-01 ";
1641        let mut parser = Parser::new(s.to_string());
1642
1643        match DateArg::parse_arg(&mut parser) {
1644            Ok(arg) => assert_eq!(arg.to_string(), "2021-08-01"),
1645            Err(err) => panic!("{:?}", err.to_string()),
1646        }
1647
1648        let s = " 2021-8-1 ";
1649        let mut parser = Parser::new(s.to_string());
1650
1651        match DateArg::parse_arg(&mut parser) {
1652            Ok(_) => assert!(false),
1653            Err(err) => assert_eq!(err.to_string(), "Argument parse error date-arg"),
1654        }
1655
1656        let s = " 08-01-2021 ";
1657        let mut parser = Parser::new(s.to_string());
1658
1659        match DateArg::parse_arg(&mut parser) {
1660            Ok(_) => assert!(false),
1661            Err(err) => assert_eq!(err.to_string(), "Argument parse error date-arg"),
1662        }
1663
1664        let s = " 2021-08-0x ";
1665        let mut parser = Parser::new(s.to_string());
1666
1667        match DateArg::parse_arg(&mut parser) {
1668            Ok(_) => assert!(false),
1669            Err(err) => assert_eq!(err.to_string(), "Argument parse error date-arg"),
1670        }
1671    }
1672
1673    #[test]
1674    pub fn test_fraction_digits_arg() {
1675        let s = "18";
1676        let mut parser = Parser::new(s.to_string());
1677
1678        match FractionDigitsArg::parse_arg(&mut parser) {
1679            Ok(arg) => assert_eq!(arg.digits(), &18),
1680            Err(err) => panic!("{:?}", err.to_string()),
1681        }
1682
1683        let s = "0";
1684        let mut parser = Parser::new(s.to_string());
1685
1686        match FractionDigitsArg::parse_arg(&mut parser) {
1687            Ok(_) => assert!(false),
1688            Err(err) => assert_eq!(err.to_string(), "Argument parse error fraction-digits-arg"),
1689        }
1690
1691        let s = "19";
1692        let mut parser = Parser::new(s.to_string());
1693
1694        match FractionDigitsArg::parse_arg(&mut parser) {
1695            Ok(_) => assert!(false),
1696            Err(err) => assert_eq!(err.to_string(), "Argument parse error fraction-digits-arg"),
1697        }
1698    }
1699
1700    #[test]
1701    pub fn test_range_arg() {
1702        let s = r#""1..10""#;
1703        let mut parser = Parser::new(s.to_string());
1704
1705        match RangeArg::parse_arg(&mut parser) {
1706            Ok(arg) => assert_eq!(
1707                arg,
1708                RangeArg {
1709                    parts: vec![(RangeBoundary::Integer(1), Some(RangeBoundary::Integer(10)))]
1710                }
1711            ),
1712            Err(err) => panic!("{:?}", err.to_string()),
1713        }
1714
1715        let s = r#""1 .. 10 | 21..30""#;
1716        let mut parser = Parser::new(s.to_string());
1717
1718        match RangeArg::parse_arg(&mut parser) {
1719            Ok(arg) => assert_eq!(
1720                arg,
1721                RangeArg {
1722                    parts: vec![
1723                        (RangeBoundary::Integer(1), Some(RangeBoundary::Integer(10))),
1724                        (RangeBoundary::Integer(21), Some(RangeBoundary::Integer(30))),
1725                    ]
1726                }
1727            ),
1728            Err(err) => panic!("{:?}", err.to_string()),
1729        }
1730
1731        let s = r#""min..max""#;
1732        let mut parser = Parser::new(s.to_string());
1733
1734        match RangeArg::parse_arg(&mut parser) {
1735            Ok(arg) => assert_eq!(
1736                arg,
1737                RangeArg {
1738                    parts: vec![(RangeBoundary::Min, Some(RangeBoundary::Max)),]
1739                }
1740            ),
1741            Err(err) => panic!("{:?}", err.to_string()),
1742        }
1743
1744        let s = r#""min..""#;
1745        let mut parser = Parser::new(s.to_string());
1746
1747        match RangeArg::parse_arg(&mut parser) {
1748            Ok(_) => assert!(false),
1749            Err(err) => assert_eq!(err.to_string(), "Argument parse error range-arg"),
1750        }
1751
1752        let s = r#""1.01 .. 1.99""#;
1753        let mut parser = Parser::new(s.to_string());
1754
1755        match RangeArg::parse_arg(&mut parser) {
1756            Ok(arg) => assert_eq!(
1757                arg,
1758                RangeArg {
1759                    parts: vec![(
1760                        RangeBoundary::Decimal(1.01),
1761                        Some(RangeBoundary::Decimal(1.99))
1762                    )]
1763                }
1764            ),
1765            Err(err) => panic!("{:?}", err.to_string()),
1766        }
1767    }
1768
1769    #[test]
1770    pub fn test_length_arg() {
1771        let s = r#""1..10""#;
1772        let mut parser = Parser::new(s.to_string());
1773
1774        match LengthArg::parse_arg(&mut parser) {
1775            Ok(arg) => assert_eq!(
1776                arg,
1777                LengthArg {
1778                    parts: vec![(
1779                        LengthBoundary::Integer(1),
1780                        Some(LengthBoundary::Integer(10))
1781                    )]
1782                }
1783            ),
1784            Err(err) => panic!("{:?}", err.to_string()),
1785        }
1786
1787        let s = r#""1 .. 10 | 21..30""#;
1788        let mut parser = Parser::new(s.to_string());
1789
1790        match LengthArg::parse_arg(&mut parser) {
1791            Ok(arg) => assert_eq!(
1792                arg,
1793                LengthArg {
1794                    parts: vec![
1795                        (
1796                            LengthBoundary::Integer(1),
1797                            Some(LengthBoundary::Integer(10))
1798                        ),
1799                        (
1800                            LengthBoundary::Integer(21),
1801                            Some(LengthBoundary::Integer(30))
1802                        ),
1803                    ]
1804                }
1805            ),
1806            Err(err) => panic!("{:?}", err.to_string()),
1807        }
1808
1809        let s = r#""min..max""#;
1810        let mut parser = Parser::new(s.to_string());
1811
1812        match LengthArg::parse_arg(&mut parser) {
1813            Ok(arg) => assert_eq!(
1814                arg,
1815                LengthArg {
1816                    parts: vec![(LengthBoundary::Min, Some(LengthBoundary::Max)),]
1817                }
1818            ),
1819            Err(err) => panic!("{:?}", err.to_string()),
1820        }
1821
1822        let s = r#""min..""#;
1823        let mut parser = Parser::new(s.to_string());
1824
1825        match LengthArg::parse_arg(&mut parser) {
1826            Ok(_) => assert!(false),
1827            Err(err) => assert_eq!(err.to_string(), "Argument parse error length-arg"),
1828        }
1829    }
1830
1831    #[test]
1832    pub fn test_path_key_expr() {
1833        let s = "current()/../node";
1834        match PathKeyExpr::from_str(s) {
1835            Ok(arg) => assert_eq!(
1836                arg,
1837                PathKeyExpr {
1838                    rel_path_keyexpr: "current()/../node".to_string()
1839                }
1840            ),
1841            Err(err) => panic!("{:?}", err.to_string()),
1842        }
1843
1844        let s = "current()/../../../node";
1845        match PathKeyExpr::from_str(s) {
1846            Ok(arg) => assert_eq!(
1847                arg,
1848                PathKeyExpr {
1849                    rel_path_keyexpr: "current()/../../../node".to_string()
1850                }
1851            ),
1852            Err(err) => panic!("{:?}", err.to_string()),
1853        }
1854
1855        let s = "current()/../../../node/node/node";
1856        match PathKeyExpr::from_str(s) {
1857            Ok(arg) => assert_eq!(
1858                arg,
1859                PathKeyExpr {
1860                    rel_path_keyexpr: "current()/../../../node/node/node".to_string()
1861                }
1862            ),
1863            Err(err) => panic!("{:?}", err.to_string()),
1864        }
1865
1866        let s = "current ( ) / .. / .. / .. / node / node / node ";
1867        match PathKeyExpr::from_str(s) {
1868            Ok(arg) => assert_eq!(
1869                arg,
1870                PathKeyExpr {
1871                    rel_path_keyexpr: "current ( ) / .. / .. / .. / node / node / node "
1872                        .to_string()
1873                }
1874            ),
1875            Err(err) => panic!("{:?}", err.to_string()),
1876        }
1877
1878        let s = "current()/..";
1879        match PathKeyExpr::from_str(s) {
1880            Ok(_) => assert!(false),
1881            Err(err) => assert_eq!(err.to_string(), "Arg error: path-key-expr"),
1882        }
1883
1884        let s = "current()/node/node/node";
1885        match PathKeyExpr::from_str(s) {
1886            Ok(_) => assert!(false),
1887            Err(err) => assert_eq!(err.to_string(), "Arg error: path-key-expr"),
1888        }
1889    }
1890
1891    #[test]
1892    pub fn test_absolute_path() {
1893        let s = "/node1/node2[id=current()/../rel1/rel2]";
1894        let path = AbsolutePath {
1895            nodes: vec![
1896                PathNode {
1897                    node_identifier: NodeIdentifier::from_str("node1").unwrap(),
1898                    path_predicate: vec![],
1899                },
1900                PathNode {
1901                    node_identifier: NodeIdentifier::from_str("node2").unwrap(),
1902                    path_predicate: vec![PathPredicate {
1903                        path_equality_expr: PathEqualityExpr {
1904                            node_identifier: NodeIdentifier::from_str("id").unwrap(),
1905                            path_key_expr: PathKeyExpr {
1906                                rel_path_keyexpr: "current()/../rel1/rel2".to_string(),
1907                            },
1908                        },
1909                    }],
1910                },
1911            ],
1912        };
1913
1914        match AbsolutePath::from_str(s) {
1915            Ok(p) => assert_eq!(p, path),
1916            Err(err) => panic!("{:?}", err.to_string()),
1917        }
1918
1919        let s =
1920            "/node1/node2[id1=current()/../rel1/rel2][prefix:id2=current()/../../rel3/rel4]/node3";
1921        let path = AbsolutePath {
1922            nodes: vec![
1923                PathNode {
1924                    node_identifier: NodeIdentifier::from_str("node1").unwrap(),
1925                    path_predicate: vec![],
1926                },
1927                PathNode {
1928                    node_identifier: NodeIdentifier::from_str("node2").unwrap(),
1929                    path_predicate: vec![
1930                        PathPredicate {
1931                            path_equality_expr: PathEqualityExpr {
1932                                node_identifier: NodeIdentifier::from_str("id1").unwrap(),
1933                                path_key_expr: PathKeyExpr {
1934                                    rel_path_keyexpr: "current()/../rel1/rel2".to_string(),
1935                                },
1936                            },
1937                        },
1938                        PathPredicate {
1939                            path_equality_expr: PathEqualityExpr {
1940                                node_identifier: NodeIdentifier::from_str("prefix:id2").unwrap(),
1941                                path_key_expr: PathKeyExpr {
1942                                    rel_path_keyexpr: "current()/../../rel3/rel4".to_string(),
1943                                },
1944                            },
1945                        },
1946                    ],
1947                },
1948                PathNode {
1949                    node_identifier: NodeIdentifier::from_str("node3").unwrap(),
1950                    path_predicate: vec![],
1951                },
1952            ],
1953        };
1954
1955        match AbsolutePath::from_str(s) {
1956            Ok(p) => assert_eq!(p, path),
1957            Err(err) => panic!("{:?}", err.to_string()),
1958        }
1959    }
1960
1961    #[test]
1962    pub fn test_descendant_path() {
1963        let s = "node0/node1/node2[id=current()/../rel1/rel2]";
1964
1965        let absolute_path = AbsolutePath {
1966            nodes: vec![
1967                PathNode {
1968                    node_identifier: NodeIdentifier::from_str("node1").unwrap(),
1969                    path_predicate: vec![],
1970                },
1971                PathNode {
1972                    node_identifier: NodeIdentifier::from_str("node2").unwrap(),
1973                    path_predicate: vec![PathPredicate {
1974                        path_equality_expr: PathEqualityExpr {
1975                            node_identifier: NodeIdentifier::from_str("id").unwrap(),
1976                            path_key_expr: PathKeyExpr {
1977                                rel_path_keyexpr: "current()/../rel1/rel2".to_string(),
1978                            },
1979                        },
1980                    }],
1981                },
1982            ],
1983        };
1984        let descendant_path = DescendantPath {
1985            node_identifier: NodeIdentifier::from_str("node0").unwrap(),
1986            path_predicate: vec![],
1987            absolute_path: Some(absolute_path),
1988        };
1989
1990        match DescendantPath::from_str(s) {
1991            Ok(p) => assert_eq!(p, descendant_path),
1992            Err(err) => panic!("{:?}", err.to_string()),
1993        }
1994    }
1995
1996    #[test]
1997    pub fn test_relative_path() {
1998        let s = "../../node0/node1/node2";
1999
2000        let absolute_path = AbsolutePath {
2001            nodes: vec![
2002                PathNode {
2003                    node_identifier: NodeIdentifier::from_str("node1").unwrap(),
2004                    path_predicate: vec![],
2005                },
2006                PathNode {
2007                    node_identifier: NodeIdentifier::from_str("node2").unwrap(),
2008                    path_predicate: vec![],
2009                },
2010            ],
2011        };
2012
2013        let descendant_path = DescendantPath {
2014            node_identifier: NodeIdentifier::from_str("node0").unwrap(),
2015            path_predicate: vec![],
2016            absolute_path: Some(absolute_path),
2017        };
2018
2019        let relative_path = RelativePath {
2020            up: 2u32,
2021            descendant_path,
2022        };
2023
2024        match RelativePath::from_str(s) {
2025            Ok(p) => assert_eq!(p, relative_path),
2026            Err(err) => panic!("{:?}", err.to_string()),
2027        }
2028    }
2029
2030    #[test]
2031    pub fn test_if_feature_expr() {
2032        let s = r#""p1:id1 and p1:id2 or (p2:id3 and p2:id4) or not p3:id5""#;
2033        let mut parser = Parser::new(s.to_string());
2034
2035        match IfFeatureExpr::parse_arg(&mut parser) {
2036            Ok(expr) => assert_eq!(
2037                format!("{:?}", expr),
2038                "p1:id1 and p1:id2 or (p2:id3 and p2:id4) or not p3:id5"
2039            ),
2040            Err(_) => panic!(),
2041        }
2042
2043        let s = r#""p1:id1 p1:id2""#;
2044        let mut parser = Parser::new(s.to_string());
2045
2046        match IfFeatureExpr::parse_arg(&mut parser) {
2047            Ok(expr) => panic!("{:?}", expr),
2048            Err(err) => assert_eq!(err.to_string(), "Argument parse error if-feature-expr"),
2049        }
2050    }
2051
2052    #[test]
2053    pub fn test_key_arg() {
2054        let s = r#""p1:id1 p1:id2 p2:id3 id4 id5""#;
2055        let mut parser = Parser::new(s.to_string());
2056
2057        match KeyArg::parse_arg(&mut parser) {
2058            Ok(arg) => assert_eq!(
2059                arg,
2060                KeyArg {
2061                    keys: vec![
2062                        NodeIdentifier::from_str("p1:id1").unwrap(),
2063                        NodeIdentifier::from_str("p1:id2").unwrap(),
2064                        NodeIdentifier::from_str("p2:id3").unwrap(),
2065                        NodeIdentifier::from_str("id4").unwrap(),
2066                        NodeIdentifier::from_str("id5").unwrap(),
2067                    ]
2068                }
2069            ),
2070            Err(err) => panic!("{}", err.to_string()),
2071        }
2072    }
2073
2074    #[test]
2075    pub fn test_absolute_schema_nodeid() {
2076        let s = r#""/id1/id2/id3""#;
2077        let mut parser = Parser::new(s.to_string());
2078
2079        match AbsoluteSchemaNodeid::parse_arg(&mut parser) {
2080            Ok(arg) => {
2081                assert_eq!(arg.to_string(), "/id1/id2/id3");
2082                assert_eq!(arg.nodes.len(), 3);
2083            }
2084            Err(err) => panic!("{}", err.to_string()),
2085        }
2086    }
2087
2088    #[test]
2089    pub fn test_descendant_schema_nodeid() {
2090        let s = r#""id1/id2/id3""#;
2091        let mut parser = Parser::new(s.to_string());
2092
2093        match DescendantSchemaNodeid::parse_arg(&mut parser) {
2094            Ok(arg) => {
2095                assert_eq!(arg.to_string(), "id1/id2/id3");
2096                assert_eq!(arg.nodes.len(), 3);
2097            }
2098            Err(err) => panic!("{}", err.to_string()),
2099        }
2100    }
2101}