1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct BtId(pub u16);
6
7impl fmt::Display for BtId {
8 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9 write!(f, "BT-{}", self.0)
10 }
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16#[non_exhaustive]
17pub enum Group {
18 Document,
19 Seller,
20 Buyer,
21 Payee,
22 TaxRepresentative,
23 Delivery,
24 Payment,
25 DocumentAllowance,
26 DocumentCharge,
27 Totals,
28 TaxBreakdown,
30 Attachment,
31 Line,
32}
33
34impl Group {
35 pub fn bg_id(self) -> Option<u16> {
36 Some(match self {
37 Self::Document => return None,
38 Self::Seller => 4,
39 Self::Buyer => 7,
40 Self::Payee => 10,
41 Self::TaxRepresentative => 11,
42 Self::Delivery => 13,
43 Self::Payment => 16,
44 Self::DocumentAllowance => 20,
45 Self::DocumentCharge => 21,
46 Self::Totals => 22,
47 Self::TaxBreakdown => 23,
48 Self::Attachment => 24,
49 Self::Line => 25,
50 })
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55pub struct Path {
56 pub group: Group,
57 pub index: Option<usize>,
58 pub term: Option<BtId>,
59}
60
61impl Path {
62 pub fn term(term: BtId) -> Self {
63 Self {
64 group: Group::Document,
65 index: None,
66 term: Some(term),
67 }
68 }
69
70 pub fn at_term(group: Group, index: usize, term: BtId) -> Self {
71 Self {
72 group,
73 index: Some(index),
74 term: Some(term),
75 }
76 }
77
78 pub fn group(group: Group) -> Self {
79 Self {
80 group,
81 index: None,
82 term: None,
83 }
84 }
85
86 pub fn group_term(group: Group, term: BtId) -> Self {
87 Self {
88 group,
89 index: None,
90 term: Some(term),
91 }
92 }
93}
94
95impl fmt::Display for Path {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 match (self.group.bg_id(), self.index, self.term) {
98 (None, _, Some(t)) => write!(f, "{t}"),
99 (None, _, None) => write!(f, "Invoice"),
100 (Some(bg), None, None) => write!(f, "BG-{bg}"),
101 (Some(bg), Some(i), None) => write!(f, "BG-{bg}[{i}]"),
102 (Some(bg), None, Some(t)) => write!(f, "BG-{bg}/{t}"),
103 (Some(bg), Some(i), Some(t)) => write!(f, "BG-{bg}[{i}]/{t}"),
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn display_shapes() {
114 assert_eq!(Path::term(BtId(1)).to_string(), "BT-1");
115 assert_eq!(Path::group(Group::Totals).to_string(), "BG-22");
116 assert_eq!(
117 Path {
118 group: Group::Totals,
119 index: None,
120 term: Some(BtId(109))
121 }
122 .to_string(),
123 "BG-22/BT-109"
124 );
125 assert_eq!(Path::group(Group::Line).to_string(), "BG-25");
126 assert_eq!(
127 Path::at_term(Group::Line, 2, BtId(151)).to_string(),
128 "BG-25[2]/BT-151"
129 );
130 }
131}