1use std::fmt;
2use std::{io, str::FromStr};
3
4use ahash::HashMap;
5use bstr::BString;
6
7use super::Attribute;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Orientation {
12 Forward,
13 Reverse,
14}
15
16#[derive(Debug, Clone)]
18pub struct OrientedElement {
19 pub id: BString,
20 pub orientation: Option<Orientation>,
21}
22
23impl FromStr for OrientedElement {
24 type Err = io::Error;
25
26 fn from_str(s: &str) -> Result<Self, Self::Err> {
27 if let Some(stripped) = s.strip_suffix('+') {
28 Ok(OrientedElement {
29 id: stripped.into(),
30 orientation: Some(Orientation::Forward),
31 })
32 } else if let Some(stripped) = s.strip_suffix('-') {
33 Ok(OrientedElement {
34 id: stripped.into(),
35 orientation: Some(Orientation::Reverse),
36 })
37 } else {
38 Ok(OrientedElement {
39 id: s.into(),
40 orientation: None,
41 })
42 }
43 }
44}
45
46impl fmt::Display for OrientedElement {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self.orientation {
49 Some(Orientation::Forward) => write!(f, "{}+", self.id),
50 Some(Orientation::Reverse) => write!(f, "{}-", self.id),
51 None => write!(f, "{}", self.id),
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
58pub enum Group {
59 Unordered {
60 id: BString,
61 elements: Vec<BString>,
62 attributes: HashMap<BString, Attribute>,
63 },
64 Ordered {
65 id: BString,
66 elements: Vec<OrientedElement>,
67 attributes: HashMap<BString, Attribute>,
68 },
69 Chain {
70 id: BString,
71 elements: Vec<BString>, attributes: HashMap<BString, Attribute>,
73 },
74}