sokoban-elements 0.2.1

Parsing and writing Sokoban, Hexoban, Trioban and Octoban file formats.
Documentation
#![cfg_attr(doc, doc = include_str!("./lib.rs.md"))]

// Serde rules for this crate, because the `serde` feature is not JSON-only. Compact formats
// (`bincode`, MessagePack, ...) write struct fields *positionally*, with no field names on the
// wire, so anything that makes the field sequence depend on a value's contents produces output the
// same code cannot read back. Banned crate-wide, in every `derive` and every hand-written impl:
//
//   skip_serializing, skip_serializing_if, skip_deserializing, flatten, untagged
//
// `flatten` and `untagged` are doubly disqualified: both buffer through serde's `Content` and need
// a self-describing format, so they break on `bincode` however stable the field sequence is.
//
// `#[serde(default)]` and `deny_unknown_fields` are unaffected and used freely. Nothing enforces
// this - a violation costs nothing under `serde_json` and silently breaks the compact formats.
//
// `deny_unknown_fields` has a placement rule of its own: the three wire-format mirrors below only,
// never on `Puzzle`, `Collection` (`src/puzzle.rs`) or `ReaderSettings` / `WriterSettings`
// (`src/io/settings.rs`), all four of which downstream code may want to flatten into a wrapper of
// its own. `src/puzzle.rs` has the reasoning.
//
// `GameBoard`, `SavedGame` and `SokobanPlus` have private fields with invariants only their
// constructors enforce, so each has a hand-written impl over a private mirror struct at the bottom
// of its file rather than a `derive`; the four ID newtypes use `serde(try_from, into)` so a
// `derive` cannot bypass their bound checks. See also `src/puzzle.rs` on where
// `deny_unknown_fields` may go.

mod board_area;
mod direction;
mod game_board;
mod io;
mod piece;
mod point2d;
mod puzzle;
mod rle;
mod saved_game;
mod size2d;
mod sokoban_plus;
mod static_board_analysis;
mod tessellation;
mod tile;
mod utilities;

pub use board_area::{BoardArea, BoardAreaIntoIter, BoardAreaIter};
pub use direction::{Direction, DirectionsSet, DirectionsSetIter};
pub use game_board::{
    BoardSyntaxError, BoardSyntaxErrorKind, GameBoard, GameBoardIter, HorizontalEdge, MirrorAxis,
    Rotation, VerticalEdge,
};
pub use io::{
    FileFormat, IoReadError, IoReadErrorKind, IoWriteError, ReaderSettings, WriterSettings,
};
pub use piece::{BoxID, Boxbox, Goal, GoalID, PieceIdError, PieceIdErrorKind, Pusher, PusherID};
pub use point2d::Point2D;
pub use puzzle::{Collection, Puzzle};
pub use saved_game::{
    SavedGame, SavedGameSyntaxError, SavedGameSyntaxErrorKind, SolvingMode, Step,
};
pub use size2d::Size2D;
pub use sokoban_plus::{PlusID, SokobanPlus, SokobanPlusSyntaxError, SokobanPlusSyntaxErrorKind};
pub use static_board_analysis::StaticBoardAnalysis;
pub use tessellation::Tessellation;
pub use tile::{TileKind, TileShape};