1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! # Extended Piece Identifier Notation (EPIN)
//!
//! A `no_std`, `unsafe`-free implementation of the
//! [EPIN v1.0.0 specification](https://sashite.dev/specs/epin/1.0.0/).
//!
//! EPIN is a strict superset of [PIN](https://sashite.dev/specs/pin/1.0.0/): it
//! inherits the four PIN attributes (piece name, side, state, terminal status)
//! and adds a single optional trailing marker, the **derivation marker** `'`,
//! which flags whether a piece's style is *native* or *derived*. A token has
//! the shape:
//!
//! ```text
//! <pin>['] e.g. K r' +K^ -k^'
//! ```
//!
//! matching the anchored regular expression `\A[-+]?[A-Za-z]\^?'?\z`. What
//! "native" and "derived" *mean*, and how a concrete style is resolved, is
//! defined by the surrounding context — EPIN encodes only the flag.
//!
//! This crate is a thin layer over [`sashite_pin`]: an [`Identifier`] is a PIN
//! [`sashite_pin::Identifier`] paired with the native/derived flag. The PIN
//! layer is re-exported (see below) so callers can reach the full PIN API —
//! including the type returned by [`Identifier::pin`] — without declaring
//! `sashite-pin` themselves.
//!
//! ## Example
//!
//! ```
//! # fn main() -> Result<(), sashite_epin::ParseError> {
//! use sashite_epin::{Identifier, Side};
//!
//! let king: Identifier = "+K^'".parse()?;
//! assert_eq!(king.letter().as_char(), 'K');
//! assert_eq!(king.side(), Side::First);
//! assert!(king.is_terminal());
//! assert!(king.is_derived());
//!
//! // The underlying PIN token is one method away.
//! assert_eq!(king.pin().encode().as_str(), "+K^");
//!
//! // Native/derived is a single, idempotent flag.
//! assert_eq!(king.native().encode().as_str(), "+K^");
//! assert_eq!(king.encode().as_str(), "+K^'");
//! # Ok(())
//! # }
//! ```
//!
//! ## Guarantees
//!
//! - **`no_std` and allocation-free:** parsing borrows the input bytes and an
//! [`Identifier`] is a small `Copy` value; nothing is heap-allocated.
//! - **No `unsafe`:** the crate is built under a forbid-`unsafe` lint policy.
//! - **Single source of truth:** all PIN-level parsing, validation, and
//! encoding is delegated to [`sashite_pin`]; EPIN only adds the `'` marker.
//! - **No required dependencies beyond PIN:** the optional `serde` feature adds
//! `serde` (and turns on `sashite-pin/serde`), and keeps the crate `no_std`.
pub use EncodedEpin;
pub use ParseError;
pub use Identifier;
// The PIN layer EPIN builds upon is re-exported so downstream users can rely on
// the exact same version without declaring `sashite-pin` themselves. The PIN
// identifier (returned by [`Identifier::pin`]) is reachable as
// `sashite_epin::sashite_pin::Identifier`.
pub use sashite_pin;
pub use ;