Expand description
§Extended Piece Identifier Notation (EPIN)
A no_std, unsafe-free implementation of the
EPIN v1.0.0 specification.
EPIN is a strict superset of PIN: 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:
<pin>['] e.g. K r' +K^ -k^'matching the anchored regular expression \A[-+]?[A-Za-z]\^?'?\z. The
anchors apply to the whole input, never to a line within it, so anything
carrying a \r or \n is rejected. The domain is closed and small: 624
tokens, the 312 PIN identifiers taken native and derived. 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 Re-exports) so callers can reach the full PIN
API — including the type returned by Identifier::pin — without declaring
sashite-pin themselves.
§Example
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^'");§Guarantees
no_stdand allocation-free: the parser reads a borrowed slice without copying it, anIdentifieris a 5-byteCopyvalue that borrows nothing, andEncodedEpinholds its at-most-four output bytes in an inline buffer. Nothing touches the heap, and the crate needs noalloc.- No
unsafe: the crate is built under a forbid-unsafelint policy. - Panic-free parsing: every entry point returns a
ParseErrorrather than panicking, for any input — including bytes that are not valid UTF-8. The parser performs no indexing and no arithmetic at all, andtests/conformance.rsexercises it over every byte string up to three bytes, every byte value at every position of a four-byte string, and every Unicode scalar. - 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
serdefeature addsserde(and turns onsashite-pin/serde), and keeps the crateno_std.
§What is, and is not, const
sashite_pin is const end to end — a PIN token can be parsed, checked
and spelled out at compile time. EPIN inherits only part of that:
Identifier::new, every accessor (including Identifier::pin) and the
native / derive /
with_pin transforms are const fn, so a const
PIN core lifts into a const EPIN identifier:
use sashite_epin::{sashite_pin::Identifier as Pin, Identifier};
const CORE: Pin = match Pin::parse("+K^") {
Ok(pin) => pin,
Err(_) => panic!("\"+K^\" is a valid PIN token"),
};
const KING: Identifier = Identifier::new(CORE, true);
const IS_DERIVED: bool = KING.is_derived();Identifier::parse, Identifier::is_valid and Identifier::encode
are not const, so const TOKEN: Identifier = Identifier::parse("+K^'")
does not compile. The obstacles are in the standard library, not in the
design: at this crate’s 1.81 MSRV, parsing may call neither <[u8]>::contains
(the misplaced-marker check) nor a TryFrom implementation (how the core
reaches PIN) from a const fn, and encoding may neither iterate PIN’s
encoded bytes with a for loop nor index the output buffer. Parse at run
time, or build from a const PIN core as above.
Re-exports§
pub use sashite_pin;
Structs§
- Encoded
Epin - The canonical string form of an
Identifier, stored inline. - Identifier
- A parsed EPIN token: a PIN identity plus a native/derived style flag.
- Letter
- The PIN attribute types, re-exported because they appear throughout EPIN’s
own API:
Identifier::letter,Identifier::sideandIdentifier::statereturn them. The single-letter abbreviation of a piece name.
Enums§
- Parse
Error - The reason a string could not be parsed as an EPIN token.
- Side
- The PIN attribute types, re-exported because they appear throughout EPIN’s
own API:
Identifier::letter,Identifier::sideandIdentifier::statereturn them. The camp a piece belongs to. - State
- The PIN attribute types, re-exported because they appear throughout EPIN’s
own API:
Identifier::letter,Identifier::sideandIdentifier::statereturn them. The state of a piece, encoded by the optional+/-prefix.