pub fn collapse_margins(margins: &[f32]) -> f32 {
let max_positive = margins
.iter()
.copied()
.filter(|&m| m > 0.0)
.fold(0.0_f32, f32::max);
let min_negative = margins
.iter()
.copied()
.filter(|&m| m < 0.0)
.fold(0.0_f32, f32::min);
max_positive + min_negative
}
pub fn sibling_gap(a_bottom: f32, b_top: f32) -> f32 {
collapse_margins(&[a_bottom, b_top])
}
pub fn parent_child_top(parent_top: f32, child_top: f32) -> f32 {
collapse_margins(&[parent_top, child_top])
}
pub fn parent_child_bottom(parent_bottom: f32, child_bottom: f32) -> f32 {
collapse_margins(&[parent_bottom, child_bottom])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn two_positive_take_max() {
assert_eq!(collapse_margins(&[10.0, 20.0]), 20.0);
assert_eq!(collapse_margins(&[20.0, 10.0]), 20.0);
}
#[test]
fn equal_positives_collapse_to_one() {
assert_eq!(collapse_margins(&[15.0, 15.0]), 15.0);
}
#[test]
fn two_negative_take_most_negative() {
assert_eq!(collapse_margins(&[-5.0, -10.0]), -10.0);
}
#[test]
fn mixed_signs_sum_max_positive_and_min_negative() {
assert_eq!(collapse_margins(&[20.0, -5.0]), 15.0);
assert_eq!(collapse_margins(&[10.0, -15.0]), -5.0);
}
#[test]
fn empty_input_zero() {
assert_eq!(collapse_margins(&[]), 0.0);
}
#[test]
fn sibling_gap_collapses_to_max_positive() {
assert_eq!(sibling_gap(20.0, 10.0), 20.0);
assert_eq!(sibling_gap(0.0, 30.0), 30.0);
}
#[test]
fn parent_child_top_collapses() {
assert_eq!(parent_child_top(10.0, 25.0), 25.0);
}
#[test]
fn three_way_collapse_via_collapse_margins() {
assert_eq!(collapse_margins(&[10.0, 5.0, 15.0]), 15.0);
}
}