sashite_pin/lib.rs
1//! # Piece Identifier Notation (PIN)
2//!
3//! A `no_std`, `unsafe`-free implementation of the
4//! [PIN v1.0.0 specification](https://sashite.dev/specs/pin/1.0.0/).
5//!
6//! PIN is a compact, ASCII-only token that encodes a piece's identity at the
7//! level of notation. A token has the shape:
8//!
9//! ```text
10//! [<state-modifier>]<abbr>[<terminal-marker>]
11//! ```
12//!
13//! matching the anchored regular expression `^[+-]?[A-Za-z]\^?$`, and maps to
14//! exactly four attributes:
15//!
16//! | Component | Encodes | Values |
17//! |------------------|------------------|-------------------------------------------|
18//! | letter case | [`Side`] | uppercase → `First`, lowercase → `Second` |
19//! | letter | [`Letter`] | the piece-name abbreviation (`A`–`Z`) |
20//! | `+` / `-` prefix | [`State`] | `Enhanced` / `Diminished` (else `Normal`) |
21//! | `^` suffix | terminal status | present → terminal piece |
22//!
23//! PIN standardizes only the *encoding*; the meaning of each attribute is left
24//! to the rule system. See the [glossary](https://sashite.dev/glossary/).
25//!
26//! ## Example
27//!
28//! ```
29//! # fn main() -> Result<(), sashite_pin::ParseError> {
30//! use sashite_pin::{Identifier, Side, State};
31//!
32//! let king: Identifier = "+K^".parse()?;
33//! assert_eq!(king.letter().as_char(), 'K');
34//! assert_eq!(king.side(), Side::First);
35//! assert_eq!(king.state(), State::Enhanced);
36//! assert!(king.is_terminal());
37//!
38//! // Round-trips back to its canonical, zero-allocation string form.
39//! assert_eq!(king.encode().as_str(), "+K^");
40//!
41//! // Cheap, infallible transformations (the type is `Copy`).
42//! assert_eq!(king.flipped().encode().as_str(), "+k^");
43//! # Ok(())
44//! # }
45//! ```
46//!
47//! ## Guarantees
48//!
49//! - **`no_std` and allocation-free:** parsing borrows the input bytes and an
50//! [`Identifier`] is a 4-byte `Copy` value; nothing is heap-allocated.
51//! - **No `unsafe`:** the crate is built under a forbid-`unsafe` lint policy.
52//! - **Bounded, panic-free parsing:** inputs longer than three bytes are
53//! rejected before inspection, and the public parsing API never panics.
54//! - **No required dependencies:** the default build has an empty dependency
55//! graph; the optional `serde` feature adds `serde` (kept `no_std`).
56
57#![no_std]
58
59mod encode;
60mod error;
61mod identifier;
62mod letter;
63mod parse;
64#[cfg(feature = "serde")]
65mod serde_impl;
66mod side;
67mod state;
68
69pub use crate::encode::EncodedPin;
70pub use crate::error::ParseError;
71pub use crate::identifier::Identifier;
72pub use crate::letter::Letter;
73pub use crate::side::Side;
74pub use crate::state::State;