Skip to main content

fhir_rs/fhirpath4/
executor.rs

1use crate::{impl_executor_for_anytype, impl_executor_for_primitive};
2use super::*;
3use crate::prelude::*;
4
5pub trait Executor: Base + Convert + Compare {
6
7    fn child(&self, _index: usize) -> Result<Collection> {
8        Err(FhirError::error("该数据类型不支持获取子元素"))
9    }
10
11    fn element(&self, _symbol: &String, _index: &Option<usize>) -> crate::prelude::Result<Collection> {
12        Err(FhirError::error("该数据类型不支持获取子路径"))
13    }
14
15    fn to_collection(&self, index: &Option<usize>) -> Collection;
16}
17
18pub trait Convert {
19    fn to_integer(&self) -> Result<Integer> {
20        Err(FhirError::error("该数据类型不能转换为整数"))
21    }
22
23    fn to_decimal(&self) -> Result<Decimal> {
24        Err(FhirError::error("该数据类型不能转换为数值"))
25    }
26
27    fn to_strings(&self) -> Result<String> {
28        Err(FhirError::error("该数据类型不能转换为字符串"))
29    }
30
31    fn to_datetime(&self) -> Result<DateTime> {
32        Err(FhirError::error("该数据类型不能转换为日期和时间"))
33    }
34
35    fn to_boolean(&self) -> Result<Boolean> {
36        Err(FhirError::error("该数据类型不能转换为布尔"))
37    }
38}
39
40pub trait Compare {
41
42    fn eq(&self, _right: &dyn Executor) -> Result<bool> {
43        Err(FhirError::error("该数据类型不支持比较运算符[==]"))
44    }
45
46    fn gt(&self, _right: &dyn Executor) -> Result<bool> {
47        Err(FhirError::error("该数据类型不支持比较运算符[>]"))
48    }
49
50    fn ge(&self, _right: &dyn Executor) -> Result<bool> {
51        Err(FhirError::error("该数据类型不支持比较运算符[>=]"))
52    }
53
54    fn lt(&self, _right: &dyn Executor) -> Result<bool> {
55        Err(FhirError::error("该数据类型不支持比较运算符[<]"))
56    }
57
58    fn le(&self, _right: &dyn Executor) -> Result<bool> {
59        Err(FhirError::error("该数据类型不支持比较运算符[<=]"))
60    }
61}
62
63macro_rules! impl_executor {
64    (
65        $($ty:ident,)+
66    ) => {
67        $(
68            impl Executor for $ty {
69                fn to_collection(&self, _index: &Option<usize>) -> Collection {
70                    Collection::new_any(Box::new(self.clone()))
71                }
72            }
73        )+
74    }
75}
76
77macro_rules! impl_convert {
78    (
79        $($ty:ident,)+
80    ) => {
81        $(
82            impl Convert for $ty {}
83        )+
84    }
85}
86
87macro_rules! impl_compare {
88    (
89        $($ty:ident,)+
90    ) => {
91        $(
92            impl Compare for $ty {}
93        )+
94    }
95}
96
97impl_executor!(usize, isize, i64, f64, bool, Instant, DateTime, Time, Date, String, Xhtml,);
98impl_convert!(usize, isize, i64, f64, Instant, DateTime, Time, Date,);
99impl_compare!(usize, isize, i64, f64, bool, Instant, DateTime, Time, Date,);
100
101impl Compare for String {
102    fn eq(&self, right: &dyn Executor) -> Result<bool> {
103        let rhs = right.to_strings()?;
104        Ok(*self == rhs)
105    }
106}
107impl Convert for String {
108
109    fn to_strings(&self) -> Result<String> {
110        Ok(self.clone())
111    }
112}
113
114impl Compare for Xhtml {
115    fn eq(&self, right: &dyn Executor) -> Result<bool> {
116        let rhs = right.to_strings()?;
117        Ok(*self.0 == rhs)
118    }
119}
120impl Convert for Xhtml {
121
122    fn to_strings(&self) -> Result<String> {
123        Ok(self.0.clone())
124    }
125}
126
127impl Convert for Boolean {
128    fn to_boolean(&self) -> Result<Boolean> {
129        Ok(*self)
130    }
131}
132
133
134impl<T: Executor> Executor for Box<T> {
135    fn to_collection(&self, index: &Option<usize>) -> Collection {
136        self.as_ref().to_collection(index)
137    }
138}
139
140impl<T: Executor> Convert for Box<T> {}
141impl<T: Executor> Compare for Box<T> {}
142
143impl<T: Executor> Executor for Option<T> {
144
145    fn to_collection(&self, index: &Option<usize>) -> Collection {
146        match self {
147            None => Collection::new(),
148            Some(value) => value.to_collection(index),
149        }
150    }
151}
152
153impl<T: Executor> Convert for Option<T> {}
154impl<T: Executor> Compare for Option<T> {}
155
156impl<T: Executor> Executor for Vec<T> {
157    fn to_collection(&self, index: &Option<usize>) -> Collection {
158        match index {
159            Some(idx) => {
160                match self.get(*idx) {
161                    Some(val) => val.to_collection(index),
162                    None => Collection::new(),
163                }
164            },
165            None => {
166                let mut collection = Collection::new();
167                for part in self{
168                    collection.combine(part.to_collection(index));
169                }
170                collection
171            }
172        }
173    }
174}
175
176impl<T: Executor> Convert for Vec<T> {}
177impl<T: Executor> Compare for Vec<T> {}
178
179impl_executor_for_primitive!{
180    StringDt,
181    IdDt,
182    Base64BinaryDt,
183    MarkdownDt,
184    UriDt,
185    UrlDt,
186    OidDt,
187    UuidDt,
188    CanonicalDt,
189    CodeDt,
190    XhtmlDt,
191    BooleanDt,
192    DateTimeDt,
193    DateDt,
194    TimeDt,
195    InstantDt,
196    UnsignedIntDt,
197    PositiveIntDt,
198    IntegerDt,
199    Integer64Dt,
200    DecimalDt,
201}
202
203impl_executor_for_anytype!{
204    Base64Binary,
205    Boolean,
206    Canonical,
207    Code,
208    DateTime,
209    Date,
210    Decimal,
211    Id,
212    Instant,
213    Integer,
214    Integer64,
215    Markdown,
216    Oid,
217    PositiveInt,
218    String,
219    Time,
220    UnsignedInt,
221    Uri,
222    Url,
223    Uuid,
224    Address,
225    Age,
226    Annotation,
227    Attachment,
228    CodeableConcept,
229    CodeableReference,
230    Coding,
231    ContactPoint,
232    Count,
233    Distance,
234    Duration,
235    HumanName,
236    Identifier,
237    Money,
238    Period,
239    Quantity,
240    Range,
241    Ratio,
242    RatioRange,
243    Reference,
244    SampledData,
245    Signature,
246    Timing,
247    ContactDetail,
248    DataRequirement,
249    Expression,
250    ParameterDefinition,
251    RelatedArtifact,
252    TriggerDefinition,
253    UsageContext,
254    Availability,
255    ExtendedContactDetail,
256    Dosage,
257    Meta,
258}