From 2bbb9fa6adbcaf9abdcf064cf1dd23074ab44ab7 Mon Sep 17 00:00:00 2001 From: Thom van der Woude Date: Thu, 2 Jan 2025 18:11:54 +0100 Subject: [PATCH 1/5] Implemented reuse of fringe and parent map memory allocations using new AstarContext struct --- src/astar_jps.rs | 152 ++++++++++++++++++++++++++++++----------------- src/lib.rs | 14 ++++- 2 files changed, 107 insertions(+), 59 deletions(-) diff --git a/src/astar_jps.rs b/src/astar_jps.rs index 7096fd0..fd4451c 100644 --- a/src/astar_jps.rs +++ b/src/astar_jps.rs @@ -15,6 +15,8 @@ use std::collections::BinaryHeap; use std::hash::Hash; +#[derive(Clone, Debug)] + struct SmallestCostHolder { estimated_cost: K, cost: K, @@ -64,73 +66,111 @@ where path } -pub fn astar_jps( - start: &N, - mut successors: FN, - mut heuristic: FH, - mut success: FS, -) -> Option<(Vec, C)> +/// Represents search fringe and parent map and reusing memory allocations between searches +#[derive(Clone, Debug)] +pub struct AstarContext { + fringe: BinaryHeap>, + parents: FxIndexMap, +} + +impl AstarContext where N: Eq + Hash + Clone, C: Zero + Ord + Copy, - FN: FnMut(&Option<&N>, &N) -> IN, - IN: IntoIterator, - FH: FnMut(&N) -> C, - FS: FnMut(&N) -> bool, { - let mut to_see = BinaryHeap::new(); - to_see.push(SmallestCostHolder { - estimated_cost: Zero::zero(), - cost: Zero::zero(), - index: 0, - }); - let mut parents: FxIndexMap = FxIndexMap::default(); - parents.insert(start.clone(), (usize::MAX, Zero::zero())); - while let Some(SmallestCostHolder { cost, index, .. }) = to_see.pop() { - let successors = { - let (node, &(parent_index, c)) = parents.get_index(index).unwrap(); - if success(node) { - let path = reverse_path(&parents, |&(p, _)| p, index); - return Some((path, cost)); - } - // We may have inserted a node several time into the binary heap if we found - // a better way to access it. Ensure that we are currently dealing with the - // best path and discard the others. - if cost > c { - continue; - } - let optional_parent_node = parents.get_index(parent_index).map(|x| x.0); - - successors(&optional_parent_node, node) - }; - for (successor, move_cost) in successors { - let new_cost = cost + move_cost; - let h; // heuristic(&successor) - let n; // index for successor - match parents.entry(successor) { - Vacant(e) => { - h = heuristic(e.key()); - n = e.index(); - e.insert((index, new_cost)); + pub fn new() -> AstarContext { + AstarContext { + fringe: BinaryHeap::new(), + parents: FxIndexMap::default(), + } + } + pub fn astar_jps( + &mut self, + start: &N, + mut successors: FN, + mut heuristic: FH, + mut success: FS, + ) -> Option<(Vec, C)> + where + FN: FnMut(&Option<&N>, &N) -> IN, + IN: IntoIterator, + FH: FnMut(&N) -> C, + FS: FnMut(&N) -> bool, + { + self.fringe.clear(); + self.parents.clear(); + self.fringe.push(SmallestCostHolder { + estimated_cost: Zero::zero(), + cost: Zero::zero(), + index: 0, + }); + self.parents + .insert(start.clone(), (usize::MAX, Zero::zero())); + while let Some(SmallestCostHolder { cost, index, .. }) = self.fringe.pop() { + let successors = { + let (node, &(parent_index, c)) = self.parents.get_index(index).unwrap(); + if success(node) { + let path = reverse_path(&self.parents, |&(p, _)| p, index); + return Some((path, cost)); } - Occupied(mut e) => { - if e.get().1 > new_cost { + // We may have inserted a node several time into the binary heap if we found + // a better way to access it. Ensure that we are currently dealing with the + // best path and discard the others. + if cost > c { + continue; + } + let optional_parent_node = self.parents.get_index(parent_index).map(|x| x.0); + + successors(&optional_parent_node, node) + }; + for (successor, move_cost) in successors { + let new_cost = cost + move_cost; + let h; // heuristic(&successor) + let n; // index for successor + match self.parents.entry(successor) { + Vacant(e) => { h = heuristic(e.key()); n = e.index(); e.insert((index, new_cost)); - } else { - continue; + } + Occupied(mut e) => { + if e.get().1 > new_cost { + h = heuristic(e.key()); + n = e.index(); + e.insert((index, new_cost)); + } else { + continue; + } } } - } - to_see.push(SmallestCostHolder { - estimated_cost: new_cost + h, - cost: new_cost, - index: n, - }); + self.fringe.push(SmallestCostHolder { + estimated_cost: new_cost + h, + cost: new_cost, + index: n, + }); + } } + warn!("Reachable goal could not be pathed to, is reachable graph correct?"); + None } - warn!("Reachable goal could not be pathed to, is reachable graph correct?"); - None +} + +/// Standalone astar_jps function that creates an [AstarContext] object for backward-compatibility. +pub fn astar_jps( + start: &N, + successors: FN, + heuristic: FH, + success: FS, +) -> Option<(Vec, C)> +where + N: Eq + Hash + Clone, + C: Zero + Ord + Copy, + FN: FnMut(&Option<&N>, &N) -> IN, + IN: IntoIterator, + FH: FnMut(&N) -> C, + FS: FnMut(&N) -> bool, +{ + let mut search = AstarContext::new(); + search.astar_jps(start, successors, heuristic, success) } diff --git a/src/lib.rs b/src/lib.rs index f4c821b..c4aead5 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ //! [connected components](https://en.wikipedia.org/wiki/Component_(graph_theory)) //! to avoid flood-filling behaviour if no path exists. mod astar_jps; +use astar_jps::AstarContext; use grid_util::direction::Direction; use grid_util::grid::{BoolGrid, Grid, SimpleGrid}; use grid_util::point::Point; @@ -15,6 +16,7 @@ use petgraph::unionfind::UnionFind; use crate::astar_jps::astar_jps; use core::fmt; +use std::cell::RefCell; use std::collections::VecDeque; const EQUAL_EDGE_COST: bool = false; @@ -68,6 +70,7 @@ pub struct PathingGrid { pub heuristic_factor: f32, pub improved_pruning: bool, pub allow_diagonal_move: bool, + context: RefCell>, } impl Default for PathingGrid { @@ -80,6 +83,7 @@ impl Default for PathingGrid { improved_pruning: true, heuristic_factor: 1.0, allow_diagonal_move: true, + context: AstarContext::new().into(), } } } @@ -382,7 +386,8 @@ impl PathingGrid { if goals.is_empty() { return None; } - let result = astar_jps( + let mut ct = self.context.borrow_mut(); + let result = ct.astar_jps( &start, |parent, node| { if GRAPH_PRUNING { @@ -417,7 +422,8 @@ impl PathingGrid { return None; } // A neighbour of the goal can be reached, compute a path - astar_jps( + let mut ct = self.context.borrow_mut(); + ct.astar_jps( &start, |parent, node| { if GRAPH_PRUNING { @@ -437,7 +443,8 @@ impl PathingGrid { return None; } // The goal is reachable from the start, compute a path - astar_jps( + let mut ct = self.context.borrow_mut(); + ct.astar_jps( &start, |parent, node| { if GRAPH_PRUNING { @@ -536,6 +543,7 @@ impl Grid for PathingGrid { improved_pruning: true, heuristic_factor: 1.0, allow_diagonal_move: true, + context: AstarContext::new().into(), }; // Emulates 'placing' of blocked tile around map border to correctly initialize neighbours // and make behaviour of a map bordered by tiles the same as a borderless map. From a85e0335620767aa6af7d579ea7f48bccf26f85d Mon Sep 17 00:00:00 2001 From: Thom van der Woude Date: Thu, 2 Jan 2025 21:40:39 +0100 Subject: [PATCH 2/5] Updated neighborhood generation functions to use SmallVec instead of Vec --- Cargo.lock | 9 ++++++++- Cargo.toml | 1 + src/lib.rs | 16 +++++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f95f29e..2104943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -258,6 +258,7 @@ dependencies = [ "num-traits", "petgraph", "rand", + "smallvec", ] [[package]] @@ -685,6 +686,12 @@ dependencies = [ "serde", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "strum" version = "0.20.0" diff --git a/Cargo.toml b/Cargo.toml index 6b25304..31fdd1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ itertools = "0.13" num-traits = "0.2" grid_util = "0.1" log = "0.4" +smallvec = "1.13.2" [lib] bench = false diff --git a/src/lib.rs b/src/lib.rs index c4aead5..c0b321d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ use grid_util::direction::Direction; use grid_util::grid::{BoolGrid, Grid, SimpleGrid}; use grid_util::point::Point; use petgraph::unionfind::UnionFind; +use smallvec::{smallvec, SmallVec}; use crate::astar_jps::astar_jps; use core::fmt; @@ -95,13 +96,13 @@ impl PathingGrid { point.neumann_neighborhood() } } - fn neighborhood_points_and_cost(&self, pos: &Point) -> Vec<(Point, i32)> { + fn neighborhood_points_and_cost(&self, pos: &Point) -> SmallVec<[(Point, i32); 8]> { self.neighborhood_points(pos) .into_iter() .filter(|p| self.can_move_to(*p)) // See comment in pruned_neighborhood about cost calculation .map(move |p| (p, (pos.dir_obj(&p).num() % 2) * (D - C) + C)) - .collect::>() + .collect::>() } /// Uses C as cost for cardinal (straight) moves and D for diagonal moves. pub fn heuristic(&self, p1: &Point, p2: &Point) -> i32 { @@ -266,13 +267,18 @@ impl PathingGrid { } } } - fn jps_neighbours(&self, parent: Option<&Point>, node: &Point, goal: &F) -> Vec<(Point, i32)> + fn jps_neighbours( + &self, + parent: Option<&Point>, + node: &Point, + goal: &F, + ) -> SmallVec<[(Point, i32); 8]> where F: Fn(&Point) -> bool, { match parent { Some(parent_node) => { - let mut succ = vec![]; + let mut succ = SmallVec::new(); let dir = parent_node.dir_obj(node); for (n, c) in self.pruned_neighborhood(dir, node) { let dir = node.dir_obj(&n); @@ -386,7 +392,7 @@ impl PathingGrid { if goals.is_empty() { return None; } - let mut ct = self.context.borrow_mut(); + let mut ct: std::cell::RefMut<'_, AstarContext> = self.context.borrow_mut(); let result = ct.astar_jps( &start, |parent, node| { From 971ce197a55886a36196d603b5bc7d7280d92d05 Mon Sep 17 00:00:00 2001 From: Thom van der Woude Date: Thu, 2 Jan 2025 22:10:59 +0100 Subject: [PATCH 3/5] Introduced N_SMALLVEC_SIZE constant and removed 4-grid from benchmark for now --- benches/comparison_bench.rs | 2 +- src/lib.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/benches/comparison_bench.rs b/benches/comparison_bench.rs index b9d8899..671c35d 100644 --- a/benches/comparison_bench.rs +++ b/benches/comparison_bench.rs @@ -4,7 +4,7 @@ use grid_pathfinding_benchmark::*; use grid_util::grid::Grid; fn dao_bench(c: &mut Criterion) { - for (allow_diag, pruning) in [(false, false), (true, false), (true, true)] { + for (allow_diag, pruning) in [(true, false), (true, true)] { let bench_set = if allow_diag { ["dao/arena", "dao/den312d", "dao/arena2"] } else { diff --git a/src/lib.rs b/src/lib.rs index c0b321d..b9f23df 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ use std::collections::VecDeque; const EQUAL_EDGE_COST: bool = false; const GRAPH_PRUNING: bool = true; +const N_SMALLVEC_SIZE: usize = 8; // Costs for diagonal and cardinal moves. // Values for unequal costs approximating a ratio D/C of sqrt(2) are from @@ -96,13 +97,13 @@ impl PathingGrid { point.neumann_neighborhood() } } - fn neighborhood_points_and_cost(&self, pos: &Point) -> SmallVec<[(Point, i32); 8]> { + fn neighborhood_points_and_cost(&self, pos: &Point) -> SmallVec<[(Point, i32); N_SMALLVEC_SIZE]> { self.neighborhood_points(pos) .into_iter() .filter(|p| self.can_move_to(*p)) // See comment in pruned_neighborhood about cost calculation .map(move |p| (p, (pos.dir_obj(&p).num() % 2) * (D - C) + C)) - .collect::>() + .collect::>() } /// Uses C as cost for cardinal (straight) moves and D for diagonal moves. pub fn heuristic(&self, p1: &Point, p2: &Point) -> i32 { @@ -272,7 +273,7 @@ impl PathingGrid { parent: Option<&Point>, node: &Point, goal: &F, - ) -> SmallVec<[(Point, i32); 8]> + ) -> SmallVec<[(Point, i32); N_SMALLVEC_SIZE]> where F: Fn(&Point) -> bool, { From 16d07e7a6e25fe482f452a5a2ce46d25f002c2b7 Mon Sep 17 00:00:00 2001 From: Thom van der Woude Date: Fri, 3 Jan 2025 11:17:26 +0100 Subject: [PATCH 4/5] Renamed SmallestCostHolder to SearchNode and added some documentation to astar_jps.rs --- src/astar_jps.rs | 20 ++++++++++---------- src/lib.rs | 7 +++++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/astar_jps.rs b/src/astar_jps.rs index fd4451c..c2fc967 100644 --- a/src/astar_jps.rs +++ b/src/astar_jps.rs @@ -17,27 +17,27 @@ use std::hash::Hash; #[derive(Clone, Debug)] -struct SmallestCostHolder { +struct SearchNode { estimated_cost: K, cost: K, index: usize, } -impl Eq for SmallestCostHolder {} +impl Eq for SearchNode {} -impl PartialEq for SmallestCostHolder { +impl PartialEq for SearchNode { fn eq(&self, other: &Self) -> bool { self.estimated_cost.eq(&other.estimated_cost) && self.cost.eq(&other.cost) } } -impl PartialOrd for SmallestCostHolder { +impl PartialOrd for SearchNode { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for SmallestCostHolder { +impl Ord for SearchNode { fn cmp(&self, other: &Self) -> Ordering { // First orders per estimated cost, then creates subordering // based on cost, favoring exploration of smallest cost nodes first @@ -66,10 +66,10 @@ where path } -/// Represents search fringe and parent map and reusing memory allocations between searches +/// [AstarContext] represents the search fringe and node parent map, facilitating reuse of memory allocations. #[derive(Clone, Debug)] pub struct AstarContext { - fringe: BinaryHeap>, + fringe: BinaryHeap>, parents: FxIndexMap, } @@ -99,14 +99,14 @@ where { self.fringe.clear(); self.parents.clear(); - self.fringe.push(SmallestCostHolder { + self.fringe.push(SearchNode { estimated_cost: Zero::zero(), cost: Zero::zero(), index: 0, }); self.parents .insert(start.clone(), (usize::MAX, Zero::zero())); - while let Some(SmallestCostHolder { cost, index, .. }) = self.fringe.pop() { + while let Some(SearchNode { cost, index, .. }) = self.fringe.pop() { let successors = { let (node, &(parent_index, c)) = self.parents.get_index(index).unwrap(); if success(node) { @@ -144,7 +144,7 @@ where } } - self.fringe.push(SmallestCostHolder { + self.fringe.push(SearchNode { estimated_cost: new_cost + h, cost: new_cost, index: n, diff --git a/src/lib.rs b/src/lib.rs index b9f23df..5984eb6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,7 +97,10 @@ impl PathingGrid { point.neumann_neighborhood() } } - fn neighborhood_points_and_cost(&self, pos: &Point) -> SmallVec<[(Point, i32); N_SMALLVEC_SIZE]> { + fn neighborhood_points_and_cost( + &self, + pos: &Point, + ) -> SmallVec<[(Point, i32); N_SMALLVEC_SIZE]> { self.neighborhood_points(pos) .into_iter() .filter(|p| self.can_move_to(*p)) @@ -393,7 +396,7 @@ impl PathingGrid { if goals.is_empty() { return None; } - let mut ct: std::cell::RefMut<'_, AstarContext> = self.context.borrow_mut(); + let mut ct = self.context.borrow_mut(); let result = ct.astar_jps( &start, |parent, node| { From c965a84e23f4e4958745e854966e358da3fdcfeb Mon Sep 17 00:00:00 2001 From: Thom van der Woude Date: Fri, 3 Jan 2025 11:23:15 +0100 Subject: [PATCH 5/5] Ran cargo update --- Cargo.lock | 143 +++++++++++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2104943..222c802 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -156,9 +156,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -187,9 +187,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -252,7 +252,7 @@ dependencies = [ "fxhash", "grid_pathfinding_benchmark", "grid_util", - "indexmap 2.3.0", + "indexmap 2.7.0", "itertools 0.13.0", "log", "num-traits", @@ -305,9 +305,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -339,12 +339,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -367,16 +367,17 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -388,9 +389,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "log" @@ -436,9 +437,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" @@ -459,14 +460,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.3.0", + "indexmap 2.7.0", ] [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -477,15 +478,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -511,9 +512,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -525,14 +526,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79528bef70da112116feb5ecb6b64f1394e5360660d6474a760789ea07885501" dependencies = [ "proc-macro2", - "syn 2.0.72", + "syn 2.0.94", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -576,7 +577,7 @@ dependencies = [ "proc-macro2", "proc_macro2_helper", "quote", - "syn 2.0.72", + "syn 2.0.94", ] [[package]] @@ -601,9 +602,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -613,9 +614,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -624,9 +625,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ron" @@ -656,29 +657,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.94", ] [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -723,9 +724,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" dependencies = [ "proc-macro2", "quote", @@ -760,22 +761,22 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.7.0", "toml_datetime", "winnow", ] [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "walkdir" @@ -795,34 +796,34 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.94", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -830,28 +831,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.94", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -988,5 +989,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.94", ]