Skip to main content

step_p21/ast/
mod.rs

1//! Abstract syntax tree for exchange structure
2//!
3//! This module contains implementation of [serde::Serialize] and
4//! [serde::Deserialize] for AST structs.
5//!
6//! Deserialize
7//! ------------
8//!
9//! [Implementing a Deserializer](https://serde.rs/impl-deserializer.html) page of [serde manual](https://serde.rs/) says
10//! > The deserializer is responsible for mapping the input data
11//! > into [Serde's data model](https://serde.rs/data-model.html) by invoking
12//! > exactly one of the methods
13//! > on the Visitor that it receives.
14//!
15//! [serde::de::Deserializer] trait is implemented for [Parameter],
16//! [Record], and [SubSuperRecord].
17//! Be sure that this mapping is not only for step_p11-generated structs.
18//! This can be used with other Rust structs using `serde_derive::Deserialize`
19//! custom derive:
20//!
21//! ```text
22//! ┌────────────────────┐
23//! │ Exchange Structure │
24//! └─┬──────────────────┘
25//!   │ Deserialier trait  ◄── Implemented here
26//! ┌─▼────────────────┐
27//! │ serde data model │
28//! └─┬────┬───────────┘
29//!   │    │ step_p21_derive::Deserialize
30//!   │ ┌──▼─────────────────────────┐
31//!   │ │ step_p11-generated Rust struct │
32//!   │ └────────────────────────────┘
33//!   │ serde_derive::Deserialize
34//! ┌─▼─────────────────┐
35//! │ Other Rust struct │
36//! └───────────────────┘
37//! ```
38
39pub mod de;
40pub mod ser;
41
42use crate::parser;
43use std::str::FromStr;
44
45/// AST portion
46pub trait AST: FromStr<Err = crate::error::Error> {
47    fn parse(input: &str) -> parser::combinator::ParseResult<'_, Self>;
48}
49
50macro_rules! derive_ast_from_str {
51    ($ast:ty, $parse:path) => {
52        impl std::str::FromStr for $ast {
53            type Err = $crate::error::Error;
54
55            fn from_str(input: &str) -> $crate::error::Result<Self> {
56                use nom::Finish;
57                let input = input.trim();
58                let (residual, record) =
59                    AST::parse(input).finish().map_err(|err| {
60                        $crate::error::TokenizeFailed::new(input, err)
61                    })?;
62                if !residual.is_empty() {
63                    return Err($crate::error::Error::ExtraInputRemaining(
64                        input.to_string(),
65                    ));
66                }
67                Ok(record)
68            }
69        }
70
71        impl AST for $ast {
72            fn parse(input: &str) -> parser::combinator::ParseResult<'_, Self> {
73                $parse(input)
74            }
75        }
76    };
77}
78
79/// Name of an entity instance or a value
80///
81/// Corresponding to [parser::token::rhs_occurrence_name] and
82/// [parser::token::lhs_occurrence_name]
83#[derive(Debug, Clone, PartialEq)]
84pub enum Name {
85    /// Like `#11`, corresponds to [parser::token::entity_instance_name]
86    Entity(u64),
87    /// Like `@11`, corresponds to [parser::token::value_instance_name]
88    Value(u64),
89    /// Like `#CONST_ENTITY`, corresponds to
90    /// [parser::token::constant_entity_name]
91    ConstantEntity(String),
92    /// Like `@CONST_VALUE`, corresponds to [parser::token::constant_value_name]
93    ConstantValue(String),
94}
95derive_ast_from_str!(Name, parser::token::rhs_occurrence_name);
96
97/// A struct typed in EXPRESS schema, e.g. `A(1.0, 2.0)`
98///
99/// FromStr
100/// --------
101///
102/// ```
103/// use std::str::FromStr;
104/// use step_p21::ast::{Parameter, Record};
105///
106/// let record = Record::from_str("A(1, 2)").unwrap();
107/// assert_eq!(
108///     record,
109///     Record {
110///         name: "A".to_string(),
111///         parameter: vec![Parameter::Integer(1), Parameter::Integer(2)]
112///             .into(),
113///     }
114/// )
115/// ```
116///
117/// Deserialize as a map
118/// ---------------------
119///
120/// [serde::Deserializer] implementation for [Record] provides
121/// a mapping it into "map" in serde data model.
122/// The keyword is mapped into the key and the parameters are its value:
123///
124/// ```
125/// use serde::Deserialize;
126/// use std::{collections::HashMap, str::FromStr};
127/// use step_p21::ast::*;
128///
129/// let p = Record::from_str("DATA_KEYWORD(1, 2)").unwrap();
130///
131/// // Map can be deserialize as a hashmap
132/// assert_eq!(
133///     HashMap::<String, Vec<i32>>::deserialize(&p).unwrap(),
134///     maplit::hashmap! {
135///         "DATA_KEYWORD".to_string() => vec![1, 2]
136///     }
137/// );
138///
139/// // Map in serde can be interpreted as Rust field
140/// #[derive(Debug, Clone, PartialEq, Deserialize)]
141/// struct X {
142///     #[serde(rename = "DATA_KEYWORD")]
143///     a: Vec<i32>,
144/// }
145/// assert_eq!(X::deserialize(&p).unwrap(), X { a: vec![1, 2] });
146/// ```
147///
148/// Mapping to simple instance
149/// ---------------------------
150///
151/// It is deserialized as a "struct" only when the hint function
152/// [serde::Deserializer::deserialize_struct] is called
153/// and the struct name matches to its keyword appears in the exchange
154/// structure. See [the manual of container attribute in serde](https://serde.rs/container-attrs.html)
155/// for detail.
156///
157/// ```
158/// use serde::Deserialize;
159/// use std::{collections::HashMap, str::FromStr};
160/// use step_p21::ast::*;
161///
162/// let p = Record::from_str("DATA_KEYWORD(1, 2)").unwrap();
163///
164/// #[derive(Debug, Clone, PartialEq, Deserialize)]
165/// #[serde(rename = "DATA_KEYWORD")] // keyword matches
166/// struct A {
167///     x: i32,
168///     y: i32,
169/// }
170/// assert_eq!(A::deserialize(&p).unwrap(), A { x: 1, y: 2 });
171///
172/// #[derive(Debug, Clone, PartialEq, Deserialize)]
173/// #[serde(rename = "ANOTHER_KEYWORD")] // keyword does not match
174/// struct B {
175///     x: i32,
176///     y: i32,
177/// }
178/// assert!(B::deserialize(&p).is_err());
179/// ```
180///
181/// Internal mapping to complex entity instance
182/// --------------------------------------------
183///
184/// Complex entity in EXPRESS language is
185/// a set of two or more primitive component called partial complex entity.
186///
187/// ```text
188/// ENTITY person;
189///   name: STRING;
190/// END_ENTITY;
191///
192/// ENTITY employee SUBTYPE OF (person);
193///   pay: INTEGER;
194/// END_ENTITY;
195///
196/// ENTITY student SUBTYPE OF (person);
197///   school_name: STRING;
198/// END_ENTITY;
199/// ```
200///
201/// In this EXPRESS schema, a complex entity of `person` can have three
202/// components representing `person`, `employee`, and `student`.
203/// There are two way of mapping it from an exchange structure.
204/// The internal mapping looks like usual case:
205///
206/// ```text
207/// #1 = EMPLOYEE('Hitori Goto', 10);
208/// #2 = STUDENT('Ikuno Kita', 'Shuka');
209/// ```
210///
211/// `#1` has two parameters while `employee` definition has a field `pay`.
212/// These parameters are consumed by supertype `person` first,
213/// and then subtype `employee` consumes:
214///
215/// ```text
216/// #1 = EMPLOYEE('Hitori Goto', 10);
217///               ▲              ▲
218///               │              └─ map to pay in employee
219///               └─ map to name in person
220/// ```
221///
222/// Internal mapping cannot handle the case where
223/// both `employee` and `student` components co-exist.
224/// This case will be handled by external mapping using [SubSuperRecord].
225///
226/// The detail of internal mapping is defined in 12.2.5.2 "Internal mapping"
227/// of [ISO-10303-21](https://www.iso.org/standard/63141.html).
228///
229/// In terms of serde data model, [Record] is not self-describing
230/// when using internal mapping rule.
231/// Structs using internal mapping should implement [serde::Deserialize]
232/// as described in subtype-supertype constraint in EXPRESS schema.
233#[derive(Debug, Clone, PartialEq)]
234pub struct Record {
235    pub name: String,
236    pub parameter: Parameter,
237}
238derive_ast_from_str!(Record, parser::exchange::simple_record);
239
240/// A set of [Record] mapping to complex entity instance,
241/// e.g. `(A(1) B(2.0) C("3"))`
242///
243/// FromStr
244/// --------
245///
246/// ```
247/// use std::str::FromStr;
248/// use step_p21::ast::*;
249///
250/// let record = SubSuperRecord::from_str("(A(1, 2) B(3, 4))").unwrap();
251/// assert_eq!(
252///     record,
253///     SubSuperRecord(vec![
254///         Record {
255///             name: "A".to_string(),
256///             parameter: vec![Parameter::Integer(1), Parameter::Integer(2)]
257///                 .into(),
258///         },
259///         Record {
260///             name: "B".to_string(),
261///             parameter: vec![Parameter::Integer(3), Parameter::Integer(4)]
262///                 .into(),
263///         }
264///     ])
265/// )
266/// ```
267///
268/// Deserialize as a map
269/// ---------------------
270///
271/// Similar to [Record], [SubSuperRecord] can be deserialized as a "map":
272///
273/// ```
274/// use serde::Deserialize;
275/// use std::{collections::HashMap, str::FromStr};
276/// use step_p21::ast::*;
277///
278/// let p = SubSuperRecord::from_str("(A(1, 2) B(3, 4))").unwrap();
279///
280/// // Map can be deserialize as a hashmap
281/// assert_eq!(
282///     HashMap::<String, Vec<i32>>::deserialize(&p).unwrap(),
283///     maplit::hashmap! {
284///         "A".to_string() => vec![1, 2],
285///         "B".to_string() => vec![3, 4],
286///     }
287/// );
288///
289/// // Map in serde can be interpreted as Rust field
290/// #[derive(Debug, Clone, PartialEq, Deserialize)]
291/// struct X {
292///     #[serde(rename = "A")]
293///     a: Vec<i32>,
294///     #[serde(rename = "B")]
295///     b: Vec<i32>,
296/// }
297/// assert_eq!(
298///     X::deserialize(&p).unwrap(),
299///     X {
300///         a: vec![1, 2],
301///         b: vec![3, 4]
302///     }
303/// );
304/// ```
305///
306/// External mapping to complex entity instance
307/// --------------------------------------------
308///
309/// As discussed in [Record] for internal mapping,
310///
311/// ```text
312/// ENTITY person;
313///   name: STRING;
314/// END_ENTITY;
315///
316/// ENTITY employee SUBTYPE OF (person);
317///   pay: INTEGER;
318/// END_ENTITY;
319///
320/// ENTITY student SUBTYPE OF (person);
321///   school_name: STRING;
322/// END_ENTITY;
323/// ```
324///
325/// The instance of `person` may have three partial complex entity.
326/// External mapping has different looks in exchange structure:
327///
328/// ```text
329/// #3 = (PERSON('Hitori Goto') EMPLOYEE(10));
330/// #4 = (PERSON('Ikuno Kita') STUDENT('Shuka));
331/// #5 = (PERSON('Nizika Iziti') EMPLOYEE(15) STUDENT('Simokitazawa'))
332/// ```
333///
334/// Each components enclosed by `()` corresponds to a partial entity instance,
335/// which consists of fields declared in its entity definition.
336///
337/// ```text
338/// #5 = (PERSON('Nizika Iziti') EMPLOYEE(15) STUDENT('Simokitazawa'))
339///              ▲                        ▲           ▲
340///              │                        │           └─ school_name in student
341///              │                        └─ pay in employee
342///              └─ name in person
343/// ```
344///
345/// The detail of external mapping is defined in 12.2.5.3 "External mapping"
346/// of [ISO-10303-21](https://www.iso.org/standard/63141.html).
347///
348/// [SubSuperRecord] is not self-describing because
349/// EXPRESS does not defines memory layout of complex entities.
350#[derive(Debug, Clone, PartialEq)]
351pub struct SubSuperRecord(pub Vec<Record>);
352derive_ast_from_str!(SubSuperRecord, parser::exchange::subsuper_record);
353
354impl IntoIterator for SubSuperRecord {
355    type IntoIter = std::vec::IntoIter<Self::Item>;
356    type Item = Record;
357
358    fn into_iter(self) -> Self::IntoIter {
359        self.0.into_iter()
360    }
361}
362
363impl<'a> IntoIterator for &'a SubSuperRecord {
364    type IntoIter = std::slice::Iter<'a, Record>;
365    type Item = &'a Record;
366
367    fn into_iter(self) -> Self::IntoIter {
368        self.0.iter()
369    }
370}
371
372impl FromIterator<Record> for SubSuperRecord {
373    fn from_iter<I: IntoIterator<Item = Record>>(iter: I) -> Self {
374        Self(iter.into_iter().collect())
375    }
376}
377
378impl<'a> FromIterator<&'a Record> for SubSuperRecord {
379    fn from_iter<I: IntoIterator<Item = &'a Record>>(iter: I) -> Self {
380        Self(iter.into_iter().cloned().collect())
381    }
382}
383
384/// `DATA` section in STEP file
385///
386/// ```
387/// use std::str::FromStr;
388/// use step_p21::ast::DataSection;
389///
390/// let input = r#"
391/// DATA;
392///   #1 = A(1.0, 2.0);
393///   #2 = B(3.0, A((4.0, 5.0)));
394///   #3 = B(6.0, #1);
395/// ENDSEC;
396/// "#;
397/// let data_section = DataSection::from_str(input).unwrap();
398/// dbg!(data_section);
399/// ```
400#[derive(Debug, Clone, PartialEq)]
401pub struct DataSection {
402    /// Metadata
403    pub meta: Vec<Parameter>,
404    /// Each lines in data section
405    pub entities: Vec<EntityInstance>,
406}
407derive_ast_from_str!(DataSection, parser::exchange::data_section);
408
409/// Primitive value type in STEP data
410///
411/// Inline struct or list can be nested, i.e. `Parameter` can be a tree.
412///
413/// ```
414/// use nom::Finish;
415/// use step_p21::{
416///     ast::{Parameter, Record},
417///     parser::exchange,
418/// };
419///
420/// let (residual, p) = exchange::parameter("B((1.0, A((2.0, 3.0))))")
421///     .finish()
422///     .unwrap();
423/// assert_eq!(residual, "");
424///
425/// // A((2.0, 3.0))
426/// let a = Parameter::Typed {
427///     keyword: "A".to_string(),
428///     parameter: Box::new(
429///         vec![Parameter::real(2.0), Parameter::real(3.0)].into(),
430///     ),
431/// };
432///
433/// // B((1.0, a))
434/// let b = Parameter::Typed {
435///     keyword: "B".to_string(),
436///     parameter: Box::new(vec![Parameter::real(1.0), a].into()),
437/// };
438///
439/// assert_eq!(p, b);
440/// ```
441///
442/// FromIterator
443/// -------------
444/// Create a list as `Parameter::List` from `Iterator<Item=Parameter>` or
445/// `Iterator<Item=&Parameter>`.
446///
447/// ```
448/// use step_p21::ast::Parameter;
449///
450/// let p: Parameter = [Parameter::real(1.0), Parameter::real(2.0)]
451///     .iter()
452///     .collect();
453/// assert!(matches!(p, Parameter::List(_)));
454/// ```
455///
456/// Deserialize
457/// ------------
458///
459/// | Parameter   | serde data model |
460/// |:------------|:-----------------|
461/// | Integer     | i64              |
462/// | Real        | f64              |
463/// | String      | string           |
464/// | List        | seq              |
465/// | NotProvided | option (always none)|
466/// | Omitted     | option (always none)|
467/// | Enumeration | unit_variant (through [serde::de::value::StringDeserializer])|
468/// | Typed       | map (through [de::RecordDeserializer])|
469/// | Ref         | newtype_variant  |
470#[derive(Debug, Clone, PartialEq, derive_more::From)]
471pub enum Parameter {
472    /// Corresponding to `TYPED_PARAMETER` in WSN:
473    ///
474    /// ```text
475    /// TYPED_PARAMETER = KEYWORD "(" PARAMETER ")" .
476    /// ```
477    ///
478    /// and [parser::exchange::typed_parameter].
479    /// It takes only one `PARAMETER` different from [Record],
480    /// which takes many `PARAMETER`s.
481    ///
482    /// ```text
483    /// SIMPLE_RECORD = KEYWORD "(" [ PARAMETER_LIST ] ")" .
484    /// ```
485    ///
486    /// FromStr
487    /// --------
488    /// ```
489    /// use std::str::FromStr;
490    /// use step_p21::ast::Parameter;
491    ///
492    /// let p = Parameter::from_str("FILE_NAME('step_p21')").unwrap();
493    /// assert!(matches!(p, Parameter::Typed { .. }));
494    /// ```
495    ///
496    /// Deserialize
497    /// ------------
498    /// ```
499    /// use serde::Deserialize;
500    /// use std::{collections::HashMap, str::FromStr};
501    /// use step_p21::ast::*;
502    ///
503    /// // Regarded as a map `{ "A": [1, 2] }` in serde data model
504    /// let p = Parameter::from_str("A((1, 2))").unwrap();
505    ///
506    /// // Map can be deserialize as a hashmap
507    /// assert_eq!(
508    ///     HashMap::<String, Vec<i32>>::deserialize(&p).unwrap(),
509    ///     maplit::hashmap! {
510    ///         "A".to_string() => vec![1, 2]
511    ///     }
512    /// );
513    ///
514    /// // Map in serde can be interpreted as Rust field
515    /// #[derive(Debug, Clone, PartialEq, Deserialize)]
516    /// struct X {
517    ///     #[serde(rename = "A")]
518    ///     a: Vec<i32>,
519    /// }
520    /// assert_eq!(X::deserialize(&p).unwrap(), X { a: vec![1, 2] });
521    /// ```
522    ///
523    /// Different from [Record], deserializing into a struct is not supported:
524    ///
525    /// ```
526    /// use serde::Deserialize;
527    /// use std::{collections::HashMap, str::FromStr};
528    /// use step_p21::ast::*;
529    ///
530    /// let p = Parameter::from_str("A(1)").unwrap();
531    ///
532    /// #[derive(Debug, Clone, PartialEq, Deserialize)]
533    /// struct A {
534    ///     x: i32,
535    /// }
536    /// assert!(A::deserialize(&p).is_err());
537    /// ```
538    Typed {
539        keyword: String,
540        parameter: Box<Parameter>,
541    },
542
543    /// Signed integer
544    ///
545    /// FromStr
546    /// --------
547    /// ```
548    /// use std::str::FromStr;
549    /// use step_p21::ast::Parameter;
550    ///
551    /// let p = Parameter::from_str("10").unwrap();
552    /// assert_eq!(p, Parameter::Integer(10));
553    ///
554    /// let p = Parameter::from_str("-10").unwrap();
555    /// assert_eq!(p, Parameter::Integer(-10));
556    /// ```
557    ///
558    /// Deserialize
559    /// ------------
560    /// ```
561    /// use serde::Deserialize;
562    /// use step_p21::ast::*;
563    ///
564    /// let p = Parameter::Integer(2);
565    /// let a = i64::deserialize(&p).unwrap();
566    /// assert_eq!(a, 2);
567    ///
568    /// // can be deserialized as unsigned
569    /// let a = u64::deserialize(&p).unwrap();
570    /// assert_eq!(a, 2);
571    ///
572    /// // cannot be deserialized negative integer into unsigned
573    /// let p = Parameter::Integer(-2);
574    /// let a = i64::deserialize(&p).unwrap();
575    /// assert_eq!(a, -2);
576    /// assert!(u64::deserialize(&p).is_err());
577    /// ```
578    #[from]
579    Integer(i64),
580
581    /// Real number
582    ///
583    /// FromStr
584    /// --------
585    /// ```
586    /// use std::str::FromStr;
587    /// use step_p21::ast::Parameter;
588    ///
589    /// let p = Parameter::from_str("1.0").unwrap();
590    /// assert_eq!(p, Parameter::Real(1.0));
591    /// ```
592    #[from]
593    Real(f64),
594
595    /// string literal
596    ///
597    /// FromStr
598    /// --------
599    /// ```
600    /// use std::str::FromStr;
601    /// use step_p21::ast::Parameter;
602    ///
603    /// let p = Parameter::from_str("'EXAMPLE STRING'").unwrap();
604    /// assert_eq!(p, Parameter::String("EXAMPLE STRING".to_string()));
605    /// ```
606    #[from]
607    String(String),
608
609    /// Enumeration defined in EXPRESS schema, like `.TRUE.`
610    ///
611    /// FromStr
612    /// --------
613    /// ```
614    /// # use std::str::FromStr;
615    /// # use step_p21::ast::Parameter;
616    /// let p = Parameter::from_str(".TRUE.").unwrap();
617    /// assert_eq!(p, Parameter::Enumeration("TRUE".to_string()));
618    /// ```
619    ///
620    /// Deserialize
621    /// ------------
622    /// ```
623    /// use serde::Deserialize;
624    /// use std::str::FromStr;
625    /// use step_p21::ast::*;
626    ///
627    /// let p = Parameter::from_str(".A.").unwrap();
628    ///
629    /// #[derive(Debug, PartialEq, Deserialize)]
630    /// enum E {
631    ///     A,
632    ///     B,
633    /// }
634    /// assert_eq!(E::deserialize(&p).unwrap(), E::A);
635    /// ```
636    Enumeration(String),
637
638    /// List of parameters. This can be non-uniform.
639    ///
640    /// FromStr
641    /// --------
642    /// ```
643    /// use std::str::FromStr;
644    /// use step_p21::ast::Parameter;
645    ///
646    /// let p = Parameter::from_str("(1.0, 2, 'STRING')").unwrap();
647    /// assert_eq!(
648    ///     p,
649    ///     Parameter::List(vec![
650    ///         Parameter::Real(1.0),
651    ///         Parameter::Integer(2),
652    ///         Parameter::String("STRING".to_string()),
653    ///     ])
654    /// );
655    /// ```
656    ///
657    /// Deserialize
658    /// ------------
659    /// ```
660    /// use serde::Deserialize;
661    /// use std::str::FromStr;
662    /// use step_p21::ast::*;
663    ///
664    /// let p = Parameter::from_str("(1, 2, 3)").unwrap();
665    ///
666    /// // As Vec<i32>
667    /// let a = Vec::<i32>::deserialize(&p).unwrap();
668    /// assert_eq!(a, vec![1, 2, 3]);
669    ///
670    /// // As user-defined struct
671    /// #[derive(Debug, Clone, PartialEq, Deserialize)]
672    /// struct A {
673    ///     x: i32,
674    ///     y: i32,
675    ///     z: i32,
676    /// }
677    /// let a = A::deserialize(&p).unwrap();
678    /// assert_eq!(a, A { x: 1, y: 2, z: 3 });
679    /// ```
680    #[from]
681    List(Vec<Parameter>),
682
683    /// A reference to entity or value
684    ///
685    /// Deserialize
686    /// ------------
687    /// ```
688    /// use serde::Deserialize;
689    /// use std::str::FromStr;
690    /// use step_p21::ast::*;
691    ///
692    /// let p = Parameter::from_str("#12").unwrap();
693    ///
694    /// #[derive(Debug, PartialEq, Deserialize)]
695    /// enum Id {
696    ///     #[serde(rename = "Entity")] // "Entity" is keyword for entity reference
697    ///     E(usize),
698    ///     #[serde(rename = "Value")] // "Value" is keyword for value reference
699    ///     V(usize),
700    /// }
701    /// assert_eq!(Id::deserialize(&p).unwrap(), Id::E(12));
702    /// ```
703    #[from]
704    Ref(Name),
705
706    /// The special token dollar sign (`$`) is used to represent
707    /// an object whose value is not provided in the exchange structure.
708    ///
709    /// Deserialize
710    /// -----------
711    /// ```
712    /// use serde::Deserialize;
713    /// use step_p21::ast::*;
714    ///
715    /// let p = Parameter::NotProvided;
716    /// assert_eq!(Option::<i64>::deserialize(&p).unwrap(), None);
717    /// ```
718    NotProvided,
719
720    /// Omitted parameter denoted by `*`
721    ///
722    /// Deserialize
723    /// ------------
724    /// ```
725    /// use serde::Deserialize;
726    /// use step_p21::ast::*;
727    ///
728    /// let p = Parameter::Omitted;
729    /// assert_eq!(Option::<i64>::deserialize(&p).unwrap(), None);
730    /// ```
731    Omitted,
732}
733
734impl Parameter {
735    pub fn integer(i: i64) -> Self {
736        Parameter::Integer(i)
737    }
738
739    pub fn real(x: f64) -> Self {
740        Parameter::Real(x)
741    }
742
743    pub fn string(s: &str) -> Self {
744        Parameter::String(s.to_string())
745    }
746}
747
748impl std::iter::FromIterator<Parameter> for Parameter {
749    fn from_iter<Iter: IntoIterator<Item = Parameter>>(iter: Iter) -> Self {
750        Parameter::List(iter.into_iter().collect())
751    }
752}
753
754impl<'a> std::iter::FromIterator<&'a Parameter> for Parameter {
755    fn from_iter<Iter: IntoIterator<Item = &'a Parameter>>(iter: Iter) -> Self {
756        iter.into_iter().cloned().collect()
757    }
758}
759
760derive_ast_from_str!(Parameter, parser::exchange::parameter);
761
762/// Entire exchange structure
763#[derive(Debug, Clone, PartialEq)]
764pub struct Exchange {
765    /// `HEADER` section
766    pub header: Vec<Record>,
767    /// `ANCHOR` section
768    pub anchor: Vec<Anchor>,
769    /// `REFERENCE` section
770    pub reference: Vec<ReferenceEntry>,
771    /// `DATA` section
772    pub data: Vec<DataSection>,
773    /// `SIGNATURE` section
774    pub signature: Vec<String>,
775}
776derive_ast_from_str!(Exchange, parser::exchange::exchange_file);
777
778/// Each line of data section
779#[derive(Debug, Clone, PartialEq)]
780pub enum EntityInstance {
781    Simple { id: u64, record: Record },
782    Complex { id: u64, subsuper: SubSuperRecord },
783}
784derive_ast_from_str!(EntityInstance, parser::exchange::entity_instance);
785
786#[derive(Debug, Clone, PartialEq)]
787pub struct ReferenceEntry {
788    pub name: Name,
789    pub resource: URI,
790}
791derive_ast_from_str!(ReferenceEntry, parser::exchange::reference);
792
793#[derive(Debug, Clone, PartialEq)]
794pub struct URI(pub String);
795
796#[derive(Debug, Clone, PartialEq)]
797pub struct Anchor {
798    pub name: String,
799    pub item: AnchorItem,
800    pub tags: Vec<(String, AnchorItem)>,
801}
802derive_ast_from_str!(Anchor, parser::exchange::anchor);
803
804#[derive(Debug, Clone, PartialEq)]
805pub enum AnchorItem {
806    Integer(i64),
807    Real(f64),
808    String(String),
809    Enumeration(String),
810    /// The special token dollar sign (`$`) is used to represent an object whose
811    /// value is not provided in the exchange structure.
812    NotProvided,
813    /// A reference to entity or value
814    Name(Name),
815    /// List of other parameters
816    List(Vec<AnchorItem>),
817}
818derive_ast_from_str!(AnchorItem, parser::exchange::anchor_item);