2 Commits

Author SHA1 Message Date
cmounce d82e05505c Update packages, bump version to 0.2.0 2026-03-18 17:23:39 -07:00
cmounce 3e8bedb0c9 Clean up docs for Program enum, text functions 2026-03-18 17:20:53 -07:00
4 changed files with 54 additions and 29 deletions
Generated
+17 -17
View File
@@ -207,9 +207,9 @@ dependencies = [
[[package]] [[package]]
name = "num_enum" name = "num_enum"
version = "0.7.5" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
dependencies = [ dependencies = [
"num_enum_derive", "num_enum_derive",
"rustversion", "rustversion",
@@ -217,9 +217,9 @@ dependencies = [
[[package]] [[package]]
name = "num_enum_derive" name = "num_enum_derive"
version = "0.7.5" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
dependencies = [ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
@@ -229,9 +229,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.3" version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
@@ -368,9 +368,9 @@ dependencies = [
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.26.0" version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [ dependencies = [
"fastrand", "fastrand",
"getrandom", "getrandom",
@@ -401,18 +401,18 @@ dependencies = [
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "1.0.0+spec-1.1.0" version = "1.0.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
dependencies = [ dependencies = [
"serde_core", "serde_core",
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.25.4+spec-1.1.0" version = "0.25.5+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" checksum = "8ca1a40644a28bce036923f6a431df0b34236949d111cc07cb6dca830c9ef2e1"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"toml_datetime", "toml_datetime",
@@ -422,9 +422,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_parser" name = "toml_parser"
version = "1.0.9+spec-1.1.0" version = "1.0.10+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
dependencies = [ dependencies = [
"winnow", "winnow",
] ]
@@ -583,9 +583,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.7.15" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@@ -686,7 +686,7 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]] [[package]]
name = "zztff" name = "zztff"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"codepage-437", "codepage-437",
"insta", "insta",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "zztff" name = "zztff"
version = "0.1.0" version = "0.2.0"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
description = "Library for reading/writing ZZT worlds and boards" description = "Library for reading/writing ZZT worlds and boards"
+10 -6
View File
@@ -3,7 +3,8 @@ use codepage_437::CP437_WINGDINGS;
use super::errors::EncodeError; use super::errors::EncodeError;
/// Serialize a multi-line code string for an object or a scroll. /// Serialize a multi-line code string for an object or a scroll.
/// Uses ZZT's convention of CR-terminated lines. ///
/// Characters that do not have a CP437 equivalent will result in an [`EncodeError::EncodingError`].
pub fn encode_multiline(input: &str) -> Result<Vec<u8>, EncodeError> { pub fn encode_multiline(input: &str) -> Result<Vec<u8>, EncodeError> {
input input
.chars() .chars()
@@ -33,8 +34,11 @@ pub fn decode_multiline(input: &[u8]) -> String {
.collect() .collect()
} }
/// Serialize a single-line string for a board title. /// Serialize a single-line string, such as a board title.
/// Newlines cannot be encoded because ZZT interprets them as dingbats (♪). ///
/// Newlines cannot be encoded because in single-line contexts, ZZT interprets that byte as a
/// dingbat, specifically the '♪' character. Passing a newline, or any non-CP437 character, will
/// result in an [`EncodeError::EncodingError`].
pub fn encode_oneline(input: &str) -> Result<Vec<u8>, EncodeError> { pub fn encode_oneline(input: &str) -> Result<Vec<u8>, EncodeError> {
input input
.chars() .chars()
@@ -46,7 +50,7 @@ pub fn encode_oneline(input: &str) -> Result<Vec<u8>, EncodeError> {
.collect() .collect()
} }
/// Deserialize a board title. /// Deserialize a single-line string, such as a board title.
pub fn decode_oneline(input: &[u8]) -> String { pub fn decode_oneline(input: &[u8]) -> String {
input.iter().map(|&x| CP437_WINGDINGS.decode(x)).collect() input.iter().map(|&x| CP437_WINGDINGS.decode(x)).collect()
} }
@@ -60,7 +64,7 @@ mod tests {
encode_multiline(input).expect("Error in test") encode_multiline(input).expect("Error in test")
} }
fn serialize_title(input: &str) -> Vec<u8> { fn serialize_line(input: &str) -> Vec<u8> {
encode_oneline(input).expect("Error in test") encode_oneline(input).expect("Error in test")
} }
@@ -73,7 +77,7 @@ mod tests {
#[test] #[test]
fn roundtrip_oneline() { fn roundtrip_oneline() {
let bytes: Vec<u8> = (0..=255).collect(); let bytes: Vec<u8> = (0..=255).collect();
assert_eq!(bytes, serialize_title(&decode_oneline(&bytes))) assert_eq!(bytes, serialize_line(&decode_oneline(&bytes)))
} }
#[test] #[test]
+26 -5
View File
@@ -351,15 +351,36 @@ pub struct Tile {
pub color: u8, pub color: u8,
} }
/// A stat's ZZT-OOP program. /// A stat's ZZT-OOP program text.
/// ///
/// In ZZT, stats can either have their own code or bind to another stat's code. /// Stats must either have their own program or bind to another stat's program. This is either-or:
/// This enum prevents invalid states where both are set. /// in ZZT, it is impossible to represent a stat that has both (or neither). This enum models that
/// constraint.
///
/// Internally, this is because ZZT uses a single `i16` like an enum discriminant. Zero or more
/// indicates the length of the program text, i.e., how many bytes follow the stat on disk. Negative
/// values are interpreted as negated bind indexes: -123 means no program text follows, and that the
/// stat instead shares code with the 123rd stat on the board.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Program { pub enum Program {
/// The stat owns its own code. /// The stat has its own program code.
///
/// This is the typical default for most stats. For stats that don't have or need a program, an
/// empty `String` is used. The text has a maximum of 32767 characters, though in ZZT 3.2 you
/// will encounter other limits before that.
///
/// Despite the name, this has more to do with ZZT's behavior than with Rust ownership.
Own(String), Own(String),
/// The stat is bound to another stat (index into the stats list). /// The stat is bound to the code at the given stat index.
///
/// Bind indexes are 0-based, with the asterisk that zero is not representable due to how ZZT
/// encodes bind indexes. The smallest possible value is 1, which represents being bound to the
/// stat that comes immediately after the player.
///
/// The largest representable bind index is 32768. zztff will successfully serialize this value,
/// though it's only useful as a curiosity and will likely crash ZZT: the index will definitely
/// be out of bounds because it is impossible to serialize a stat list that long without hitting
/// other limits in the file format. Indexes larger than that will result in an [`EncodeError`].
Bound(NonZero<u16>), Bound(NonZero<u16>),
} }