1use std::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct BtId(
8 pub u16,
10);
11
12impl fmt::Display for BtId {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 write!(f, "BT-{}", self.0)
15 }
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[non_exhaustive]
22pub enum Group {
23 Document,
25 Seller,
27 Buyer,
29 Payee,
31 TaxRepresentative,
33 Delivery,
35 Payment,
37 DocumentAllowance,
39 DocumentCharge,
41 Totals,
43 TaxBreakdown,
45 Attachment,
47 Line,
49}
50
51impl Group {
52 pub fn bg_id(self) -> Option<u16> {
54 Some(match self {
55 Self::Document => return None,
56 Self::Seller => 4,
57 Self::Buyer => 7,
58 Self::Payee => 10,
59 Self::TaxRepresentative => 11,
60 Self::Delivery => 13,
61 Self::Payment => 16,
62 Self::DocumentAllowance => 20,
63 Self::DocumentCharge => 21,
64 Self::Totals => 22,
65 Self::TaxBreakdown => 23,
66 Self::Attachment => 24,
67 Self::Line => 25,
68 })
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub struct Path {
77 pub group: Group,
79 pub index: Option<usize>,
81 pub term: Option<BtId>,
83}
84
85impl Path {
86 pub fn term(term: BtId) -> Self {
88 Self {
89 group: Group::Document,
90 index: None,
91 term: Some(term),
92 }
93 }
94
95 pub fn at_term(group: Group, index: usize, term: BtId) -> Self {
97 Self {
98 group,
99 index: Some(index),
100 term: Some(term),
101 }
102 }
103
104 pub fn group(group: Group) -> Self {
106 Self {
107 group,
108 index: None,
109 term: None,
110 }
111 }
112
113 pub fn group_term(group: Group, term: BtId) -> Self {
115 Self {
116 group,
117 index: None,
118 term: Some(term),
119 }
120 }
121}
122
123impl fmt::Display for Path {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 match (self.group.bg_id(), self.index, self.term) {
126 (None, _, Some(t)) => write!(f, "{t}"),
127 (None, _, None) => write!(f, "Invoice"),
128 (Some(bg), None, None) => write!(f, "BG-{bg}"),
129 (Some(bg), Some(i), None) => write!(f, "BG-{bg}[{i}]"),
130 (Some(bg), None, Some(t)) => write!(f, "BG-{bg}/{t}"),
131 (Some(bg), Some(i), Some(t)) => write!(f, "BG-{bg}[{i}]/{t}"),
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn display_shapes() {
142 assert_eq!(Path::term(BtId(1)).to_string(), "BT-1");
143 assert_eq!(Path::group(Group::Totals).to_string(), "BG-22");
144 assert_eq!(
145 Path {
146 group: Group::Totals,
147 index: None,
148 term: Some(BtId(109))
149 }
150 .to_string(),
151 "BG-22/BT-109"
152 );
153 assert_eq!(Path::group(Group::Line).to_string(), "BG-25");
154 assert_eq!(
155 Path::at_term(Group::Line, 2, BtId(151)).to_string(),
156 "BG-25[2]/BT-151"
157 );
158 }
159}