Skip to main content

asn1rs_model/model/
lor.rs

1use crate::model::rs::ResolveScope;
2use crate::model::{Asn, LiteralValue, Model};
3use std::fmt::{Debug, Display, Formatter};
4
5pub trait ResolveState: Clone {
6    type SizeType: Display + Debug + Clone + PartialOrd + PartialEq;
7    type RangeType: Display + Debug + Clone + PartialOrd + PartialEq;
8    type ConstType: Debug + Clone + PartialOrd + PartialEq;
9}
10
11#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
12pub struct Resolved;
13impl ResolveState for Resolved {
14    type SizeType = usize;
15    type RangeType = i64;
16    type ConstType = LiteralValue;
17}
18
19#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
20pub struct Unresolved;
21impl ResolveState for Unresolved {
22    type SizeType = LitOrRef<usize>;
23    type RangeType = LitOrRef<i64>;
24    type ConstType = LitOrRef<LiteralValue>;
25}
26
27#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
28pub enum LitOrRef<T> {
29    Lit(T),
30    Ref(String),
31}
32
33impl<T> Default for LitOrRef<T>
34where
35    T: Default,
36{
37    fn default() -> Self {
38        LitOrRef::Lit(T::default())
39    }
40}
41
42impl<T> Display for LitOrRef<T>
43where
44    T: Display,
45{
46    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47        match self {
48            LitOrRef::Lit(v) => Display::fmt(v, f),
49            LitOrRef::Ref(v) => Display::fmt(v, f),
50        }
51    }
52}
53
54#[derive(Debug, PartialOrd, PartialEq, Eq)]
55pub enum Error {
56    FailedToResolveType(String),
57    FailedToResolveReference(String),
58    FailedToParseLiteral(String),
59}
60
61impl std::error::Error for Error {}
62impl std::fmt::Display for Error {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        match self {
65            Error::FailedToResolveType(name) => {
66                write!(f, "Failed to resolve type with name: {}", name)
67            }
68            Error::FailedToResolveReference(name) => {
69                write!(f, "Failed to resolve reference with name: {}", name)
70            }
71            Error::FailedToParseLiteral(literal) => {
72                write!(f, "Failed to parse literal: {}", literal)
73            }
74        }
75    }
76}
77
78pub trait Resolver<T> {
79    fn resolve(&self, lor: &LitOrRef<T>) -> Result<T, Error>;
80}
81
82pub trait TryResolve<T, R: Sized> {
83    fn try_resolve(&self, resolver: &impl Resolver<T>) -> Result<R, Error>;
84}
85
86impl Model<Asn<Unresolved>> {
87    pub fn try_resolve(&self) -> Result<Model<Asn<Resolved>>, Error> {
88        ResolveScope::from(self).try_resolve()
89    }
90}
91
92#[cfg(test)]
93pub mod tests {
94    use super::*;
95    use crate::model::Range;
96    use crate::model::Type;
97    use crate::model::{Definition, Integer, ValueReference};
98
99    #[test]
100    fn test_simple_resolve() {
101        let mut unresolved = Model::<Asn<Unresolved>> {
102            name: "UnresolvedModel".to_string(),
103            definitions: vec![Definition(
104                "IntegerWithVR".to_string(),
105                Type::<Unresolved>::Integer(Integer {
106                    range: Range(
107                        Some(LitOrRef::Ref("my_min".to_string())),
108                        Some(LitOrRef::Ref("my_max".to_string())),
109                        true,
110                    ),
111                    constants: Vec::default(),
112                })
113                .untagged(),
114            )],
115            ..Default::default()
116        };
117
118        assert_eq!(
119            Error::FailedToResolveReference("my_min".to_string()),
120            unresolved.try_resolve().unwrap_err()
121        );
122
123        unresolved.value_references.push(ValueReference {
124            name: "my_min".to_string(),
125            role: Type::Integer(Integer::default()).untagged(),
126            value: LiteralValue::Integer(123),
127        });
128
129        assert_eq!(
130            Error::FailedToResolveReference("my_max".to_string()),
131            unresolved.try_resolve().unwrap_err()
132        );
133
134        unresolved.value_references.push(ValueReference {
135            name: "my_max".to_string(),
136            role: Type::Integer(Integer::default()).untagged(),
137            value: LiteralValue::Integer(456),
138        });
139
140        let resolved = unresolved.try_resolve().unwrap();
141        assert_eq!(
142            &resolved.definitions[..],
143            &[Definition(
144                "IntegerWithVR".to_string(),
145                Type::<Resolved>::Integer(Integer {
146                    range: Range(Some(123), Some(456), true),
147                    constants: Vec::default(),
148                })
149                .untagged(),
150            )]
151        )
152    }
153}