Expand description
§Field Expression Encoding Notation (FEEN)
A no_std, unsafe-free, allocation-free implementation of the
FEEN v1.0.0 specification, built on
EPIN (piece tokens) and
SIN (style tokens).
FEEN encodes a complete board-game position as three space-separated fields:
<piece-placement> <hands> <style-turn>for example the chess starting position
-rnbqk^bn-r/+p+p+p+p+p+p+p+p/8/8/8/8/+P+P+P+P+P+P+P+P/-RNBQK^BN-R / C/c.
§Allocation-free by design
Unlike a fixed-size token, a position is variable-sized, so this crate is built as a borrowing, streaming validator rather than a parser that returns an owned value:
Feen::parsevalidates an input string in a single pass and returns aFeenview that borrows it — nothing is materialized, nothing is allocated.- The view exposes the geometry (
Feen::shape), the square and piece counts, the active player, and lazy iterators over board squares and hand items. - An owned position is available behind the
allocfeature as asashite_qi::Qi, produced byFeen::to_qi;encodeturns one back into a canonical FEEN string. That conversion is the only part of the crate that allocates.
The default build does not even link the alloc crate.
§Bounds (assumed for safety)
Inputs are bounded before and during parsing, which keeps memory and time bounded even on untrusted input:
- at most
MAX_STRING_LENGTHbytes (checked before any parsing), - at most
MAX_DIMENSIONSboard dimensions, - at most
MAX_DIMENSION_SIZEcells along any dimension, - regular shapes only: every rank within a dimension has the same length.
The last point makes this crate intentionally stricter than the FEEN
specification, which also permits irregular boards: such inputs are rejected
with ParseError::BoardNotRegular.
§Example
use sashite_feen::{Feen, Side};
let feen = Feen::parse("8/8/8/8/8/8/8/8 / C/c")?;
assert_eq!(feen.square_count(), 64);
assert_eq!(feen.piece_count(), 0);
assert_eq!(feen.active_side(), Side::First);
assert!(Feen::is_valid("k^+p4+PK^ / C/c")); // a 1D, 8-square board§Guarantees
no_stdand allocation-free core. Validation and iteration borrow the input; nothing touches the heap unless theallocfeature is used.- No
unsafe, no regex engine. Parsing is a single left-to-right pass over raw bytes, with bounded integer arithmetic. - Built on EPIN and SIN. Piece and style tokens are validated by those crates; FEEN adds only the field, dimensional, canonicality, and cardinality rules.
Re-exports§
pub use sashite_epin;pub use sashite_sin;pub use sashite_qi;
Modules§
- feen_
string - A
#[serde(with = "…")]adapter that (de)serializes aQiposition as its canonical FEEN string. Available with theserdefeature. A#[serde(with = "…")]adapter that (de)serializes asashite_qi::Qiposition as its canonical FEEN string, rather than structurally.
Structs§
- Feen
- A validated FEEN position that borrows its source string.
- Hand
Item - A single item in a player’s hand: a piece together with its multiplicity.
- Hand
Iter - A lazy iterator over the items of one hand.
- Shape
- The shape of a regular board: the size of each of its dimensions.
- Square
Iter - A lazy iterator over board squares in FEEN traversal order.
Enums§
- Parse
Error - The reason a string is not a valid, canonical FEEN position.
- Side
- The two-side model (
First/second) shared across the ecosystem, re-exported fromsashite_sin. Used here for the active player and the hand attribution. The camp a player belongs to.
Constants§
- MAX_
DIMENSIONS - Maximum number of board dimensions (1D, 2D, or 3D).
- MAX_
DIMENSION_ SIZE - Maximum number of cells along any single dimension.
- MAX_
STRING_ LENGTH - Maximum length, in bytes, of a FEEN string.
Functions§
- encode
- Canonical FEEN serialization of an owned
Qiposition. Available with theallocfeature. Encodes an ownedQiposition as its canonical FEEN string. - write_
feen - Canonical FEEN serialization of an owned
Qiposition. Available with theallocfeature. Writes the canonical FEEN string forpositionto afmt::Writesink.