1use crate::epc::{EPCValue, EPC};
6use crate::error::{ParseError, Result};
7use crate::util::{extract_indicator, read_string, uri_encode, zero_pad};
8use crate::{ApplicationIdentifier, GS1, GTIN};
9use bitreader::BitReader;
10
11#[derive(PartialEq, Debug)]
16pub struct SGTIN96 {
17 pub filter: u8,
19 pub gtin: GTIN,
21 pub serial: u64,
23}
24
25impl EPC for SGTIN96 {
26 fn to_uri(&self) -> String {
28 format!(
29 "urn:epc:id:sgtin:{}.{}{}.{}",
30 zero_pad(self.gtin.company.to_string(), self.gtin.company_digits),
31 self.gtin.indicator,
32 zero_pad(self.gtin.item.to_string(), 12 - self.gtin.company_digits),
33 self.serial
34 )
35 }
36
37 fn to_tag_uri(&self) -> String {
38 format!(
39 "urn:epc:tag:sgtin-96:{}.{}.{}{}.{}",
40 self.filter,
41 zero_pad(self.gtin.company.to_string(), self.gtin.company_digits),
42 self.gtin.indicator,
43 zero_pad(self.gtin.item.to_string(), 12 - self.gtin.company_digits),
44 self.serial
45 )
46 }
47
48 fn get_value(&self) -> EPCValue {
49 EPCValue::SGTIN96(self)
50 }
51}
52
53impl GS1 for SGTIN96 {
54 fn to_gs1(&self) -> String {
55 let gtin_gs1 = self.gtin.to_gs1();
56 format!(
57 "{} ({:0>2}) {}",
58 gtin_gs1,
59 ApplicationIdentifier::SerialNumber as u16,
60 self.serial
61 )
62 }
63}
64
65#[derive(PartialEq, Debug)]
70pub struct SGTIN198 {
71 pub filter: u8,
73 pub gtin: GTIN,
75 pub serial: String,
77}
78
79impl EPC for SGTIN198 {
80 fn to_uri(&self) -> String {
82 format!(
83 "urn:epc:id:sgtin:{}.{}{}.{}",
84 zero_pad(self.gtin.company.to_string(), self.gtin.company_digits),
85 self.gtin.indicator,
86 zero_pad(self.gtin.item.to_string(), 12 - self.gtin.company_digits),
87 uri_encode(self.serial.to_string())
88 )
89 }
90
91 fn to_tag_uri(&self) -> String {
92 format!(
93 "urn:epc:tag:sgtin-198:{}.{}.{}{}.{}",
94 self.filter,
95 zero_pad(self.gtin.company.to_string(), self.gtin.company_digits),
96 self.gtin.indicator,
97 zero_pad(self.gtin.item.to_string(), 12 - self.gtin.company_digits),
98 uri_encode(self.serial.to_string())
99 )
100 }
101
102 fn get_value(&self) -> EPCValue {
103 EPCValue::SGTIN198(self)
104 }
105}
106
107impl GS1 for SGTIN198 {
108 fn to_gs1(&self) -> String {
109 let gtin_gs1 = self.gtin.to_gs1();
110 format!(
111 "{} ({:0>2}) {}",
112 gtin_gs1,
113 ApplicationIdentifier::SerialNumber as u16,
114 self.serial
115 )
116 }
117}
118
119fn company_digits(partition: u8) -> usize {
123 12 - partition as usize
124}
125
126fn item_digits(partition: u8) -> usize {
127 13 - company_digits(partition)
128}
129
130fn partition_bits(partition: u8) -> Result<(u8, u8)> {
132 Ok(match partition {
133 0 => (40, 4),
134 1 => (37, 7),
135 2 => (34, 10),
136 3 => (30, 14),
137 4 => (27, 17),
138 5 => (24, 20),
139 6 => (20, 24),
140 _ => {
141 return Err(Box::new(ParseError()));
142 }
143 })
144}
145
146pub(super) fn decode_sgtin96(data: &[u8]) -> Result<Box<dyn EPC>> {
148 let mut reader = BitReader::new(data);
149
150 let filter = reader.read_u8(3)?;
151 let partition = reader.read_u8(3)?;
152 let (company_bits, item_bits) = partition_bits(partition)?;
153 let company = reader.read_u64(company_bits)?;
154 let item = reader.read_u64(item_bits)?;
155 let (item, indicator) = extract_indicator(item, item_digits(partition))?;
156 let serial = reader.read_u64(38)?;
157
158 Ok(Box::new(SGTIN96 {
159 filter,
160 gtin: GTIN {
161 company,
162 company_digits: company_digits(partition),
163 item,
164 indicator,
165 },
166 serial,
167 }))
168}
169
170pub(super) fn decode_sgtin198(data: &[u8]) -> Result<Box<dyn EPC>> {
172 let mut reader = BitReader::new(data);
173
174 let filter = reader.read_u8(3)?;
175 let partition = reader.read_u8(3)?;
176 let (company_bits, item_bits) = partition_bits(partition)?;
177 let company = reader.read_u64(company_bits)?;
178 let item = reader.read_u64(item_bits)?;
179 let (item, indicator) = extract_indicator(item, item_digits(partition))?;
180 let serial = read_string(reader, 140)?;
181
182 Ok(Box::new(SGTIN198 {
183 filter,
184 gtin: GTIN {
185 company,
186 company_digits: company_digits(partition),
187 item,
188 indicator,
189 },
190 serial,
191 }))
192}