1use crate::checksum::gs1_checksum;
3use crate::epc::{EPCValue, EPC};
4use crate::error::{ParseError, Result};
5use crate::util::{extract_indicator, zero_pad};
6use crate::{ApplicationIdentifier, GS1};
7use bitreader::BitReader;
8
9#[derive(PartialEq, Debug)]
11pub struct SSCC96 {
12 pub filter: u8,
14 pub partition: u8,
15 pub indicator: u8,
16 pub company: u64,
17 pub serial: u64,
18}
19
20impl EPC for SSCC96 {
21 fn to_uri(&self) -> String {
23 format!(
24 "urn:epc:id:sscc:{}.{}{}",
25 zero_pad(self.company.to_string(), company_digits(self.partition)),
26 self.indicator,
27 zero_pad(self.serial.to_string(), item_digits(self.partition) - 1)
28 )
29 }
30
31 fn to_tag_uri(&self) -> String {
32 format!(
33 "urn:epc:tag:sscc-96:{}.{}.{}{}",
34 self.filter,
35 zero_pad(self.company.to_string(), company_digits(self.partition)),
36 self.indicator,
37 zero_pad(self.serial.to_string(), item_digits(self.partition) - 1)
38 )
39 }
40
41 fn get_value(&self) -> EPCValue {
42 EPCValue::SSCC96(self)
43 }
44}
45
46impl GS1 for SSCC96 {
47 fn to_gs1(&self) -> String {
48 let element_string = format!(
49 "{}{}{}",
50 self.indicator,
51 zero_pad(self.company.to_string(), company_digits(self.partition)),
52 zero_pad(self.serial.to_string(), item_digits(self.partition) - 1)
53 );
54 format!(
55 "({:0>2}) {}{}",
56 ApplicationIdentifier::SSCC as u16,
57 element_string,
58 gs1_checksum(&element_string)
59 )
60 }
61}
62
63fn company_digits(partition: u8) -> usize {
67 12 - partition as usize
68}
69
70fn item_digits(partition: u8) -> usize {
71 17 - company_digits(partition)
72}
73
74fn partition_bits(partition: u8) -> Result<(u8, u8)> {
76 Ok(match partition {
77 0 => (40, 18),
78 1 => (37, 21),
79 2 => (34, 24),
80 3 => (30, 28),
81 4 => (27, 31),
82 5 => (24, 34),
83 6 => (20, 48),
84 _ => {
85 return Err(Box::new(ParseError()));
86 }
87 })
88}
89
90pub(super) fn decode_sscc96(data: &[u8]) -> Result<Box<dyn EPC>> {
92 let mut reader = BitReader::new(data);
93
94 let filter = reader.read_u8(3)?;
95 let partition = reader.read_u8(3)?;
96 let (company_bits, serial_bits) = partition_bits(partition)?;
97 let company = reader.read_u64(company_bits)?;
98 let serial = reader.read_u64(serial_bits)?;
99 let (serial, indicator) = extract_indicator(serial, item_digits(partition))?;
100
101 Ok(Box::new(SSCC96 {
102 filter,
103 partition,
104 indicator,
105 company,
106 serial,
107 }))
108}