Skip to main content

sashite_sin/
lib.rs

1//! # Style Identifier Notation (SIN)
2//!
3//! A `no_std`, `unsafe`-free implementation of the
4//! [SIN v1.0.0 specification](https://sashite.dev/specs/sin/1.0.0/).
5//!
6//! SIN is a compact, ASCII-only token that encodes a player's identity — the
7//! pair (player side, player style) — at the level of notation. A token has the
8//! shape:
9//!
10//! ```text
11//! <abbr>
12//! ```
13//!
14//! matching the anchored regular expression `^[A-Za-z]$`, and maps to exactly
15//! two attributes:
16//!
17//! | Component   | Encodes    | Values                                    |
18//! |-------------|------------|-------------------------------------------|
19//! | letter case | [`Side`]   | uppercase → `First`, lowercase → `Second` |
20//! | letter      | [`Letter`] | the player-style abbreviation (`A`–`Z`)   |
21//!
22//! SIN standardizes only the *encoding*; which letter denotes which style is
23//! left to the rule system. See the [glossary](https://sashite.dev/glossary/).
24//!
25//! ## Example
26//!
27//! ```
28//! # fn main() -> Result<(), sashite_sin::ParseError> {
29//! use sashite_sin::{Identifier, Side};
30//!
31//! let western: Identifier = "W".parse()?;
32//! assert_eq!(western.letter().as_char(), 'W');
33//! assert_eq!(western.side(), Side::First);
34//!
35//! // A SIN token is exactly one character.
36//! assert_eq!(western.to_char(), 'W');
37//! assert_eq!(western.encode().as_str(), "W");
38//!
39//! // Cheap, infallible transformations (the type is `Copy`).
40//! assert_eq!(western.flipped().to_char(), 'w');
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! ## Guarantees
46//!
47//! - **`no_std` and allocation-free:** parsing borrows the input bytes and an
48//!   [`Identifier`] is a 2-byte `Copy` value; nothing is heap-allocated.
49//! - **No `unsafe`:** the crate is built under a forbid-`unsafe` lint policy.
50//! - **Bounded, panic-free parsing:** inputs longer than one byte are rejected
51//!   before inspection, and the public parsing API never panics.
52//! - **No required dependencies:** SIN is self-contained, so the default build
53//!   has an empty dependency graph; the optional `serde` feature adds `serde`
54//!   (kept `no_std`).
55
56#![no_std]
57
58mod encode;
59mod error;
60mod identifier;
61mod letter;
62mod parse;
63#[cfg(feature = "serde")]
64mod serde_impl;
65mod side;
66
67pub use crate::encode::EncodedSin;
68pub use crate::error::ParseError;
69pub use crate::identifier::Identifier;
70pub use crate::letter::Letter;
71pub use crate::side::Side;