1use crate::{payload::*, error::NdefError};
2use crate::*;
3use anyhow::anyhow;
4use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
5use std::io::{prelude::*, Cursor};
6
7#[derive(Debug, Clone)]
8pub struct NdefRecord {
9 flags: RecordFlags,
10 tnf: TNF,
12 record_type: Vec<u8>,
14 id: Option<Vec<u8>>,
16 payload: Vec<u8>,
18}
19
20#[allow(dead_code)]
21impl NdefRecord {
22 pub fn builder() -> NdefRecordBuilder {
23 NdefRecordBuilder::new()
24 }
25 pub fn flags(&self) -> RecordFlags {
26 self.flags
27 }
28
29 pub fn tnf(&self) -> TNF {
30 self.tnf
31 }
32
33 pub fn record_type(&self) -> &[u8] {
34 &self.record_type
35 }
36
37 pub fn rtd(&self) -> Option<RTD> {
38 RTD_PRE_DEFINED
39 .iter()
40 .find(|&r| r.0 == self.record_type.as_slice())
41 .copied()
42 }
43
44 pub fn id(&self) -> Option<&[u8]> {
45 self.id.as_deref()
46 }
47
48 pub fn payload(&self) -> &[u8] {
49 &self.payload
50 }
51
52 pub fn clear_begin(&mut self) {
53 self.flags.remove(RecordFlags::MB);
54 }
55
56 pub fn clear_start(&mut self) {
57 self.flags.remove(RecordFlags::ME);
58 }
59
60 pub fn to_buffer(&self, flag: RecordFlags) -> Result<Vec<u8>> {
61 let buffer: Vec<u8> = vec![];
62 let mut output = Cursor::new(buffer);
63 let mut rf = self.flags;
64 if flag & RecordFlags::MB == RecordFlags::MB {
65 rf |= RecordFlags::MB;
66 } else {
67 rf &= !RecordFlags::MB;
68 }
69
70 if flag & RecordFlags::ME == RecordFlags::ME {
71 rf |= RecordFlags::ME;
72 } else {
73 rf &= !RecordFlags::ME;
74 }
75
76 let flag = rf.bits() | ((self.tnf as u8) & 0x07);
77
78 output
79 .write_u8(flag)
80 .map_err(|_| anyhow!("Failed to write flags"))?;
81
82 output
83 .write_u8(self.record_type.len() as u8)
84 .map_err(|_| anyhow!("Failed to write record type length"))?;
85 if self.flags & RecordFlags::SR == RecordFlags::SR {
86 output
87 .write_u8(self.payload.len() as u8)
88 .map_err(|_| anyhow!("Failed to write ID length"))?;
89 } else {
90 output
91 .write_u32::<LittleEndian>(self.payload.len() as u32)
92 .map_err(|_| anyhow!("Failed to write payload length"))?;
93 }
94 if let Some(id) = self.id.as_ref() {
95 output
96 .write_u8((id.len() & 0xff) as u8)
97 .map_err(|_| anyhow!("Failed to write TNF"))?;
98 }
99 output
100 .write_all(&self.record_type)
101 .map_err(|_| anyhow!("Failed to write record type"))?;
102 if let Some(id) = self.id.as_ref() {
103 output
104 .write_all(id)
105 .map_err(|_| anyhow!("Failed to write ID"))?;
106 }
107 output
108 .write_all(&self.payload)
109 .map_err(|_| anyhow!("Failed to write payload"))?;
110 Ok(output.into_inner())
111 }
112
113 pub(crate) fn decode(reader: &mut dyn Read) -> Result<Self> {
114 let flags = reader.read_u8().map_err(|e| anyhow!("read error, {}", e))?;
115 let tnf = TNF::from_repr(flags & 0x0f)
116 .ok_or_else(|| NdefError::InvalidTnf)?;
117 let flags = RecordFlags::from_bits_retain(flags);
118
119 let type_len = reader
120 .read_u8()
121 .map_err(|_| NdefError::InvalidTagLength)?;
122 let payload_len = if flags & RecordFlags::SR == RecordFlags::SR {
123 reader
124 .read_u8()
125 .map_err(|_| NdefError::InvalidPayload)? as u32
126 } else {
127 reader
128 .read_u32::<LittleEndian>()
129 .map_err(|_| NdefError::InvalidPayload)?
130 };
131
132 let id_len = if flags & RecordFlags::IL == RecordFlags::IL {
133 reader
134 .read_u8()
135 .map_err(|_| NdefError::InvalidId)?
136 } else {
137 0
138 };
139
140 let mut record_type = vec![0u8; type_len as usize];
141 reader
142 .read_exact(&mut record_type)
143 .map_err(|_| NdefError::InvalidRecordType)?;
144
145 let id = if id_len > 0 {
146 let mut id = vec![0u8; id_len as usize];
147 reader
148 .read_exact(&mut id)
149 .map_err(|_| NdefError::InvalidId)?;
150 Some(id)
151 } else {
152 None
153 };
154
155 let mut payload = vec![0u8; payload_len as usize];
156 reader
157 .read_exact(&mut payload)
158 .map_err(|_| NdefError::InvalidPayload)?;
159 Ok(Self {
160 flags,
161 tnf,
162 id,
163 record_type,
164 payload,
165 })
166 }
167}
168
169pub struct NdefRecordBuilder {
170 flags: RecordFlags,
171 tnf: TNF,
172 record_type: Vec<u8>,
173 id: Option<Vec<u8>>,
174 payload: Vec<u8>,
175}
176
177impl NdefRecordBuilder {
178 fn new() -> Self {
179 Self {
180 flags: RecordFlags::empty(),
181 tnf: TNF::Empty,
182 record_type: vec![],
183 id: None,
184 payload: vec![],
185 }
186 }
187
188 pub fn id(mut self, id: Vec<u8>) -> Self {
189 if id.is_empty() {
190 return self;
191 }
192 self.id = Some(id);
193 self.flags |= RecordFlags::IL;
194 self
195 }
196
197 pub fn tnf(mut self, tnf: TNF) -> Self {
198 self.tnf = tnf;
199 self
200 }
201
202 pub fn payload<P>(mut self, payload: &P) -> Self
203 where
204 P: RecordPayload,
205 {
206 self.record_type = payload.record_type().to_vec();
207 self.payload = payload.payload().to_vec();
208 if self.payload.len() < 256 {
209 self.flags |= RecordFlags::SR;
210 } else {
211 self.flags &= !RecordFlags::SR;
212 }
213 self
214 }
215
216 pub fn build(self) -> Result<NdefRecord> {
217 if self.tnf == TNF::Empty
218 && (!self.payload.is_empty() || !self.record_type.is_empty() || self.id.is_some())
219 {
220 return Err(anyhow!("Invalid empty record").into());
221 }
222 if self.tnf == TNF::Empty {
223 Ok(NdefRecord {
224 flags: self.flags,
225 tnf: self.tnf,
226 record_type: vec![],
227 id: None,
228 payload: vec![],
229 })
230 } else {
231 if self.record_type.len() > 0xff {
232 return Err(anyhow!("record type too long").into());
233 }
234 if let Some(id) = self.id.as_ref() {
235 if id.len() > 0xff {
236 return Err(anyhow!("record id too long").into());
237 }
238 }
239
240 Ok(NdefRecord {
241 flags: self.flags,
242 tnf: self.tnf,
243 record_type: self.record_type,
244 id: self.id,
245 payload: self.payload,
246 })
247 }
248 }
249}