asn1rs_model/model/
lor.rs1use 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}