build(deps): use kasuari instead of cassowary (#1758)

[Kasuari](https://github.com/ratatui/kasuari) is a maintained fork of Cassowary.
This commit is contained in:
Josh McKinney 2025-04-04 00:03:39 -07:00 committed by GitHub
parent ebe10cd81f
commit 3d5b250e74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 76 additions and 72 deletions

56
Cargo.lock generated
View File

@ -354,12 +354,6 @@ dependencies = [
"thiserror 2.0.12", "thiserror 2.0.12",
] ]
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]] [[package]]
name = "cast" name = "cast"
version = "0.3.0" version = "0.3.0"
@ -903,6 +897,16 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "env_logger"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"log",
"regex",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -1651,6 +1655,19 @@ dependencies = [
"simple_asn1", "simple_asn1",
] ]
[[package]]
name = "kasuari"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf4d16f344910446711b7e223a5351073ab8c93dc5c84c5be2c0965346316b1"
dependencies = [
"hashbrown",
"quickcheck",
"quickcheck_macros",
"rstest",
"thiserror 2.0.12",
]
[[package]] [[package]]
name = "lab" name = "lab"
version = "0.11.0" version = "0.11.0"
@ -2325,6 +2342,28 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "quickcheck"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
dependencies = [
"env_logger",
"log",
"rand 0.8.5",
]
[[package]]
name = "quickcheck_macros"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.39" version = "1.0.39"
@ -2436,6 +2475,9 @@ name = "rand_core"
version = "0.6.4" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.15",
]
[[package]] [[package]]
name = "rand_core" name = "rand_core"
@ -2548,12 +2590,12 @@ version = "0.1.0-alpha.3"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"bitflags 2.9.0", "bitflags 2.9.0",
"cassowary",
"compact_str", "compact_str",
"document-features", "document-features",
"hashbrown", "hashbrown",
"indoc", "indoc",
"itertools 0.13.0", "itertools 0.13.0",
"kasuari",
"lru", "lru",
"palette", "palette",
"pretty_assertions", "pretty_assertions",

View File

@ -45,12 +45,12 @@ serde = ["dep:serde", "bitflags/serde", "compact_str/serde"]
[dependencies] [dependencies]
anstyle = { version = "1", optional = true } anstyle = { version = "1", optional = true }
bitflags = "2.3" bitflags = "2.3"
cassowary = "0.3"
compact_str = "0.8.0" compact_str = "0.8.0"
document-features = { workspace = true, optional = true } document-features = { workspace = true, optional = true }
hashbrown = "0.15.2" hashbrown = "0.15.2"
indoc.workspace = true indoc.workspace = true
itertools.workspace = true itertools.workspace = true
kasuari = "0.4.0"
lru = "0.12.0" lru = "0.12.0"
palette = { version = "0.7.6", optional = true } palette = { version = "0.7.6", optional = true }
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }

View File

@ -3,11 +3,10 @@ use core::cell::RefCell;
use core::iter; use core::iter;
use core::num::NonZeroUsize; use core::num::NonZeroUsize;
use cassowary::strength::REQUIRED;
use cassowary::WeightedRelation::{EQ, GE, LE};
use cassowary::{AddConstraintError, Expression, Solver, Variable};
use hashbrown::HashMap; use hashbrown::HashMap;
use itertools::Itertools; use itertools::Itertools;
use kasuari::WeightedRelation::{EQ, GE, LE};
use kasuari::{AddConstraintError, Expression, Solver, Strength, Variable};
use lru::LruCache; use lru::LruCache;
use self::strengths::{ use self::strengths::{
@ -769,8 +768,8 @@ fn configure_area(
area_start: f64, area_start: f64,
area_end: f64, area_end: f64,
) -> Result<(), AddConstraintError> { ) -> Result<(), AddConstraintError> {
solver.add_constraint(area.start | EQ(REQUIRED) | area_start)?; solver.add_constraint(area.start | EQ(Strength::REQUIRED) | area_start)?;
solver.add_constraint(area.end | EQ(REQUIRED) | area_end)?; solver.add_constraint(area.end | EQ(Strength::REQUIRED) | area_end)?;
Ok(()) Ok(())
} }
@ -781,8 +780,8 @@ fn configure_variable_in_area_constraints(
) -> Result<(), AddConstraintError> { ) -> Result<(), AddConstraintError> {
// all variables are in the range [area.start, area.end] // all variables are in the range [area.start, area.end]
for &variable in variables { for &variable in variables {
solver.add_constraint(variable | GE(REQUIRED) | area.start)?; solver.add_constraint(variable | GE(Strength::REQUIRED) | area.start)?;
solver.add_constraint(variable | LE(REQUIRED) | area.end)?; solver.add_constraint(variable | LE(Strength::REQUIRED) | area.end)?;
} }
Ok(()) Ok(())
@ -802,7 +801,7 @@ fn configure_variable_constraints(
// └v0 └v1 └v2 └v3 └v4 └v5 └v6 └v7 // └v0 └v1 └v2 └v3 └v4 └v5 └v6 └v7
for (&left, &right) in variables.iter().skip(1).tuples() { for (&left, &right) in variables.iter().skip(1).tuples() {
solver.add_constraint(left | LE(REQUIRED) | right)?; solver.add_constraint(left | LE(Strength::REQUIRED) | right)?;
} }
Ok(()) Ok(())
} }
@ -1048,24 +1047,24 @@ impl Element {
self.end - self.start self.end - self.start
} }
fn has_max_size(&self, size: u16, strength: f64) -> cassowary::Constraint { fn has_max_size(&self, size: u16, strength: Strength) -> kasuari::Constraint {
self.size() | LE(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER) self.size() | LE(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER)
} }
fn has_min_size(&self, size: i16, strength: f64) -> cassowary::Constraint { fn has_min_size(&self, size: i16, strength: Strength) -> kasuari::Constraint {
self.size() | GE(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER) self.size() | GE(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER)
} }
fn has_int_size(&self, size: u16, strength: f64) -> cassowary::Constraint { fn has_int_size(&self, size: u16, strength: Strength) -> kasuari::Constraint {
self.size() | EQ(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER) self.size() | EQ(strength) | (f64::from(size) * FLOAT_PRECISION_MULTIPLIER)
} }
fn has_size<E: Into<Expression>>(&self, size: E, strength: f64) -> cassowary::Constraint { fn has_size<E: Into<Expression>>(&self, size: E, strength: Strength) -> kasuari::Constraint {
self.size() | EQ(strength) | size.into() self.size() | EQ(strength) | size.into()
} }
fn is_empty(&self) -> cassowary::Constraint { fn is_empty(&self) -> kasuari::Constraint {
self.size() | EQ(REQUIRED - 1.0) | 0.0 self.size() | EQ(Strength::REQUIRED - Strength::WEAK) | 0.0
} }
} }
@ -1084,91 +1083,91 @@ impl From<&Element> for Expression {
} }
mod strengths { mod strengths {
use cassowary::strength::{MEDIUM, REQUIRED, STRONG, WEAK}; use kasuari::Strength;
/// The strength to apply to Spacers to ensure that their sizes are equal. /// The strength to apply to Spacers to ensure that their sizes are equal.
/// ///
/// ┌ ┐┌───┐┌ ┐┌───┐┌ ┐ /// ┌ ┐┌───┐┌ ┐┌───┐┌ ┐
/// ==x │ │ ==x │ │ ==x /// ==x │ │ ==x │ │ ==x
/// └ ┘└───┘└ ┘└───┘└ ┘ /// └ ┘└───┘└ ┘└───┘└ ┘
pub const SPACER_SIZE_EQ: f64 = REQUIRED / 10.0; pub const SPACER_SIZE_EQ: Strength = Strength::REQUIRED.div_f64(10.0);
/// The strength to apply to Min inequality constraints. /// The strength to apply to Min inequality constraints.
/// ///
/// ┌────────┐ /// ┌────────┐
/// │Min(>=x)│ /// │Min(>=x)│
/// └────────┘ /// └────────┘
pub const MIN_SIZE_GE: f64 = STRONG * 100.0; pub const MIN_SIZE_GE: Strength = Strength::STRONG.mul_f64(100.0);
/// The strength to apply to Max inequality constraints. /// The strength to apply to Max inequality constraints.
/// ///
/// ┌────────┐ /// ┌────────┐
/// │Max(<=x)│ /// │Max(<=x)│
/// └────────┘ /// └────────┘
pub const MAX_SIZE_LE: f64 = STRONG * 100.0; pub const MAX_SIZE_LE: Strength = Strength::STRONG.mul_f64(100.0);
/// The strength to apply to Length constraints. /// The strength to apply to Length constraints.
/// ///
/// ┌───────────┐ /// ┌───────────┐
/// │Length(==x)│ /// │Length(==x)│
/// └───────────┘ /// └───────────┘
pub const LENGTH_SIZE_EQ: f64 = STRONG * 10.0; pub const LENGTH_SIZE_EQ: Strength = Strength::STRONG.mul_f64(10.0);
/// The strength to apply to Percentage constraints. /// The strength to apply to Percentage constraints.
/// ///
/// ┌───────────────┐ /// ┌───────────────┐
/// │Percentage(==x)│ /// │Percentage(==x)│
/// └───────────────┘ /// └───────────────┘
pub const PERCENTAGE_SIZE_EQ: f64 = STRONG; pub const PERCENTAGE_SIZE_EQ: Strength = Strength::STRONG;
/// The strength to apply to Ratio constraints. /// The strength to apply to Ratio constraints.
/// ///
/// ┌────────────┐ /// ┌────────────┐
/// │Ratio(==x,y)│ /// │Ratio(==x,y)│
/// └────────────┘ /// └────────────┘
pub const RATIO_SIZE_EQ: f64 = STRONG / 10.0; pub const RATIO_SIZE_EQ: Strength = Strength::STRONG.div_f64(10.0);
/// The strength to apply to Min equality constraints. /// The strength to apply to Min equality constraints.
/// ///
/// ┌────────┐ /// ┌────────┐
/// │Min(==x)│ /// │Min(==x)│
/// └────────┘ /// └────────┘
pub const MIN_SIZE_EQ: f64 = MEDIUM * 10.0; pub const MIN_SIZE_EQ: Strength = Strength::MEDIUM.mul_f64(10.0);
/// The strength to apply to Max equality constraints. /// The strength to apply to Max equality constraints.
/// ///
/// ┌────────┐ /// ┌────────┐
/// │Max(==x)│ /// │Max(==x)│
/// └────────┘ /// └────────┘
pub const MAX_SIZE_EQ: f64 = MEDIUM * 10.0; pub const MAX_SIZE_EQ: Strength = Strength::MEDIUM.mul_f64(10.0);
/// The strength to apply to Fill growing constraints. /// The strength to apply to Fill growing constraints.
/// ///
/// ┌─────────────────────┐ /// ┌─────────────────────┐
/// │<= Fill(x) =>│ /// │<= Fill(x) =>│
/// └─────────────────────┘ /// └─────────────────────┘
pub const FILL_GROW: f64 = MEDIUM; pub const FILL_GROW: Strength = Strength::MEDIUM;
/// The strength to apply to growing constraints. /// The strength to apply to growing constraints.
/// ///
/// ┌────────────┐ /// ┌────────────┐
/// │<= Min(x) =>│ /// │<= Min(x) =>│
/// └────────────┘ /// └────────────┘
pub const GROW: f64 = MEDIUM / 10.0; pub const GROW: Strength = Strength::MEDIUM.div_f64(10.0);
/// The strength to apply to Spacer growing constraints. /// The strength to apply to Spacer growing constraints.
/// ///
/// ┌ ┐ /// ┌ ┐
/// <= x => /// <= x =>
/// └ ┘ /// └ ┘
pub const SPACE_GROW: f64 = WEAK * 10.0; pub const SPACE_GROW: Strength = Strength::WEAK.mul_f64(10.0);
/// The strength to apply to growing the size of all segments equally. /// The strength to apply to growing the size of all segments equally.
/// ///
/// ┌───────┐ /// ┌───────┐
/// │<= x =>│ /// │<= x =>│
/// └───────┘ /// └───────┘
pub const ALL_SEGMENT_GROW: f64 = WEAK; pub const ALL_SEGMENT_GROW: Strength = Strength::WEAK;
} }
#[cfg(test)] #[cfg(test)]
@ -2675,41 +2674,4 @@ mod tests {
assert_eq!(result, expected); assert_eq!(result, expected);
} }
} }
#[test]
fn test_solver() {
use super::*;
let mut solver = Solver::new();
let x = Variable::new();
let y = Variable::new();
solver.add_constraint((x + y) | EQ(4.0) | 5.0).unwrap();
solver.add_constraint(x | EQ(1.0) | 2.0).unwrap();
for _ in 0..5 {
solver.add_constraint(y | EQ(1.0) | 2.0).unwrap();
}
let changes: HashMap<Variable, f64> = solver.fetch_changes().iter().copied().collect();
let x = changes.get(&x).unwrap_or(&0.0).round() as u16;
let y = changes.get(&y).unwrap_or(&0.0).round() as u16;
assert_eq!(x, 3);
assert_eq!(y, 2);
let mut solver = Solver::new();
let x = Variable::new();
let y = Variable::new();
solver.add_constraint((x + y) | EQ(4.0) | 5.0).unwrap();
solver.add_constraint(y | EQ(1.0) | 2.0).unwrap();
for _ in 0..5 {
solver.add_constraint(x | EQ(1.0) | 2.0).unwrap();
}
let changes: HashMap<Variable, f64> = solver.fetch_changes().iter().copied().collect();
let x = changes.get(&x).unwrap_or(&0.0).round() as u16;
let y = changes.get(&y).unwrap_or(&0.0).round() as u16;
assert_eq!(x, 2);
assert_eq!(y, 3);
}
} }