chore: update documentation

This commit is contained in:
Lucas Nogueira
2026-09-22 11:30:47 -03:00
parent d869c162a7
commit a87a3c7d44
104 changed files with 4875 additions and 222 deletions
+9
View File
@@ -4,12 +4,21 @@
use serde::{ser::Serializer, Serialize};
/// Alias for a [`std::result::Result`] with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
/// Errors returned by the NFC plugin.
///
/// Serializes to the error message string, so it can be returned directly from a command.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// An I/O error happened.
#[error(transparent)]
Io(#[from] std::io::Error),
/// The call to the Android or iOS plugin implementation failed,
/// either because the arguments could not be serialized, the response could not be
/// deserialized or the native side rejected the call (e.g. NFC is unavailable
/// or the tag could not be read or written).
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
+38
View File
@@ -2,6 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
//! Read and write NFC tags on Android and iOS.
//!
//! This plugin is mobile only: the whole crate is gated behind `#[cfg(mobile)]`,
//! so it expands to nothing when compiling for Linux, macOS or Windows.
//!
//! Register the plugin with `init` and use the `NfcExt` trait to reach the
//! `Nfc` instance from any `tauri::Manager` implementation (the app handle, a window, ...).
#![cfg(mobile)]
use serde::{Deserialize, Serialize};
@@ -37,6 +45,12 @@ struct WriteRequest {
}
impl<R: Runtime> Nfc<R> {
/// Checks whether NFC is supported by the device and currently usable by the app.
///
/// On Android this is `false` when the device has no NFC adapter or when NFC is
/// disabled in the device settings.
/// On iOS this is `false` when the `NFCReaderUsageDescription` entry is missing from the
/// `Info.plist` file or when NFC tag reading is not available on the device.
pub fn is_available(&self) -> crate::Result<bool> {
self.0
.run_mobile_plugin::<IsAvailableResponse>("isAvailable", ())
@@ -44,6 +58,16 @@ impl<R: Runtime> Nfc<R> {
.map_err(Into::into)
}
/// Scans an NFC tag, blocking until a tag matching the given [`ScanRequest::kind`] filters
/// is read or the scan fails.
///
/// Set [`ScanRequest::keep_session_alive`] to `true` to keep the connection to the tag open
/// after it has been scanned, so that a following [`Self::write`] call writes to that tag.
///
/// # Errors
///
/// Returns an error when NFC is not available (see [`Self::is_available`])
/// or when the tag could not be read.
pub fn scan(&self, payload: ScanRequest) -> crate::Result<ScanResponse> {
self.0
.run_mobile_plugin("scan", payload)
@@ -51,6 +75,19 @@ impl<R: Runtime> Nfc<R> {
.map_err(Into::into)
}
/// Writes the given NDEF records to an NFC tag, blocking until the write completes or fails.
///
/// Because this API does not take a scan kind, on Android it can only write to the tag of an
/// ongoing session, so it must be preceded by a [`Self::scan`] call with
/// [`ScanRequest::keep_session_alive`] set to `true`.
/// On iOS an NDEF reader session is started when there is no ongoing session, and the
/// records are written to the first tag that is scanned.
///
/// # Errors
///
/// Returns an error when NFC is not available (see [`Self::is_available`]), when there is no
/// connected tag on Android, when the tag is read-only, when it cannot hold the message or
/// when it does not support the NDEF format.
pub fn write(&self, records: Vec<NfcRecord>) -> crate::Result<()> {
self.0
.run_mobile_plugin("write", WriteRequest { records })
@@ -60,6 +97,7 @@ impl<R: Runtime> Nfc<R> {
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the NFC APIs.
pub trait NfcExt<R: Runtime> {
/// Returns the [`Nfc`] instance managed by the plugin.
fn nfc(&self) -> &Nfc<R>;
}
+76
View File
@@ -5,72 +5,132 @@
use serde::{Deserialize, Serialize, Serializer};
use std::fmt::Display;
/// Arguments of the [`Nfc::scan`](crate::Nfc::scan) API.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ScanRequest {
/// The kind of scan to perform, which defines how tags are matched.
pub kind: ScanKind,
/// Whether the connection to the scanned tag must be kept open after the scan resolves.
///
/// When `true`, a following [`Nfc::write`](crate::Nfc::write) call writes to the tag that was
/// scanned instead of starting a new session.
pub keep_session_alive: bool,
}
/// An NDEF record to be written to a tag.
///
/// Use [`NFCTypeNameFormat`] to describe how [`Self::kind`] must be interpreted.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NfcRecord {
/// The Type Name Format (TNF) of the record.
pub format: NFCTypeNameFormat,
/// The record type, interpreted according to [`Self::format`].
///
/// For [`NFCTypeNameFormat::NfcWellKnown`] records this is a Record Type Definition (RTD)
/// value such as `[0x54]` (`RTD_TEXT`) or `[0x55]` (`RTD_URI`).
pub kind: Vec<u8>,
/// The record identifier. Can be empty.
pub id: Vec<u8>,
/// The record payload bytes.
pub payload: Vec<u8>,
}
/// The Type Name Format (TNF) of an NDEF record, which defines how the record type is interpreted.
///
/// Serialized as its numeric value.
#[derive(serde_repr::Deserialize_repr, serde_repr::Serialize_repr)]
#[repr(u8)]
pub enum NFCTypeNameFormat {
/// The record is empty: type, identifier and payload must be empty.
Empty = 0,
/// The record type is an NFC Forum well known type, defined by a Record Type Definition (RTD)
/// such as `RTD_TEXT` (`[0x54]`) or `RTD_URI` (`[0x55]`).
NfcWellKnown = 1,
/// The record type is a MIME media type as defined in RFC 2046, e.g. `text/plain`.
Media = 2,
/// The record type is an absolute URI as defined in RFC 3986.
AbsoluteURI = 3,
/// The record type is an NFC Forum external type, i.e. a type namespaced by its issuer.
NfcExternal = 4,
/// The record type is unknown: the type must be empty and the payload interpretation is
/// left to the application.
Unknown = 5,
/// The record is a middle or last chunk of a chunked record and inherits the type of the
/// first chunk, so its own type must be empty.
Unchanged = 6,
}
/// An NDEF record read from a scanned tag.
#[derive(Deserialize)]
pub struct NfcTagRecord {
/// The Type Name Format (TNF) of the record, which defines how [`Self::kind`] is interpreted.
pub tnf: NFCTypeNameFormat,
/// The record type bytes.
pub kind: Vec<u8>,
/// The record identifier bytes. Can be empty.
pub id: Vec<u8>,
/// The record payload bytes.
pub payload: Vec<u8>,
}
/// An NFC tag that has been scanned.
#[derive(Deserialize)]
pub struct NfcTag {
/// The tag identifier, as reported by the operating system.
pub id: String,
/// The technology the tag supports.
pub kind: String,
/// The NDEF records stored on the tag. Empty when the tag holds no NDEF message.
pub records: Vec<NfcTagRecord>,
}
/// Response of the [`Nfc::scan`](crate::Nfc::scan) API.
#[derive(Deserialize)]
pub struct ScanResponse {
/// The tag that has been scanned.
pub tag: NfcTag,
}
/// Filters the tags to scan by the URI of their NDEF payload.
///
/// Every field is optional and only the ones that are set take part in the filter.
/// **Android only**: the iOS implementation ignores this filter.
#[derive(Debug, Default, Serialize)]
pub struct UriFilter {
/// Only match URIs with this scheme, e.g. `https`.
scheme: Option<String>,
/// Only match URIs with this authority (host), e.g. `tauri.app`.
host: Option<String>,
/// Only match URIs whose path starts with this prefix, e.g. `/docs`.
path_prefix: Option<String>,
}
/// The NFC technologies a tag can support, mirroring the `android.nfc.tech` classes.
///
/// **Android only**. Serialized as the technology name, e.g. `"IsoDep"`.
#[derive(Debug)]
pub enum TechKind {
/// ISO-DEP (ISO 14443-4) properties and I/O operations.
IsoDep,
/// MIFARE Classic properties and I/O operations.
MifareClassic,
/// MIFARE Ultralight and MIFARE Ultralight C properties and I/O operations.
MifareUltralight,
/// NDEF data and operations on tags that are already formatted as NDEF.
Ndef,
/// Formatting operations on tags that can be formatted as NDEF but are not yet.
NdefFormatable,
/// NFC-A (ISO 14443-3A) properties and I/O operations.
NfcA,
/// NFC-B (ISO 14443-3B) properties and I/O operations.
NfcB,
/// NFC Barcode (Kovio NFC Barcode) properties and I/O operations.
NfcBarcode,
/// NFC-F (JIS 6319-4) properties and I/O operations.
NfcF,
/// NFC-V (ISO 15693) properties and I/O operations.
NfcV,
}
@@ -104,16 +164,32 @@ impl Serialize for TechKind {
}
}
/// The kind of scan to perform, which defines which tags are matched.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum ScanKind {
/// Only match tags that carry an NDEF message.
Ndef {
/// Only match tags whose NDEF payload has this MIME type, e.g. `text/plain`.
/// **Android only**.
mime_type: Option<String>,
/// Only match tags whose NDEF payload URI matches this filter. **Android only**.
uri: Option<UriFilter>,
/// Only match tags supporting the listed technologies.
///
/// Each tech list is considered independently and the tag matches when any single tech
/// list matches it, which provides AND (inside a list) and OR (between lists) semantics.
///
/// **Android only**. See
/// <https://developer.android.com/reference/android/nfc/NfcAdapter#ACTION_TECH_DISCOVERED>
/// for more information.
tech_list: Option<Vec<Vec<TechKind>>>,
},
/// Match any tag that is discovered, whether it carries an NDEF message or not.
Tag {
/// Only match tags whose payload has this MIME type, e.g. `text/plain`. **Android only**.
mime_type: Option<String>,
/// Only match tags whose payload URI matches this filter. **Android only**.
uri: Option<UriFilter>,
},
}