Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map/tests/ways_layer_shared.rs

//! **A `WaysLayer` over a SHARED slab is a view, not a copy** (GFX_V2 shit list #2).
//!
//! korp retains its classified ways and rebuilds the `MapFacet` on every apply; with
//! `WaysLayer::new(id, Vec<Way>)` as the only door, every class layer was a
//! `.cloned()` pass over the whole set. `WaysLayer::shared(id, Arc<[Way]>, range)` is
//! the same `&[Way]` contract over the host's own slab. This test pins the three
//! things that make that true: the layer's slice IS the slab's memory (pointer range),
//! the slab is shared (`Arc::strong_count`), and a shared layer draws exactly what an
//! owned copy of the same range draws (LAW 2: same features, same ids, same order).
//!
//! Seen RED on the code this replaces: `WaysLayer::shared` and `WaySlab` did not
//! exist — the only way to build a layer was to give it an owned `Vec<Way>`.

use std::sync::Arc;

use facett_map::layer::{MapLayer, WaysLayer};
use facett_map::layer::MapView;
use facett_map::Way;

fn some_ways(n: usize) -> Vec<Way> {
    let th = facett_core::Theme::default();
    let mut out = Vec::new();
    for i in 0..n {
        let x = 18.0 + i as f64 * 1e-3;
        let tags = if i % 3 == 0 {
            vec![("building".to_string(), "yes".to_string())]
        } else {
            vec![("highway".to_string(), "residential".to_string())]
        };
        let ring: Vec<(f64, f64)> = if i % 3 == 0 {
            vec![(x, 59.3), (x + 2e-4, 59.3), (x + 2e-4, 59.3002), (x, 59.3002), (x, 59.3)]
        } else {
            vec![(x, 59.31), (x + 5e-4, 59.3105)]
        };
        out.extend(Way::from_lonlat(1000 + i as i64, &ring, &tags, &th));
    }
    out
}

#[test]
fn a_shared_ways_layer_is_a_view_into_the_hosts_slab_not_a_copy() {
    let ways = some_ways(30);
    let n = ways.len();
    let slab: Arc<[Way]> = Arc::from(ways);
    let (a, b) = (0..n / 2, n / 2..n);

    let la = WaysLayer::shared("lower", Arc::clone(&slab), a.clone());
    let lb = WaysLayer::shared("upper", Arc::clone(&slab), b.clone());
    // Shared, not copied: three handles on ONE allocation…
    assert_eq!(Arc::strong_count(&slab), 3);
    // …and each layer's slice lies INSIDE the slab's memory, at its range.
    let slab_ptrs = slab.as_ptr_range();
    for (l, r) in [(&la, &a), (&lb, &b)] {
        let s = l.ways();
        assert_eq!(s.len(), r.len());
        assert!(slab_ptrs.contains(&s.as_ptr()), "{}: the layer's slice is the slab's memory", l.id());
        assert!(std::ptr::eq(s.as_ptr(), slab[r.clone()].as_ptr()), "{}: …at its own range", l.id());
        assert!(Arc::ptr_eq(l.slab().slab(), &slab));
        assert_eq!(l.slab().range(), *r);
        // The GPU lane reads the same slice.
        assert!(std::ptr::eq(l.gpu_ways().expect("ways").as_ptr(), s.as_ptr()));
    }

    // LAW 2: a shared layer draws what an OWNED copy of the same range draws.
    let owned = WaysLayer::new("upper-owned", slab[b.clone()].to_vec());
    let view = MapView { center: facett_map::layer::LatLon::new(59.305, 18.01), zoom: 14.0, bearing_deg: 0.0, tilt_deg: 0.0, size_px: (800.0, 600.0) };
    let f_shared: Vec<i64> = lb.features(&view).iter().map(|f| f.id).collect();
    let f_owned: Vec<i64> = owned.features(&view).iter().map(|f| f.id).collect();
    assert!(!f_owned.is_empty(), "the fixture draws something at this camera");
    assert_eq!(f_shared, f_owned, "same features, same ids, same order");

    // Dropping the layers releases the shares; the host's slab stands.
    drop(la);
    drop(lb);
    assert_eq!(Arc::strong_count(&slab), 1);
}

#[test]
fn a_slab_range_is_clamped_never_out_of_bounds() {
    let slab: Arc<[Way]> = Arc::from(some_ways(5));
    let l = WaysLayer::shared("clamped", Arc::clone(&slab), 3..99);
    assert_eq!(l.ways().len(), slab.len() - 3);
    // The inverted range IS the input under test: `shared` must clamp it to an empty
    // slice instead of panicking. clippy's `reversed_empty_ranges` flags exactly that
    // inversion as a likely bug, which is wrong for this line.
    #[expect(clippy::reversed_empty_ranges, reason = "the inverted range is the input under test")]
    let l = WaysLayer::shared("inverted", Arc::clone(&slab), 9..2);
    assert!(l.ways().is_empty());
}