cameleon_genapi/parser/
elem_type.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::marker::PhantomData;
6
7use crate::{
8    builder::{CacheStoreBuilder, NodeStoreBuilder, ValueStoreBuilder},
9    elem_type::{
10        AccessMode, AddressKind, BitMask, CachingMode, DisplayNotation, Endianness,
11        FloatRepresentation, ImmOrPNode, IntegerRepresentation, MergePriority, NameSpace,
12        NamedValue, PIndex, PValue, RegPIndex, Sign, Slope, StandardNameSpace, ValueIndexed,
13        ValueKind, Visibility,
14    },
15    interface::INode,
16    store::{FloatId, IntegerId, NodeData, NodeId},
17    IntSwissKnifeNode,
18};
19
20use super::{
21    elem_name::{
22        ADDRESS, BIT, INDEX, INT_SWISS_KNIFE, NAME, OFFSET, P_ADDRESS, P_INDEX, P_OFFSET, P_VALUE,
23        P_VALUE_COPY, P_VALUE_INDEXED, VALUE, VALUE_INDEXED,
24    },
25    xml, Parse,
26};
27
28macro_rules! match_text_view{
29    ($text:expr,
30        $s1:expr => $var1:expr,
31        $($s:expr => $var:expr,)*
32    ) => {
33        if $text == $s1 {
34            $var1
35        } $(else if $text == $s {
36            $var
37        })* else {
38            unreachable!()
39        }
40    }
41}
42
43impl Default for NameSpace {
44    fn default() -> Self {
45        Self::Custom
46    }
47}
48
49impl From<&str> for NameSpace {
50    fn from(value: &str) -> Self {
51        match value {
52            "Standard" => Self::Standard,
53            "Custom" => Self::Custom,
54            _ => unreachable!(),
55        }
56    }
57}
58
59impl Parse for NameSpace {
60    fn parse(
61        node: &mut xml::Node,
62        _: &mut impl NodeStoreBuilder,
63        _: &mut impl ValueStoreBuilder,
64        _: &mut impl CacheStoreBuilder,
65    ) -> Self {
66        let text = node.next_text().unwrap();
67        match_text_view!(text,
68            "Standard" => Self::Standard,
69            "Custom" => Self::Custom,
70        )
71    }
72}
73
74impl Default for Visibility {
75    fn default() -> Self {
76        Self::Beginner
77    }
78}
79
80impl Parse for Visibility {
81    fn parse(
82        node: &mut xml::Node,
83        _: &mut impl NodeStoreBuilder,
84        _: &mut impl ValueStoreBuilder,
85        _: &mut impl CacheStoreBuilder,
86    ) -> Self {
87        let text = node.next_text().unwrap();
88        match_text_view!(text,
89            "Beginner" => Self::Beginner,
90            "Expert" => Self::Expert,
91            "Guru" => Self::Guru,
92            "Invisible" => Self::Invisible,
93        )
94    }
95}
96
97impl From<&str> for MergePriority {
98    fn from(value: &str) -> Self {
99        match value {
100            "1" => Self::High,
101            "0" => Self::Mid,
102            "-1" => Self::Low,
103            _ => unreachable!(),
104        }
105    }
106}
107
108impl Default for MergePriority {
109    fn default() -> Self {
110        Self::Mid
111    }
112}
113
114impl Parse for MergePriority {
115    fn parse(
116        node: &mut xml::Node,
117        _: &mut impl NodeStoreBuilder,
118        _: &mut impl ValueStoreBuilder,
119        _: &mut impl CacheStoreBuilder,
120    ) -> Self {
121        let text = node.next_text().unwrap();
122        match_text_view!(text,
123            "1" => Self::High,
124            "0" => Self::Mid,
125            "-1" => Self::Low,
126        )
127    }
128}
129
130impl Parse for AccessMode {
131    fn parse(
132        node: &mut xml::Node,
133        _: &mut impl NodeStoreBuilder,
134        _: &mut impl ValueStoreBuilder,
135        _: &mut impl CacheStoreBuilder,
136    ) -> Self {
137        let text = node.next_text().unwrap();
138        match_text_view!(text,
139            "RO" => Self::RO,
140            "WO" => Self::WO,
141            "RW" => Self::RW,
142        )
143    }
144}
145
146impl Parse for ImmOrPNode<i64> {
147    fn parse(
148        node: &mut xml::Node,
149        node_builder: &mut impl NodeStoreBuilder,
150        value_builder: &mut impl ValueStoreBuilder,
151        cache_builder: &mut impl CacheStoreBuilder,
152    ) -> Self {
153        let peeked_text = node.peek().unwrap().text();
154        if peeked_text.view().chars().next().unwrap().is_alphabetic() {
155            Self::PNode(node.parse(node_builder, value_builder, cache_builder))
156        } else {
157            Self::Imm(node.parse(node_builder, value_builder, cache_builder))
158        }
159    }
160}
161
162impl Parse for ImmOrPNode<f64> {
163    fn parse(
164        node: &mut xml::Node,
165        node_builder: &mut impl NodeStoreBuilder,
166        value_builder: &mut impl ValueStoreBuilder,
167        cache_builder: &mut impl CacheStoreBuilder,
168    ) -> Self {
169        let peeked_text = node.peek().unwrap().text();
170
171        if peeked_text == "INF"
172            || peeked_text == "-INF"
173            || peeked_text == "NaN"
174            || !peeked_text.view().chars().next().unwrap().is_alphabetic()
175        {
176            Self::Imm(node.parse(node_builder, value_builder, cache_builder))
177        } else {
178            Self::PNode(node.parse(node_builder, value_builder, cache_builder))
179        }
180    }
181}
182
183impl Parse for ImmOrPNode<bool> {
184    fn parse(
185        node: &mut xml::Node,
186        node_builder: &mut impl NodeStoreBuilder,
187        value_builder: &mut impl ValueStoreBuilder,
188        cache_builder: &mut impl CacheStoreBuilder,
189    ) -> Self {
190        if convert_to_bool_opt(&node.peek().unwrap().text().view()).is_some() {
191            Self::Imm(node.parse(node_builder, value_builder, cache_builder))
192        } else {
193            Self::PNode(node.parse(node_builder, value_builder, cache_builder))
194        }
195    }
196}
197
198macro_rules! impl_parse_for_imm_or_pnode_id {
199    ($id:ty, $value_ty:ty) => {
200        impl Parse for ImmOrPNode<$id> {
201            fn parse(
202                node: &mut xml::Node,
203                node_builder: &mut impl NodeStoreBuilder,
204                value_builder: &mut impl ValueStoreBuilder,
205                cache_builder: &mut impl CacheStoreBuilder,
206            ) -> Self {
207                let node: ImmOrPNode<$value_ty> =
208                    node.parse(node_builder, value_builder, cache_builder);
209                match node {
210                    ImmOrPNode::Imm(i) => {
211                        let id = value_builder.store(i);
212                        ImmOrPNode::Imm(id)
213                    }
214                    ImmOrPNode::PNode(id) => ImmOrPNode::PNode(id),
215                }
216            }
217        }
218    };
219}
220
221impl_parse_for_imm_or_pnode_id!(IntegerId, i64);
222impl_parse_for_imm_or_pnode_id!(FloatId, f64);
223
224impl Default for IntegerRepresentation {
225    fn default() -> Self {
226        Self::PureNumber
227    }
228}
229
230impl Parse for IntegerRepresentation {
231    fn parse(
232        node: &mut xml::Node,
233        _: &mut impl NodeStoreBuilder,
234        _: &mut impl ValueStoreBuilder,
235        _: &mut impl CacheStoreBuilder,
236    ) -> Self {
237        use IntegerRepresentation::{
238            Boolean, HexNumber, IpV4Address, Linear, Logarithmic, MacAddress, PureNumber,
239        };
240
241        let value = node.next_text().unwrap();
242        match_text_view!(value,
243            "Linear" => Linear,
244            "Logarithmic" => Logarithmic,
245            "Boolean" => Boolean,
246            "PureNumber" => PureNumber,
247            "HexNumber" => HexNumber,
248            "IPV4Address" => IpV4Address,
249            "MACAddress" => MacAddress,
250        )
251    }
252}
253
254impl Parse for FloatRepresentation {
255    fn parse(
256        node: &mut xml::Node,
257        _: &mut impl NodeStoreBuilder,
258        _: &mut impl ValueStoreBuilder,
259        _: &mut impl CacheStoreBuilder,
260    ) -> Self {
261        let text = node.next_text().unwrap();
262        match_text_view! {text,
263            "Linear" => Self::Linear,
264            "Logarithmic" => Self::Logarithmic,
265            "PureNumber" => Self::PureNumber,
266        }
267    }
268}
269
270impl Default for FloatRepresentation {
271    fn default() -> Self {
272        Self::PureNumber
273    }
274}
275
276impl Parse for Slope {
277    fn parse(
278        node: &mut xml::Node,
279        _: &mut impl NodeStoreBuilder,
280        _: &mut impl ValueStoreBuilder,
281        _: &mut impl CacheStoreBuilder,
282    ) -> Self {
283        let text = node.next_text().unwrap();
284        match_text_view! {text,
285            "Increasing" => Self::Increasing,
286            "Decreasing" => Self::Decreasing,
287            "Varying" => Self::Varying,
288            "Automatic" => Self::Automatic,
289        }
290    }
291}
292
293impl Default for Slope {
294    fn default() -> Self {
295        Self::Automatic
296    }
297}
298
299impl Default for DisplayNotation {
300    fn default() -> Self {
301        Self::Automatic
302    }
303}
304
305impl Parse for DisplayNotation {
306    fn parse(
307        node: &mut xml::Node,
308        _: &mut impl NodeStoreBuilder,
309        _: &mut impl ValueStoreBuilder,
310        _: &mut impl CacheStoreBuilder,
311    ) -> Self {
312        let text = node.next_text().unwrap();
313        match_text_view! {text,
314            "Automatic" => Self::Automatic,
315            "Fixed" => Self::Fixed,
316            "Scientific" => Self::Scientific,
317        }
318    }
319}
320
321impl From<&str> for StandardNameSpace {
322    fn from(value: &str) -> Self {
323        match value {
324            "None" => Self::None,
325            "IIDC" => Self::IIDC,
326            "GEV" => Self::GEV,
327            "CL" => Self::CL,
328            "USB" => Self::USB,
329            _ => unreachable!(),
330        }
331    }
332}
333
334impl Default for CachingMode {
335    fn default() -> Self {
336        Self::WriteThrough
337    }
338}
339
340impl Parse for CachingMode {
341    fn parse(
342        node: &mut xml::Node,
343        _: &mut impl NodeStoreBuilder,
344        _: &mut impl ValueStoreBuilder,
345        _: &mut impl CacheStoreBuilder,
346    ) -> Self {
347        let text = node.next_text().unwrap();
348        match_text_view! {text,
349            "WriteThrough" => Self::WriteThrough,
350            "WriteAround" => Self::WriteAround,
351            "NoCache" => Self::NoCache,
352        }
353    }
354}
355
356impl<T> Parse for NamedValue<T>
357where
358    T: Clone + PartialEq + Parse,
359{
360    fn parse(
361        node: &mut xml::Node,
362        node_builder: &mut impl NodeStoreBuilder,
363        value_builder: &mut impl ValueStoreBuilder,
364        cache_builder: &mut impl CacheStoreBuilder,
365    ) -> Self {
366        let name = node.peek().unwrap().attribute_of(NAME).unwrap().into();
367        let value = node.parse(node_builder, value_builder, cache_builder);
368        Self { name, value }
369    }
370}
371
372pub(super) fn convert_to_bool(value: &str) -> bool {
373    match convert_to_bool_opt(value) {
374        Some(b) => b,
375        _ => unreachable!(),
376    }
377}
378
379pub(super) fn convert_to_bool_opt(value: &str) -> Option<bool> {
380    match value {
381        "Yes" | "true" => Some(true),
382        "No" | "false" => Some(false),
383        _ => None,
384    }
385}
386
387impl Parse for bool {
388    fn parse(
389        node: &mut xml::Node,
390        _: &mut impl NodeStoreBuilder,
391        _: &mut impl ValueStoreBuilder,
392        _: &mut impl CacheStoreBuilder,
393    ) -> Self {
394        let text = node.next_text().unwrap();
395        convert_to_bool(&text.view())
396    }
397}
398
399pub(super) fn convert_to_int(value: &str) -> i64 {
400    if value.starts_with("0x") || value.starts_with("0X") {
401        i64::from_str_radix(&value[2..], 16).unwrap()
402    } else {
403        value.parse().unwrap()
404    }
405}
406
407pub(super) fn convert_to_uint(value: &str) -> u64 {
408    if value.starts_with("0x") || value.starts_with("0X") {
409        u64::from_str_radix(&value[2..], 16).unwrap()
410    } else {
411        value.parse().unwrap()
412    }
413}
414
415impl Parse for i64 {
416    fn parse(
417        node: &mut xml::Node,
418        _: &mut impl NodeStoreBuilder,
419        _: &mut impl ValueStoreBuilder,
420        _: &mut impl CacheStoreBuilder,
421    ) -> Self {
422        let value = node.next_text().unwrap();
423        convert_to_int(&value.view())
424    }
425}
426
427impl Parse for u64 {
428    fn parse(
429        node: &mut xml::Node,
430        _: &mut impl NodeStoreBuilder,
431        _: &mut impl ValueStoreBuilder,
432        _: &mut impl CacheStoreBuilder,
433    ) -> Self {
434        let value = node.next_text().unwrap();
435        convert_to_uint(&value.view())
436    }
437}
438
439impl Parse for f64 {
440    fn parse(
441        node: &mut xml::Node,
442        _: &mut impl NodeStoreBuilder,
443        _: &mut impl ValueStoreBuilder,
444        _: &mut impl CacheStoreBuilder,
445    ) -> Self {
446        let value = node.next_text().unwrap().view();
447        if value == "INF" {
448            f64::INFINITY
449        } else if value == "-INF" {
450            f64::NEG_INFINITY
451        } else {
452            value.parse().unwrap()
453        }
454    }
455}
456
457impl Parse for String {
458    fn parse(
459        node: &mut xml::Node,
460        _: &mut impl NodeStoreBuilder,
461        _: &mut impl ValueStoreBuilder,
462        _: &mut impl CacheStoreBuilder,
463    ) -> Self {
464        node.next_text().unwrap().view().into()
465    }
466}
467
468impl Parse for NodeId {
469    fn parse(
470        node: &mut xml::Node,
471        node_builder: &mut impl NodeStoreBuilder,
472        _: &mut impl ValueStoreBuilder,
473        _: &mut impl CacheStoreBuilder,
474    ) -> Self {
475        let text = node.next_text().unwrap();
476        node_builder.get_or_intern(text.view())
477    }
478}
479
480macro_rules! impl_parse_for_value_id {
481    ($id:ty, $value_ty:ty) => {
482        impl Parse for $id {
483            fn parse(
484                node: &mut xml::Node,
485                node_builder: &mut impl NodeStoreBuilder,
486                value_builder: &mut impl ValueStoreBuilder,
487                cache_builder: &mut impl CacheStoreBuilder,
488            ) -> Self {
489                let value: $value_ty = node.parse(node_builder, value_builder, cache_builder);
490                let id = value_builder.store(value);
491                id
492            }
493        }
494    };
495}
496
497impl_parse_for_value_id!(IntegerId, i64);
498impl_parse_for_value_id!(FloatId, f64);
499
500impl<T> Parse for ValueKind<T>
501where
502    T: Clone + Parse + PartialEq,
503    ImmOrPNode<T>: Parse,
504{
505    fn parse(
506        node: &mut xml::Node,
507        node_builder: &mut impl NodeStoreBuilder,
508        value_builder: &mut impl ValueStoreBuilder,
509        cache_builder: &mut impl CacheStoreBuilder,
510    ) -> Self {
511        let peek = node.peek().unwrap();
512        match peek.tag_name() {
513            VALUE => ValueKind::Value(node.parse(node_builder, value_builder, cache_builder)),
514            P_VALUE_COPY | P_VALUE => {
515                let p_value = node.parse(node_builder, value_builder, cache_builder);
516                ValueKind::PValue(p_value)
517            }
518            P_INDEX => {
519                let p_index = node.parse(node_builder, value_builder, cache_builder);
520                ValueKind::PIndex(p_index)
521            }
522            _ => unreachable!(),
523        }
524    }
525}
526
527impl<T> Parse for PValue<T> {
528    fn parse(
529        node: &mut xml::Node,
530        node_builder: &mut impl NodeStoreBuilder,
531        value_builder: &mut impl ValueStoreBuilder,
532        cache_builder: &mut impl CacheStoreBuilder,
533    ) -> Self {
534        // NOTE: The pValue can be sandwiched between two pValueCopy sequence.
535        let mut p_value_copies =
536            node.parse_while(P_VALUE_COPY, node_builder, value_builder, cache_builder);
537
538        let p_value = node.parse(node_builder, value_builder, cache_builder);
539
540        let node_ids: Vec<NodeId> =
541            node.parse_while(P_VALUE_COPY, node_builder, value_builder, cache_builder);
542        p_value_copies.extend(node_ids);
543
544        Self {
545            p_value,
546            p_value_copies,
547            phantom: PhantomData,
548        }
549    }
550}
551
552impl<T> Parse for PIndex<T>
553where
554    T: Clone + PartialEq + Parse,
555    ImmOrPNode<T>: Parse,
556{
557    fn parse(
558        node: &mut xml::Node,
559        node_builder: &mut impl NodeStoreBuilder,
560        value_builder: &mut impl ValueStoreBuilder,
561        cache_builder: &mut impl CacheStoreBuilder,
562    ) -> Self {
563        let p_index = node.parse(node_builder, value_builder, cache_builder);
564
565        let mut value_indexed = vec![];
566        while let Some(indexed) = node
567            .parse_if(VALUE_INDEXED, node_builder, value_builder, cache_builder)
568            .or_else(|| node.parse_if(P_VALUE_INDEXED, node_builder, value_builder, cache_builder))
569        {
570            value_indexed.push(indexed);
571        }
572
573        let value_default = node.parse(node_builder, value_builder, cache_builder);
574
575        Self {
576            p_index,
577            value_indexed,
578            value_default,
579        }
580    }
581}
582
583impl<T> Parse for ValueIndexed<T>
584where
585    T: Clone + PartialEq + Parse,
586    ImmOrPNode<T>: Parse,
587{
588    fn parse(
589        node: &mut xml::Node,
590        node_builder: &mut impl NodeStoreBuilder,
591        value_builder: &mut impl ValueStoreBuilder,
592        cache_builder: &mut impl CacheStoreBuilder,
593    ) -> Self {
594        let index = convert_to_int(node.peek().unwrap().attribute_of(INDEX).unwrap());
595        let indexed = node.parse(node_builder, value_builder, cache_builder);
596        Self { index, indexed }
597    }
598}
599
600impl Parse for AddressKind {
601    fn parse(
602        node: &mut xml::Node,
603        node_builder: &mut impl NodeStoreBuilder,
604        value_builder: &mut impl ValueStoreBuilder,
605        cache_builder: &mut impl CacheStoreBuilder,
606    ) -> Self {
607        let peeked_node = node.peek().unwrap();
608        match peeked_node.tag_name() {
609            ADDRESS | P_ADDRESS => {
610                Self::Address(node.parse(node_builder, value_builder, cache_builder))
611            }
612            INT_SWISS_KNIFE => {
613                let swiss_knife: IntSwissKnifeNode =
614                    node.next()
615                        .unwrap()
616                        .parse(node_builder, value_builder, cache_builder);
617                let id = swiss_knife.node_base().id();
618                node_builder.store_node(id, NodeData::IntSwissKnife(swiss_knife.into()));
619                Self::IntSwissKnife(id)
620            }
621            P_INDEX => Self::PIndex(node.parse(node_builder, value_builder, cache_builder)),
622            _ => unreachable!(),
623        }
624    }
625}
626
627impl Parse for RegPIndex {
628    fn parse(
629        node: &mut xml::Node,
630        node_builder: &mut impl NodeStoreBuilder,
631        value_builder: &mut impl ValueStoreBuilder,
632        cache_builder: &mut impl CacheStoreBuilder,
633    ) -> Self {
634        let next_node = node.peek().unwrap();
635
636        let imm_offset = next_node
637            .attribute_of(OFFSET)
638            .map(|s| ImmOrPNode::Imm(convert_to_int(s)));
639        let pnode_offset = next_node
640            .attribute_of(P_OFFSET)
641            .map(|s| ImmOrPNode::PNode(node_builder.get_or_intern(s)));
642        let offset = imm_offset.xor(pnode_offset);
643
644        let p_index = node.parse(node_builder, value_builder, cache_builder);
645
646        Self { offset, p_index }
647    }
648}
649
650impl Default for Endianness {
651    fn default() -> Self {
652        Self::LE
653    }
654}
655
656impl Parse for Endianness {
657    fn parse(
658        node: &mut xml::Node,
659        _: &mut impl NodeStoreBuilder,
660        _: &mut impl ValueStoreBuilder,
661        _: &mut impl CacheStoreBuilder,
662    ) -> Self {
663        let text = node.next_text().unwrap();
664        match_text_view! {text,
665            "LittleEndian" => Self::LE,
666            "BigEndian" => Self::BE,
667        }
668    }
669}
670
671impl Default for Sign {
672    fn default() -> Self {
673        Self::Unsigned
674    }
675}
676
677impl Parse for Sign {
678    fn parse(
679        node: &mut xml::Node,
680        _: &mut impl NodeStoreBuilder,
681        _: &mut impl ValueStoreBuilder,
682        _: &mut impl CacheStoreBuilder,
683    ) -> Self {
684        let text = node.next_text().unwrap();
685        match_text_view! {text,
686            "Signed" => Self::Signed,
687            "Unsigned" => Self::Unsigned,
688        }
689    }
690}
691
692impl Parse for BitMask {
693    fn parse(
694        node: &mut xml::Node,
695        node_builder: &mut impl NodeStoreBuilder,
696        value_builder: &mut impl ValueStoreBuilder,
697        cache_builder: &mut impl CacheStoreBuilder,
698    ) -> Self {
699        node.parse_if(BIT, node_builder, value_builder, cache_builder)
700            .map_or_else(
701                || {
702                    let lsb = node.parse(node_builder, value_builder, cache_builder);
703                    let msb = node.parse(node_builder, value_builder, cache_builder);
704                    Self::Range { lsb, msb }
705                },
706                Self::SingleBit,
707            )
708    }
709}