asn1rs_model/model/
int.rs

1use crate::model::lor::Error as ResolveError;
2use crate::model::lor::{ResolveState, Resolver, TryResolve, Unresolved};
3use crate::model::{Asn, Error, LitOrRef, Model, PeekableTokens, Range};
4use crate::parser::Token;
5use std::convert::TryFrom;
6use std::fmt::{Debug, Display};
7use std::iter::Peekable;
8
9#[derive(Default, Debug, Clone, PartialOrd, PartialEq, Eq)]
10pub struct Integer<T: Display + Debug + Clone = i64> {
11    pub range: Range<Option<T>>,
12    pub constants: Vec<(String, i64)>,
13}
14
15impl<T: Display + Debug + Clone> Integer<T> {
16    pub fn with_range(range: Range<Option<T>>) -> Self {
17        Self {
18            range,
19            constants: Vec::default(),
20        }
21    }
22}
23
24impl<T: Iterator<Item = Token>> TryFrom<&mut Peekable<T>>
25    for Integer<<Unresolved as ResolveState>::RangeType>
26{
27    type Error = Error;
28
29    fn try_from(iter: &mut Peekable<T>) -> Result<Self, Self::Error> {
30        let constants =
31            Model::<Asn>::maybe_read_constants(iter, Model::<Asn>::constant_i64_parser)?;
32        let range = if iter.next_is_separator_and_eq('(') {
33            let start = iter.next_or_err()?;
34            iter.next_separator_eq_or_err('.')?;
35            iter.next_separator_eq_or_err('.')?;
36            let end = iter.next_or_err()?;
37            let extensible = if iter.next_is_separator_and_eq(',') {
38                iter.next_separator_eq_or_err('.')?;
39                iter.next_separator_eq_or_err('.')?;
40                iter.next_separator_eq_or_err('.')?;
41                true
42            } else {
43                false
44            };
45            iter.next_separator_eq_or_err(')')?;
46            let start = start
47                .text()
48                .filter(|txt| !txt.eq_ignore_ascii_case("MIN"))
49                .map(|t| match t.parse::<i64>() {
50                    Ok(lit) => LitOrRef::Lit(lit),
51                    Err(_) => LitOrRef::Ref(t.to_string()),
52                });
53
54            let end = end
55                .text()
56                .filter(|txt| !txt.eq_ignore_ascii_case("MAX"))
57                .map(|t| match t.parse::<i64>() {
58                    Ok(lit) => LitOrRef::Lit(lit),
59                    Err(_) => LitOrRef::Ref(t.to_string()),
60                });
61
62            match (start, end) {
63                (Some(LitOrRef::Lit(0)), None) | (None, Some(LitOrRef::Lit(i64::MAX))) => {
64                    Range(None, None, extensible)
65                }
66                (start, end) => Range(start, end, extensible),
67            }
68        } else {
69            Range(None, None, false)
70        };
71        Ok(Self { range, constants })
72    }
73}
74
75impl TryResolve<i64, Integer<i64>> for Integer<LitOrRef<i64>> {
76    fn try_resolve(&self, resolver: &impl Resolver<i64>) -> Result<Integer<i64>, ResolveError> {
77        Ok(Integer {
78            range: Range(
79                self.range
80                    .0
81                    .as_ref()
82                    .map(|lor| resolver.resolve(lor))
83                    .transpose()?,
84                self.range
85                    .1
86                    .as_ref()
87                    .map(|lor| resolver.resolve(lor))
88                    .transpose()?,
89                self.range.2,
90            ),
91            //.reconsider_constraints(),
92            constants: self.constants.clone(),
93        })
94    }
95}