tauri_plugin_nfc/models.rs
1// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5use serde::{Deserialize, Serialize, Serializer};
6use std::fmt::Display;
7
8/// Arguments of the [`Nfc::scan`](crate::Nfc::scan) API.
9#[derive(Serialize)]
10#[serde(rename_all = "camelCase")]
11pub struct ScanRequest {
12 /// The kind of scan to perform, which defines how tags are matched.
13 pub kind: ScanKind,
14 /// Whether the connection to the scanned tag must be kept open after the scan resolves.
15 ///
16 /// When `true`, a following [`Nfc::write`](crate::Nfc::write) call writes to the tag that was
17 /// scanned instead of starting a new session.
18 pub keep_session_alive: bool,
19}
20
21/// An NDEF record to be written to a tag.
22///
23/// Use [`NFCTypeNameFormat`] to describe how [`Self::kind`] must be interpreted.
24#[derive(Serialize)]
25#[serde(rename_all = "camelCase")]
26pub struct NfcRecord {
27 /// The Type Name Format (TNF) of the record.
28 pub format: NFCTypeNameFormat,
29 /// The record type, interpreted according to [`Self::format`].
30 ///
31 /// For [`NFCTypeNameFormat::NfcWellKnown`] records this is a Record Type Definition (RTD)
32 /// value such as `[0x54]` (`RTD_TEXT`) or `[0x55]` (`RTD_URI`).
33 pub kind: Vec<u8>,
34 /// The record identifier. Can be empty.
35 pub id: Vec<u8>,
36 /// The record payload bytes.
37 pub payload: Vec<u8>,
38}
39
40/// The Type Name Format (TNF) of an NDEF record, which defines how the record type is interpreted.
41///
42/// Serialized as its numeric value.
43#[derive(serde_repr::Deserialize_repr, serde_repr::Serialize_repr)]
44#[repr(u8)]
45pub enum NFCTypeNameFormat {
46 /// The record is empty: type, identifier and payload must be empty.
47 Empty = 0,
48 /// The record type is an NFC Forum well known type, defined by a Record Type Definition (RTD)
49 /// such as `RTD_TEXT` (`[0x54]`) or `RTD_URI` (`[0x55]`).
50 NfcWellKnown = 1,
51 /// The record type is a MIME media type as defined in RFC 2046, e.g. `text/plain`.
52 Media = 2,
53 /// The record type is an absolute URI as defined in RFC 3986.
54 AbsoluteURI = 3,
55 /// The record type is an NFC Forum external type, i.e. a type namespaced by its issuer.
56 NfcExternal = 4,
57 /// The record type is unknown: the type must be empty and the payload interpretation is
58 /// left to the application.
59 Unknown = 5,
60 /// The record is a middle or last chunk of a chunked record and inherits the type of the
61 /// first chunk, so its own type must be empty.
62 Unchanged = 6,
63}
64
65/// An NDEF record read from a scanned tag.
66#[derive(Deserialize)]
67pub struct NfcTagRecord {
68 /// The Type Name Format (TNF) of the record, which defines how [`Self::kind`] is interpreted.
69 pub tnf: NFCTypeNameFormat,
70 /// The record type bytes.
71 pub kind: Vec<u8>,
72 /// The record identifier bytes. Can be empty.
73 pub id: Vec<u8>,
74 /// The record payload bytes.
75 pub payload: Vec<u8>,
76}
77
78/// An NFC tag that has been scanned.
79#[derive(Deserialize)]
80pub struct NfcTag {
81 /// The tag identifier, as reported by the operating system.
82 pub id: String,
83 /// The technology the tag supports.
84 pub kind: String,
85 /// The NDEF records stored on the tag. Empty when the tag holds no NDEF message.
86 pub records: Vec<NfcTagRecord>,
87}
88
89/// Response of the [`Nfc::scan`](crate::Nfc::scan) API.
90#[derive(Deserialize)]
91pub struct ScanResponse {
92 /// The tag that has been scanned.
93 pub tag: NfcTag,
94}
95
96/// Filters the tags to scan by the URI of their NDEF payload.
97///
98/// Every field is optional and only the ones that are set take part in the filter.
99/// **Android only**: the iOS implementation ignores this filter.
100#[derive(Debug, Default, Serialize)]
101pub struct UriFilter {
102 /// Only match URIs with this scheme, e.g. `https`.
103 scheme: Option<String>,
104 /// Only match URIs with this authority (host), e.g. `tauri.app`.
105 host: Option<String>,
106 /// Only match URIs whose path starts with this prefix, e.g. `/docs`.
107 path_prefix: Option<String>,
108}
109
110/// The NFC technologies a tag can support, mirroring the `android.nfc.tech` classes.
111///
112/// **Android only**. Serialized as the technology name, e.g. `"IsoDep"`.
113#[derive(Debug)]
114pub enum TechKind {
115 /// ISO-DEP (ISO 14443-4) properties and I/O operations.
116 IsoDep,
117 /// MIFARE Classic properties and I/O operations.
118 MifareClassic,
119 /// MIFARE Ultralight and MIFARE Ultralight C properties and I/O operations.
120 MifareUltralight,
121 /// NDEF data and operations on tags that are already formatted as NDEF.
122 Ndef,
123 /// Formatting operations on tags that can be formatted as NDEF but are not yet.
124 NdefFormatable,
125 /// NFC-A (ISO 14443-3A) properties and I/O operations.
126 NfcA,
127 /// NFC-B (ISO 14443-3B) properties and I/O operations.
128 NfcB,
129 /// NFC Barcode (Kovio NFC Barcode) properties and I/O operations.
130 NfcBarcode,
131 /// NFC-F (JIS 6319-4) properties and I/O operations.
132 NfcF,
133 /// NFC-V (ISO 15693) properties and I/O operations.
134 NfcV,
135}
136
137impl Display for TechKind {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(
140 f,
141 "{}",
142 match self {
143 Self::IsoDep => "IsoDep",
144 Self::MifareClassic => "MifareClassic",
145 Self::MifareUltralight => "MifareUltralight",
146 Self::Ndef => "Ndef",
147 Self::NdefFormatable => "NdefFormatable",
148 Self::NfcA => "NfcA",
149 Self::NfcB => "NfcB",
150 Self::NfcBarcode => "NfcBarcode",
151 Self::NfcF => "NfcF",
152 Self::NfcV => "NfcV",
153 }
154 )
155 }
156}
157
158impl Serialize for TechKind {
159 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160 where
161 S: Serializer,
162 {
163 serializer.serialize_str(&self.to_string())
164 }
165}
166
167/// The kind of scan to perform, which defines which tags are matched.
168#[derive(Debug, Serialize)]
169#[serde(rename_all = "camelCase")]
170pub enum ScanKind {
171 /// Only match tags that carry an NDEF message.
172 Ndef {
173 /// Only match tags whose NDEF payload has this MIME type, e.g. `text/plain`.
174 /// **Android only**.
175 mime_type: Option<String>,
176 /// Only match tags whose NDEF payload URI matches this filter. **Android only**.
177 uri: Option<UriFilter>,
178 /// Only match tags supporting the listed technologies.
179 ///
180 /// Each tech list is considered independently and the tag matches when any single tech
181 /// list matches it, which provides AND (inside a list) and OR (between lists) semantics.
182 ///
183 /// **Android only**. See
184 /// <https://developer.android.com/reference/android/nfc/NfcAdapter#ACTION_TECH_DISCOVERED>
185 /// for more information.
186 tech_list: Option<Vec<Vec<TechKind>>>,
187 },
188 /// Match any tag that is discovered, whether it carries an NDEF message or not.
189 Tag {
190 /// Only match tags whose payload has this MIME type, e.g. `text/plain`. **Android only**.
191 mime_type: Option<String>,
192 /// Only match tags whose payload URI matches this filter. **Android only**.
193 uri: Option<UriFilter>,
194 },
195}