pub struct Letter(/* private fields */);Expand description
The single-letter abbreviation of a player style.
A Letter is the identity part of a SIN token, independent of side. Per
the specification the abbreviation is case-insensitive (C and c denote
the same style), so a Letter is always stored uppercase; the case of the
original token is carried separately by Side.
§Invariant
The wrapped byte is always an uppercase ASCII letter (b'A'..=b'Z'). The
field is private and every constructor enforces the range, so the invariant
cannot be violated from outside the crate.
It is what makes the crate’s arithmetic total. Three places shift a byte by
32 to change case, and each would panic on overflow in a debug build; the
invariant keeps every one of them inside 65..=122, far from either end of
a u8. Nothing in the type system enforces that, so the tests sweep every
public constructor to prove it.
Ordering is alphabetical (A < B < … < Z).
Implementations§
Source§impl Letter
impl Letter
Sourcepub const fn from_ascii(byte: u8) -> Option<(Self, Side)>
pub const fn from_ascii(byte: u8) -> Option<(Self, Side)>
Decodes a raw ASCII byte into a Letter and the Side its case
implies.
Returns None for any byte that is not an ASCII letter. This is the
lossless decoder used by the token parser: the byte it was given can
always be rebuilt from the pair it returns.
Note this takes a byte. Reaching for it with c as u8 on a char
silently truncates to the low eight bits and can turn a non-ASCII
character into a letter that was never there — 'Ł' (U+0141) becomes
0x41, the byte b'A'. Use Letter::try_from_char for a char; it
matches on the character before casting and so cannot be fooled.
§Examples
use sashite_sin::{Letter, Side};
let (letter, side) = Letter::from_ascii(b'c').unwrap();
assert_eq!(letter.as_char(), 'C');
assert_eq!(side, Side::Second);
assert!(Letter::from_ascii(b'1').is_none());
// The `char` door is the safe one for non-ASCII input.
assert!(Letter::try_from_char('\u{0141}').is_err());Sourcepub const fn try_from_char(c: char) -> Result<Self, ParseError>
pub const fn try_from_char(c: char) -> Result<Self, ParseError>
Builds a Letter from a char, folding case.
Both 'C' and 'c' yield the same Letter; the case (which encodes
side) is not retained.
Case folding here is ASCII-only and deliberately so: the range patterns
compare Unicode scalar values, so characters that case-fold to an
ASCII letter — 'ſ' (U+017F), 'K' (U+212A) — are still rejected.
Only the 52 characters the grammar names are abbreviations.
§Errors
Returns ParseError::InvalidLetter if c is not an ASCII letter.
This is the only variant this function can produce: a char has no
length to be wrong about.
§Examples
use sashite_sin::Letter;
assert_eq!(Letter::try_from_char('j').unwrap().as_char(), 'J');
assert!(Letter::try_from_char('+').is_err());
assert!(Letter::try_from_char('\u{017F}').is_err()); // folds to 's'