BREAKING CHANGE: deprecate Maze::len() in favor of Maze::count()

This commit is contained in:
Kristofers Solo 2025-01-02 22:07:51 +02:00
parent d66e4c4bb2
commit fae8e91b54
9 changed files with 83 additions and 76 deletions

49
Cargo.lock generated
View File

@ -2014,21 +2014,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
name = "futures"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.31"
@ -2036,7 +2021,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -2045,17 +2029,6 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.31"
@ -2086,12 +2059,6 @@ dependencies = [
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
version = "0.3.31"
@ -2110,13 +2077,9 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
@ -2375,7 +2338,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "hexlab"
version = "0.5.2"
version = "0.5.3"
dependencies = [
"bevy",
"bevy_reflect",
@ -3570,21 +3533,21 @@ checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "rstest"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035"
checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89"
dependencies = [
"futures",
"futures-timer",
"futures-util",
"rstest_macros",
"rustc_version",
]
[[package]]
name = "rstest_macros"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a"
checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b"
dependencies = [
"cfg-if",
"glob",

View File

@ -1,7 +1,7 @@
[package]
name = "hexlab"
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
version = "0.5.2"
version = "0.5.3"
edition = "2021"
description = "A hexagonal maze generation and manipulation library"
repository = "https://github.com/kristoferssolo/hexlab"
@ -36,7 +36,7 @@ features = ["glam"]
[dev-dependencies]
claims = "0.8"
rstest = "0.23"
rstest = "0.24"
[features]
default = []

View File

@ -211,18 +211,18 @@ mod test {
#[case(100, 30301)]
fn create_hex_maze_various_radii(#[case] radius: u16, #[case] expected_size: usize) {
let maze = create_hex_maze(radius);
assert_eq!(maze.len(), expected_size);
assert_eq!(maze.count(), expected_size);
}
#[test]
fn create_hex_maze_large_radius() {
let large_radius = 1000;
let maze = create_hex_maze(large_radius);
assert_gt!(maze.len(), 0);
assert_gt!(maze.count(), 0);
// Calculate expected size for this radius
let expected_size = 3 * (large_radius as usize).pow(2) + 3 * large_radius as usize + 1;
assert_eq!(maze.len(), expected_size);
assert_eq!(maze.count(), expected_size);
}
#[test]

View File

@ -1,6 +1,8 @@
use hexx::Hex;
use hexx::{EdgeDirection, Hex};
use thiserror::Error;
use crate::Tile;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum MazeBuilderError {
/// Occurs when attempting to build a maze without specifying a radius.
@ -18,6 +20,22 @@ pub enum MazeBuilderError {
#[derive(Debug, Error, PartialEq, Eq)]
pub enum MazeError {
/// Error when attempting to access or modify a tile at a non-existent coordinate.
#[error("Invalid coordinate: {0:?}")]
InvalidCoordinate(Hex),
/// Error when a tile's internal position doesn't match its insertion coordinate.
#[error("Tile position ({tile_pos:?}) does not match insertion coordinates ({insert_pos:?})")]
PositionMismatch { tile_pos: Hex, insert_pos: Hex },
/// Error when attempting to insert a tile at an already occupied position.
#[error("A tile {old_tile:?} already exists at position {pos:?}")]
TileAlreadyExists { pos: Hex, old_tile: Tile },
/// Error when a wall operation fails at the specified coordinate and direction.
#[error("Cannot add wall at {coord:?} in direction {direction:?}")]
WallOperationFailed {
coord: Hex,
direction: EdgeDirection,
},
}

View File

@ -106,6 +106,10 @@ mod test {
}
}
}
assert_eq!(connected.len(), maze.len(), "All tiles should be connected");
assert_eq!(
connected.len(),
maze.count(),
"All tiles should be connected"
);
}
}

View File

@ -69,14 +69,7 @@ impl Maze {
self.0.insert(coords, tile)
}
/// Adds a new tile at the specified coordinates.
///
/// If the map did not have this key present, [`None`] is returned.
///
/// If the map did have this key present, the value is updated, and the old
/// value is returned.
///
/// It is recommended to use [`insert`].
/// Adds a new tile at the specified coordinates. It is recommended to use [`insert`].
///
/// [`insert`]: Maze::insert
///
@ -85,21 +78,50 @@ impl Maze {
/// - `coords` - The hexagonal coordinates where the tile should be added.
/// - `tile` - The tile to insert to.
///
/// # Errors
///
/// Returns [`MazeError::PositionMismatch`] if the tile's position doesn't match the insertion coordinates.
/// Returns [`MazeError::TileAlreadyExists`] if a tile already exists at the specified coordinates.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut maze = Maze::new();
/// let coord = Hex::ZERO;
/// let tile1 = Tile::new(coord);
/// let tile2 = Tile::new(Hex::new(1, 1));
///
/// assert_eq!(maze.insert_with_tile(coord, tile1.clone()), None);
/// assert_eq!(maze.insert_with_tile(coord, tile2), Some(tile1));
/// assert_eq!(
/// maze.insert_with_tile(Hex::new(2, 2), Tile::new(Hex::ZERO)),
/// Err(MazeError::PositionMismatch {
/// tile_pos: Hex::ZERO,
/// insert_pos: Hex::new(2, 2)
/// })
/// );
/// let tile = Tile::new(Hex::ZERO);
/// assert_eq!(maze.insert_with_tile(Hex::ZERO, tile.clone()), Ok(tile.clone()));
/// assert_eq!(
/// maze.insert_with_tile(Hex::ZERO, tile.clone()),
/// Err(MazeError::TileAlreadyExists {
/// pos: Hex::ZERO,
/// old_tile: tile
/// })
/// );
/// ```
pub fn insert_with_tile(&mut self, coords: Hex, tile: Tile) -> Option<Tile> {
self.0.insert(coords, tile)
pub fn insert_with_tile(&mut self, coords: Hex, tile: Tile) -> Result<Tile, MazeError> {
if tile.pos != coords {
return Err(MazeError::PositionMismatch {
tile_pos: tile.pos,
insert_pos: coords,
});
}
self.0
.insert(coords, tile.clone())
.map_or(Ok(tile), |old_tile| {
Err(MazeError::TileAlreadyExists {
pos: coords,
old_tile,
})
})
}
/// Returns a reference to the tile at the specified coordinates.
@ -190,17 +212,17 @@ impl Maze {
/// use hexlab::prelude::*;
///
/// let mut maze = Maze::new();
/// assert_eq!(maze.len(), 0);
/// assert_eq!(maze.count(), 0);
///
/// maze.insert(Hex::new(0, 0));
/// assert_eq!(maze.len(), 1);
/// assert_eq!(maze.count(), 1);
///
/// maze.insert(Hex::new(1, -1));
/// assert_eq!(maze.len(), 2);
/// assert_eq!(maze.count(), 2);
/// ```
#[inline]
#[must_use]
pub fn len(&self) -> usize {
pub fn count(&self) -> usize {
self.0.len()
}

View File

@ -10,7 +10,7 @@ use rstest::rstest;
#[case(5, 91)]
fn maze_size(#[case] radius: u16, #[case] expected_size: usize) {
let maze = assert_ok!(MazeBuilder::new().with_radius(radius).build());
assert_eq!(maze.len(), expected_size);
assert_eq!(maze.count(), expected_size);
}
#[test]
@ -126,5 +126,5 @@ fn generate_maze_with_different_types(#[case] generator: GeneratorType) {
.with_generator(generator)
.build());
assert_gt!(maze.len(), 0);
assert_gt!(maze.count(), 0);
}

View File

@ -19,11 +19,11 @@ fn generator_type(
}
}
}
let initial_size = maze.len();
let initial_size = maze.count();
generator.generate(&mut maze, start_pos, seed);
assert_eq!(maze.len(), initial_size, "Maze size should not change");
assert_eq!(maze.count(), initial_size, "Maze size should not change");
// Check maze connectivity
let start = start_pos.unwrap_or(Hex::ZERO);
@ -42,7 +42,7 @@ fn generator_type(
}
}
}
assert_eq!(visited.len(), maze.len(), "All tiles should be connected");
assert_eq!(visited.len(), maze.count(), "All tiles should be connected");
// Check that each tile has at least one open wall
for &pos in maze.keys() {

View File

@ -7,7 +7,7 @@ fn hex_maze_creation_and_basic_operations() {
let center = Hex::ZERO;
maze.insert(center);
assert_eq!(maze.len(), 1);
assert_eq!(maze.count(), 1);
assert!(!maze.is_empty());
let tile = maze.get(&center);
@ -47,7 +47,7 @@ fn hex_maze_multiple_tiles() {
maze.insert(tile);
}
assert_eq!(maze.len(), tiles.len());
assert_eq!(maze.count(), tiles.len());
for &tile in &tiles {
assert!(maze.get(&tile).is_some());