ndef_rs/
record.rs

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    /// The Type Name Format (TNF) field of the record.
11    tnf: TNF,
12    /// The type field of the record.
13    record_type: Vec<u8>,
14    /// The ID field of the record.
15    id: Option<Vec<u8>>,
16    /// The payload field of the record.
17    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}