fugue_fspec/
common.rs

1use std::fmt::Display;
2use std::marker::PhantomData;
3use std::ops::{Deref, Index};
4use std::str::FromStr;
5
6use fugue_arch::ArchitectureDef;
7use fugue_bytes::Endian;
8
9use serde::de::{Error, Visitor};
10use serde::ser::SerializeMap;
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13use thiserror::Error;
14
15#[derive(Clone, Deserialize, Serialize)]
16#[serde(untagged)]
17pub enum OneOrMany<T> {
18    One(T),
19    Many(Vec<T>),
20}
21
22impl<T> Default for OneOrMany<T> {
23    fn default() -> Self {
24        Self::Many(Vec::with_capacity(0))
25    }
26}
27
28impl<T> From<OneOrMany<T>> for Vec<T> {
29    fn from(value: OneOrMany<T>) -> Self {
30        match value {
31            OneOrMany::One(v) => vec![v],
32            OneOrMany::Many(vs) => vs,
33        }
34    }
35}
36
37impl<T> From<Vec<T>> for OneOrMany<T> {
38    fn from(value: Vec<T>) -> Self {
39        if value.len() == 1 {
40            Self::One(value.into_iter().next().unwrap())
41        } else {
42            Self::Many(value)
43        }
44    }
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Hash)]
48pub struct AttrWithVal<A, V> {
49    pub attr: A,
50    pub val: V,
51}
52
53struct AttrWithValVisitor<T, A>(PhantomData<(T, A)>);
54
55impl<T, A> Default for AttrWithValVisitor<T, A> {
56    fn default() -> Self {
57        AttrWithValVisitor(PhantomData)
58    }
59}
60
61impl<'de, A, V> Visitor<'de> for AttrWithValVisitor<A, V>
62where
63    A: FromStr,
64    V: Deserialize<'de>,
65{
66    type Value = AttrWithVal<A, V>;
67
68    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
69        formatter.write_str("attribute/value pair; e.g., key: value")
70    }
71
72    fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
73    where
74        M: serde::de::MapAccess<'de>,
75    {
76        let attr = if let Some(attr) = map.next_key::<String>()?.as_deref() {
77            attr.parse::<A>()
78                .map_err(|_| Error::custom("cannot parse attribute"))?
79        } else {
80            return Err(Error::custom(format!("expected attribute")))?;
81        };
82
83        let val = map.next_value::<V>()?;
84
85        Ok(AttrWithVal { attr, val })
86    }
87}
88
89impl<'de, A, V> Deserialize<'de> for AttrWithVal<A, V>
90where
91    A: FromStr,
92    V: Deserialize<'de>,
93{
94    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95    where
96        D: serde::Deserializer<'de>,
97    {
98        deserializer.deserialize_any(AttrWithValVisitor::default())
99    }
100}
101
102impl<A, V> Serialize for AttrWithVal<A, V>
103where
104    A: ToString,
105    V: Serialize,
106{
107    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108    where
109        S: serde::Serializer,
110    {
111        let mut map = serializer.serialize_map(Some(1))?;
112        map.serialize_entry(&self.attr.to_string(), &self.val)?;
113        map.end()
114    }
115}
116
117#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
118#[serde(
119    bound(deserialize = "A: FromStr, V: Deserialize<'de>"),
120    bound(serialize = "A: ToString, V: Serialize"),
121    untagged
122)]
123pub enum AttrOptWithVal<A, V> {
124    Val(V),
125    AttrWithVal(AttrWithVal<A, V>),
126}
127
128impl<A, V> From<AttrOptWithVal<A, V>> for (A, V)
129where
130    A: Default + FromStr,
131{
132    fn from(v: AttrOptWithVal<A, V>) -> Self {
133        match v {
134            AttrOptWithVal::Val(v) => (Default::default(), v),
135            AttrOptWithVal::AttrWithVal(av) => (av.attr, av.val),
136        }
137    }
138}
139
140#[derive(Debug, Deserialize, PartialEq, Eq, Hash, Serialize)]
141#[serde(
142    bound(deserialize = "A: FromStr, U: Deserialize<'de>, V: Deserialize<'de>"),
143    bound(serialize = "A: ToString, U: Serialize, V: Serialize"),
144    untagged
145)]
146pub enum AttrOptWithValOr<A, U, V>
147where
148    A: FromStr,
149{
150    Val(U),
151    AttrWithVal(AttrWithVal<A, V>),
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
155#[serde(rename_all = "kebab-case")]
156pub enum GroupKind {
157    All,
158    Any,
159    NotAll,
160    NotAny,
161}
162
163impl Default for GroupKind {
164    fn default() -> Self {
165        GroupKind::All
166    }
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Hash)]
170pub struct Group<T> {
171    kind: GroupKind,
172    values: Vec<T>,
173}
174
175impl<T> Group<T> {
176    #[inline]
177    pub fn kind(&self) -> GroupKind {
178        self.kind
179    }
180
181    #[inline]
182    pub fn values(&self) -> &[T] {
183        &self.values
184    }
185}
186
187impl<T> Index<usize> for Group<T> {
188    type Output = T;
189
190    fn index(&self, index: usize) -> &Self::Output {
191        &self.values[index]
192    }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Hash)]
196#[repr(transparent)]
197pub struct Groups<T>(Vec<Group<T>>);
198
199impl<T> Deref for Groups<T> {
200    type Target = Vec<Group<T>>;
201
202    fn deref(&self) -> &Self::Target {
203        &self.0
204    }
205}
206
207impl<T> Index<usize> for Groups<T> {
208    type Output = Group<T>;
209
210    fn index(&self, index: usize) -> &Self::Output {
211        &self.0[index]
212    }
213}
214
215impl<T> Groups<T> {
216    #[inline]
217    pub fn is_empty(&self) -> bool {
218        self.0.is_empty()
219    }
220
221    #[inline]
222    pub fn len(&self) -> usize {
223        self.0.len()
224    }
225
226    #[inline]
227    pub fn iter(&self) -> impl ExactSizeIterator<Item = &Group<T>> {
228        self.0.iter()
229    }
230
231    #[inline]
232    pub fn groups(&self) -> &[Group<T>] {
233        &self.0
234    }
235}
236
237impl<T> Default for Groups<T> {
238    fn default() -> Self {
239        Self(Vec::new())
240    }
241}
242
243struct GroupVisitor<T>(PhantomData<T>);
244
245impl<T> Default for GroupVisitor<T> {
246    fn default() -> Self {
247        GroupVisitor(PhantomData)
248    }
249}
250
251impl<'de, T> Visitor<'de> for GroupVisitor<T>
252where
253    T: Deserialize<'de>,
254{
255    type Value = Groups<T>;
256
257    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
258        formatter.write_str("")
259    }
260
261    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
262    where
263        A: serde::de::SeqAccess<'de>,
264    {
265        let kind = Default::default();
266        let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0));
267
268        while let Some(value) = seq.next_element()? {
269            values.push(value);
270        }
271
272        Ok(Groups(vec![Group { kind, values }]))
273    }
274
275    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
276    where
277        A: serde::de::MapAccess<'de>,
278    {
279        let mut groups = Vec::with_capacity(map.size_hint().unwrap_or(0));
280
281        loop {
282            let mut is_not = false;
283
284            let kind = match map.next_key::<String>()?.as_deref() {
285                Some("and" | "all") => GroupKind::All,
286                Some("any" | "or") => GroupKind::Any,
287                Some("not-all") => GroupKind::NotAll,
288                Some("not-any") => GroupKind::NotAny,
289                Some("not") => {
290                    is_not = true;
291                    GroupKind::NotAny
292                }
293                Some(c) => {
294                    return Err(Error::custom(format!("unknown grouping operator `{c}`")));
295                }
296                None => break,
297            };
298
299            let values = if is_not {
300                vec![map.next_value::<T>()?]
301            } else {
302                map.next_value::<Vec<T>>()?
303            };
304
305            groups.push(Group { kind, values });
306        }
307
308        Ok(Groups(groups))
309    }
310}
311
312impl<'de, T> Deserialize<'de> for Groups<T>
313where
314    T: Deserialize<'de>,
315{
316    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
317    where
318        D: serde::Deserializer<'de>,
319    {
320        deserializer.deserialize_any(GroupVisitor::default())
321    }
322}
323
324impl<T> Serialize for Groups<T>
325where
326    T: Serialize,
327{
328    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
329    where
330        S: Serializer,
331    {
332        let mut map = serializer.serialize_map(Some(self.len()))?;
333
334        for group in self.groups() {
335            map.serialize_entry(&group.kind(), group.values())?;
336        }
337
338        map.end()
339    }
340}
341
342#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
343#[serde(untagged)]
344pub enum GroupOrValue<T> {
345    Group(Groups<GroupOrValue<T>>),
346    Value(T),
347}
348
349pub trait GroupOrValueVisitor<T> {
350    fn matches_value(&self, value: &T) -> bool;
351}
352
353impl<T> GroupOrValue<T> {
354    pub fn matches<V>(&self, visitor: &V) -> bool
355    where
356        V: GroupOrValueVisitor<T>,
357    {
358        match self {
359            Self::Value(t) => visitor.matches_value(t),
360            Self::Group(group) => group.iter().any(|g| match g.kind() {
361                GroupKind::All => g.values().iter().all(|v| v.matches(visitor)),
362                GroupKind::Any => g.values().iter().any(|v| v.matches(visitor)),
363                GroupKind::NotAll => !g.values().iter().all(|v| v.matches(visitor)),
364                GroupKind::NotAny => !g.values().iter().any(|v| v.matches(visitor)),
365            }),
366        }
367    }
368}
369
370#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
371pub struct Language {
372    processor: String,
373    endian: Endian,
374    bits: Option<u32>,
375    variant: Option<String>,
376    convention: Option<String>,
377}
378
379impl Language {
380    pub fn new(processor: impl Into<String>, endian: Endian) -> Self {
381        Self::new_with(processor, endian, None, None, None)
382    }
383
384    pub fn new_with(
385        processor: impl Into<String>,
386        endian: Endian,
387        bits: impl Into<Option<u32>>,
388        variant: impl Into<Option<String>>,
389        convention: impl Into<Option<String>>,
390    ) -> Self {
391        Self {
392            processor: processor.into(),
393            endian,
394            bits: bits.into(),
395            variant: variant.into(),
396            convention: convention.into(),
397        }
398    }
399
400    pub fn matches(&self, other: &Self) -> bool {
401        (other.processor() == self.processor())
402            && (other.endian() == self.endian())
403            && (other.bits().is_none() || self.bits().is_none() || other.bits() == self.bits())
404            && (other.variant().is_none()
405                || self.variant().is_none()
406                || other.variant() == self.variant())
407            && (other.convention().is_none()
408                || self.convention().is_none()
409                || other.convention() == self.convention())
410    }
411
412    pub fn matches_arch(&self, arch: &ArchitectureDef) -> bool {
413        (arch.processor() == self.processor())
414            && (arch.endian() == self.endian())
415            && (self.bits().is_none() || arch.bits() as u32 == self.bits().unwrap())
416            && (self.variant().is_none() || arch.variant() == self.variant().unwrap())
417    }
418
419    pub fn processor(&self) -> &str {
420        &self.processor
421    }
422
423    pub fn endian(&self) -> Endian {
424        self.endian
425    }
426
427    pub fn bits(&self) -> Option<u32> {
428        self.bits
429    }
430
431    pub fn variant(&self) -> Option<&str> {
432        self.variant.as_deref()
433    }
434
435    pub fn convention(&self) -> Option<&str> {
436        self.convention.as_deref()
437    }
438}
439
440#[derive(Debug, Error)]
441pub enum LanguageParseError {
442    #[error("architecture format is invalid")]
443    Format,
444    #[error("invalid architecture processor (should be non-empty string and not '*')")]
445    Processor,
446    #[error("invalid architecture endian (should be LE or BE)")]
447    Endian,
448    #[error("invalid architecture bits (should be numeric or '*')")]
449    Bits,
450    #[error("invalid architecture variant (should be non-empty string or '*')")]
451    Variant,
452    #[error("invalid architecture convention (should be non-empty string or '*')")]
453    Convention,
454}
455
456impl FromStr for Language {
457    type Err = LanguageParseError;
458
459    fn from_str(s: &str) -> Result<Self, Self::Err> {
460        let parts = s.splitn(5, ':').collect::<Vec<_>>();
461        if parts.len() < 3 {
462            return Err(LanguageParseError::Format);
463        }
464
465        let processor = if parts[0] == "*" || parts[0].is_empty() {
466            return Err(LanguageParseError::Processor);
467        } else {
468            parts[0].to_owned()
469        };
470
471        let endian = match parts[1] {
472            "le" | "LE" => Endian::Little,
473            "be" | "BE" => Endian::Big,
474            _ => {
475                return Err(LanguageParseError::Endian);
476            }
477        };
478
479        let bits = if parts[2] == "*" {
480            None
481        } else {
482            match parts[2].parse::<u32>() {
483                Ok(bits) => Some(bits),
484                Err(_) => {
485                    return Err(LanguageParseError::Bits);
486                }
487            }
488        };
489
490        let variant = if parts.len() < 4 || parts[3] == "*" {
491            None
492        } else if parts[3].is_empty() {
493            return Err(LanguageParseError::Variant);
494        } else {
495            Some(parts[3].to_owned())
496        };
497
498        let convention = if parts.len() < 5 || parts[4] == "*" {
499            None
500        } else if parts[4].is_empty() {
501            return Err(LanguageParseError::Convention);
502        } else {
503            Some(parts[4].to_owned())
504        };
505
506        Ok(Language {
507            processor,
508            endian,
509            bits,
510            variant,
511            convention,
512        })
513    }
514}
515
516impl Display for Language {
517    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
518        let endian = match self.endian {
519            Endian::Big => "BE",
520            Endian::Little => "LE",
521        };
522
523        let bits = self
524            .bits
525            .as_ref()
526            .map(|bits| bits as &dyn Display)
527            .unwrap_or_else(|| &"*" as &dyn Display);
528
529        let variant = self.variant.as_deref().unwrap_or("*");
530        let convention = self.convention.as_deref().unwrap_or("*");
531
532        write!(
533            f,
534            "{}:{}:{}:{}:{}",
535            self.processor, endian, bits, variant, convention
536        )
537    }
538}
539
540impl<'de> Deserialize<'de> for Language {
541    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
542    where
543        D: Deserializer<'de>,
544    {
545        let s = String::deserialize(deserializer)?;
546        Language::from_str(&s).map_err(D::Error::custom)
547    }
548}
549
550impl Serialize for Language {
551    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
552    where
553        S: Serializer,
554    {
555        let parts = self.to_string();
556        serializer.serialize_str(&parts)
557    }
558}
559
560#[cfg(test)]
561mod test {
562    use super::*;
563
564    #[test]
565    fn test_basic_groups() -> Result<(), Box<dyn std::error::Error>> {
566        let map1 = r"
567- blah
568- blah1
569- blah2
570";
571        let map2 = r"
572or:
573    - blah
574    - blah1
575    - blah2
576";
577
578        let map3 = r"
579or:
580    - blah
581    - blah1
582    - blah2
583and:
584    - blah4
585";
586
587        let map4 = r"
588or:
589    - not: blah0
590    - blah1
591    - blah2
592not: blah4
593";
594
595        let map5 = r"
596blah
597";
598
599        let map1_group: Groups<String> = serde_yaml::from_str(map1)?;
600
601        assert_eq!(
602            map1_group,
603            Groups(vec![Group {
604                kind: GroupKind::All,
605                values: vec!["blah".to_owned(), "blah1".to_owned(), "blah2".to_owned()],
606            }])
607        );
608
609        let map2_group: Groups<String> = serde_yaml::from_str(map2)?;
610
611        assert_eq!(
612            map2_group,
613            Groups(vec![Group {
614                kind: GroupKind::Any,
615                values: vec!["blah".to_owned(), "blah1".to_owned(), "blah2".to_owned()],
616            }])
617        );
618
619        let map3_group: Groups<String> = serde_yaml::from_str(map3)?;
620
621        assert_eq!(
622            map3_group,
623            Groups(vec![
624                Group {
625                    kind: GroupKind::Any,
626                    values: vec!["blah".to_owned(), "blah1".to_owned(), "blah2".to_owned()],
627                },
628                Group {
629                    kind: GroupKind::All,
630                    values: vec!["blah4".to_owned()],
631                },
632            ]),
633        );
634
635        let map4_group: GroupOrValue<String> = serde_yaml::from_str(map4)?;
636
637        assert_eq!(
638            map4_group,
639            GroupOrValue::Group(Groups(vec![
640                Group {
641                    kind: GroupKind::Any,
642                    values: vec![
643                        GroupOrValue::Group(Groups(vec![Group {
644                            kind: GroupKind::NotAny,
645                            values: vec![GroupOrValue::Value("blah0".to_owned())]
646                        }])),
647                        GroupOrValue::Value("blah1".to_owned()),
648                        GroupOrValue::Value("blah2".to_owned())
649                    ],
650                },
651                Group {
652                    kind: GroupKind::NotAny,
653                    values: vec![GroupOrValue::Value("blah4".to_owned())],
654                },
655            ])),
656        );
657
658        let map5_group: GroupOrValue<String> = serde_yaml::from_str(map5)?;
659
660        assert_eq!(map5_group, GroupOrValue::Value("blah".to_owned()));
661
662        Ok(())
663    }
664}