1use dyn_clone::DynClone;
2use serde::{Deserialize, Serialize};
3use std::any::Any;
4use std::collections::HashMap;
5use std::fmt;
6
7mod description;
8pub use description::BlockDescription;
9pub use description::FlowgraphDescription;
10
11pub trait PmtAny: Any + DynClone + Send + Sync + 'static {
12 fn as_any(&self) -> &dyn Any;
13 fn as_any_mut(&mut self) -> &mut dyn Any;
14}
15dyn_clone::clone_trait_object!(PmtAny);
16
17impl<T: Any + DynClone + Send + Sync + 'static> PmtAny for T {
18 fn as_any(&self) -> &dyn Any {
19 self
20 }
21 fn as_any_mut(&mut self) -> &mut dyn Any {
22 self
23 }
24}
25
26impl fmt::Debug for Box<dyn PmtAny> {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "Box<dyn Any>")
29 }
30}
31
32impl dyn PmtAny {
33 pub fn downcast_ref<T: PmtAny>(&self) -> Option<&T> {
34 (*self).as_any().downcast_ref::<T>()
35 }
36 pub fn downcast_mut<T: PmtAny>(&mut self) -> Option<&mut T> {
37 (*self).as_any_mut().downcast_mut::<T>()
38 }
39}
40
41#[non_exhaustive]
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub enum Pmt {
44 Ok,
45 InvalidValue,
46 Null,
47 String(String),
48 Bool(bool),
49 Usize(usize),
50 U32(u32),
51 U64(u64),
52 F32(f32),
53 F64(f64),
54 VecF32(Vec<f32>),
55 VecU64(Vec<u64>),
56 Blob(Vec<u8>),
57 VecPmt(Vec<Pmt>),
58 Finished,
59 MapStrPmt(HashMap<String, Pmt>),
60 #[serde(skip)]
61 Any(Box<dyn PmtAny>),
62}
63
64impl PartialEq for Pmt {
65 fn eq(&self, other: &Self) -> bool {
66 match (self, other) {
67 (Pmt::Null, Pmt::Null) => true,
68 (Pmt::String(x), Pmt::String(y)) => x == y,
69 (Pmt::U32(x), Pmt::U32(y)) => x == y,
70 (Pmt::U64(x), Pmt::U64(y)) => x == y,
71 (Pmt::F32(x), Pmt::F32(y)) => x == y,
72 (Pmt::F64(x), Pmt::F64(y)) => x == y,
73 (Pmt::VecF32(x), Pmt::VecF32(y)) => x == y,
74 (Pmt::VecU64(x), Pmt::VecU64(y)) => x == y,
75 (Pmt::Blob(x), Pmt::Blob(y)) => x == y,
76 _ => false,
77 }
78 }
79}
80
81impl Pmt {
82 pub fn is_string(&self) -> bool {
83 matches!(self, Pmt::String(_))
84 }
85
86 pub fn to_string(&self) -> Option<String> {
87 match &self {
88 Pmt::String(s) => Some(s.clone()),
89 _ => None,
90 }
91 }
92
93 pub fn from_string(s: &str, t: &PmtKind) -> Option<Pmt> {
94 match t {
95 PmtKind::U32 => {
96 if let Ok(v) = s.parse::<u32>() {
97 Some(Pmt::U32(v))
98 } else {
99 None
100 }
101 }
102 PmtKind::U64 => {
103 if let Ok(v) = s.parse::<u64>() {
104 Some(Pmt::U64(v))
105 } else {
106 None
107 }
108 }
109 PmtKind::F32 => {
110 if let Ok(v) = s.parse::<f32>() {
111 Some(Pmt::F32(v))
112 } else {
113 None
114 }
115 }
116 PmtKind::F64 => {
117 if let Ok(v) = s.parse::<f64>() {
118 Some(Pmt::F64(v))
119 } else {
120 None
121 }
122 }
123 PmtKind::String => Some(Pmt::String(s.to_string())),
124 _ => None,
125 }
126 }
127}
128
129#[derive(Debug, Clone)]
130pub struct PmtConversionError;
131
132impl fmt::Display for PmtConversionError {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 write!(f, "PmtConversionError")
135 }
136}
137
138impl std::error::Error for PmtConversionError {}
139
140impl TryInto<f64> for Pmt {
141 type Error = PmtConversionError;
142
143 fn try_into(self) -> Result<f64, Self::Error> {
144 match self {
145 Pmt::F32(f) => Ok(f as f64),
146 Pmt::F64(f) => Ok(f),
147 Pmt::U32(f) => Ok(f as f64),
148 Pmt::U64(f) => Ok(f as f64),
149 _ => Err(PmtConversionError),
150 }
151 }
152}
153
154impl TryInto<usize> for Pmt {
155 type Error = PmtConversionError;
156
157 fn try_into(self) -> Result<usize, Self::Error> {
158 match self {
159 Pmt::Usize(f) => Ok(f),
160 _ => Err(PmtConversionError),
161 }
162 }
163}
164
165#[non_exhaustive]
166#[derive(Clone, PartialEq, Eq)]
167pub enum PmtKind {
168 Ok,
169 InvalidValue,
170 Null,
171 String,
172 Bool,
173 Usize,
174 U32,
175 U64,
176 F32,
177 F64,
178 VecF32,
179 VecU64,
180 Blob,
181 VecPmt,
182 Finished,
183 MapStrPmt,
184 Any,
185}
186
187#[cfg(test)]
188mod test {
189 use super::*;
190
191 #[test]
192 fn pmt() {
193 let p = Pmt::Null;
194 assert!(!p.is_string());
195 assert_eq!(p.to_string(), None);
196 let p = Pmt::String("foo".to_owned());
197 assert!(p.is_string());
198 assert_eq!(p.to_string(), Some("foo".to_owned()));
199 }
200
201 #[test]
202 fn pmt_serde() {
203 let p = Pmt::Null;
204 let mut s = flexbuffers::FlexbufferSerializer::new();
205 p.serialize(&mut s).unwrap();
206
207 let r = flexbuffers::Reader::get_root(s.view()).unwrap();
208 let p2 = Pmt::deserialize(r).unwrap();
209
210 assert_eq!(p, p2);
211 }
212
213 #[allow(clippy::many_single_char_names)]
214 #[test]
215 fn pmt_eq() {
216 let a = Pmt::Null;
217 let b = Pmt::U32(123);
218 assert_ne!(a, b);
219
220 let c = Pmt::Null;
221 let d = Pmt::U32(12);
222 let e = Pmt::U32(123);
223 assert_eq!(a, c);
224 assert_eq!(b, e);
225 assert_ne!(b, d);
226
227 let f1 = Pmt::F32(0.1);
228 let f2 = Pmt::F32(0.1);
229 let f3 = Pmt::F32(0.2);
230 assert_eq!(f1, f2);
231 assert_ne!(f1, f3);
232 }
233
234 #[test]
235 fn vec_pmt() {
236 let vpmt = Pmt::VecPmt(vec![Pmt::U32(1), Pmt::U32(2)]);
237
238 if let Pmt::VecPmt(v) = vpmt {
239 assert_eq!(v[0], Pmt::U32(1));
240 assert_eq!(v[1], Pmt::U32(2));
241 } else {
242 panic!("Not a Pmt::VecPmt");
243 }
244 }
245
246 #[test]
247 fn map_str_pmt() {
248 let u32val = 42;
249 let f64val = 6.02214076e23;
250
251 let msp = Pmt::MapStrPmt(HashMap::from([
252 ("str".to_owned(), Pmt::String("a string".to_owned())),
253 (
254 "submap".to_owned(),
255 Pmt::MapStrPmt(HashMap::from([
256 ("U32".to_owned(), Pmt::U32(u32val)),
257 ("F64".to_owned(), Pmt::F64(f64val)),
258 ])),
259 ),
260 ]));
261
262 if let Pmt::MapStrPmt(m) = msp {
263 if let Some(Pmt::MapStrPmt(sm)) = m.get("submap") {
264 assert_eq!(sm.get("U32"), Some(&Pmt::U32(u32val)));
265 assert_eq!(sm.get("F64"), Some(&Pmt::F64(f64val)));
266 } else {
267 panic!("Could not get submap");
268 }
269 } else {
270 panic!("Not a Pmt::MapStrPmt");
271 }
272 }
273}