open-standards/map/map-rs/crates/map-cascade/src/lib.rs
Transaction Science ba1212361f Add aac, map, sandbox standards; catalog the standards family
Commit the previously-untracked standard directories and catalog them in the
root README alongside proof:

- aac/    — communication cargo class: portable boards + a ten-level
            offline-first cascade (Apache-2.0 code / CC-BY-4.0 spec).
- map/    — geospatial cargo class: range-requestable signed tilesets +
            an F0–F4 fidelity cascade (Apache-2.0 code / CC-BY-4.0 spec).
- sandbox/— isolated, metered, attested execution across the heterogeneous
            compute fabric (Apache-2.0 code / CC-BY-4.0 spec).
- jouleclaw-otel-authz, jouleclaw-trust — new jouleclaw reference crates.

Root README now lists aac, map, sandbox, and proof in the catalog, the tree,
and the contribution guide.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-07 17:04:36 -04:00

157 lines
6 KiB
Rust

//! The Map fidelity cascade (SPEC §1.2).
//!
//! A render request for a [`CellKey`] declares a *requested fidelity* — a
//! ceiling. The resolver returns the **highest tier at or below that ceiling
//! that holds data for the cell**, short-circuiting on a cache hit (F0) and
//! falling back toward the F1 base floor, which the standard requires to be
//! defined everywhere on the datum. The shared family invariant holds: stop at
//! the first tier that closes the request, and record it.
//!
//! The cascade is pure: it depends only on [`map_schema`] and a [`TileSource`]
//! the caller supplies. Building the energy receipt for the closing tier is the
//! caller's job (see `map-receipt`), keeping metering and resolution separate.
use map_schema::{CellKey, ContentId, Tier};
/// What a resolver can ask of a tile store. Implementations back this with a
/// tileset directory, an OPFS cache, a live entity feed, etc.
pub trait TileSource {
/// Is the cell already resolved in the local store (the F0 short-circuit)?
/// Returns the cached tile's content id.
fn cached(&self, cell: &CellKey) -> Option<ContentId>;
/// Does `tier` hold data for `cell`? Returns the tile's content id if so.
///
/// A conforming source MUST return `Some` for [`Tier::Base`] for any cell on
/// the datum — the floor that makes graceful fallback a property of the
/// standard (SPEC §1.2).
fn tile(&self, cell: &CellKey, tier: Tier) -> Option<ContentId>;
}
/// The outcome of resolving a render request.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Resolution {
/// The tier that closed the request.
pub tier: Tier,
/// The content id of the tile that closed it.
pub content_id: ContentId,
/// Whether the resolver fell back below the requested fidelity (true when a
/// higher tier was requested but absent for this cell).
pub fell_back: bool,
}
#[derive(Debug, thiserror::Error)]
pub enum CascadeError {
/// The source violated SPEC §1.2: not even the F1 base floor was present for
/// a cell the source was asked to cover.
#[error("uncovered region: no F1 base tile for the requested cell")]
UncoveredRegion,
}
/// The fidelity ladder, descending (excludes the F0 cache short-circuit, which
/// is handled separately). A request walks this filtered to tiers at or below
/// the ceiling, taking the first that holds data.
const LADDER_DESC: [Tier; 4] = [Tier::Photoreal, Tier::Feature, Tier::Field, Tier::Base];
/// Resolve a render request (SPEC §1.2).
///
/// `requested` is the fidelity ceiling. A request below [`Tier::Base`] (i.e.
/// `Cache`) is clamped to `Base`, since `Cache` is a short-circuit, not a
/// fidelity a caller targets.
pub fn resolve(
source: &dyn TileSource,
cell: &CellKey,
requested: Tier,
) -> Result<Resolution, CascadeError> {
// F0 — cache short-circuit. Cheapest tier; closes any previously-resolved cell.
if let Some(content_id) = source.cached(cell) {
return Ok(Resolution { tier: Tier::Cache, content_id, fell_back: false });
}
let ceiling = requested.rank().max(Tier::Base.rank());
// Walk the ladder from the ceiling downward; first tier with data wins.
for tier in LADDER_DESC {
if tier.rank() > ceiling {
continue; // MUST NOT return a tier above the request.
}
if let Some(content_id) = source.tile(cell, tier) {
return Ok(Resolution {
tier,
content_id,
fell_back: tier.rank() < ceiling,
});
}
}
// The floor is required to be defined everywhere; absence is a source bug.
Err(CascadeError::UncoveredRegion)
}
#[cfg(test)]
mod tests {
use super::*;
use map_schema::{AltBand, Lod, S2CellId, TimeBucket};
use std::collections::HashMap;
fn cell(s2: u64) -> CellKey {
CellKey { s2: S2CellId(s2), alt: AltBand(0), time: TimeBucket::ATEMPORAL, lod: Lod(0) }
}
/// A source described by which tiers each cell holds, plus a cache set.
#[derive(Default)]
struct Mock {
present: HashMap<u64, Vec<Tier>>,
cache: Vec<u64>,
}
impl TileSource for Mock {
fn cached(&self, c: &CellKey) -> Option<ContentId> {
self.cache.contains(&c.s2.0).then(|| ContentId::of_bytes(b"cached"))
}
fn tile(&self, c: &CellKey, tier: Tier) -> Option<ContentId> {
self.present
.get(&c.s2.0)
.filter(|tiers| tiers.contains(&tier))
.map(|_| ContentId::of_bytes(&[tier.rank()]))
}
}
#[test]
fn returns_highest_available_at_or_below_ceiling() {
let mut m = Mock::default();
m.present.insert(1, vec![Tier::Base, Tier::Field, Tier::Photoreal]);
// ceiling Photoreal -> Photoreal closes, no fallback
let r = resolve(&m, &cell(1), Tier::Photoreal).unwrap();
assert_eq!(r.tier, Tier::Photoreal);
assert!(!r.fell_back);
// ceiling Field -> must NOT return Photoreal; Field closes
let r = resolve(&m, &cell(1), Tier::Field).unwrap();
assert_eq!(r.tier, Tier::Field);
assert!(!r.fell_back);
}
#[test]
fn falls_back_to_floor_when_higher_tiers_absent() {
let mut m = Mock::default();
m.present.insert(2, vec![Tier::Base]); // only the floor
let r = resolve(&m, &cell(2), Tier::Photoreal).unwrap();
assert_eq!(r.tier, Tier::Base);
assert!(r.fell_back); // requested Photoreal, got Base
}
#[test]
fn cache_short_circuits() {
let mut m = Mock::default();
m.present.insert(3, vec![Tier::Base, Tier::Photoreal]);
m.cache.push(3);
let r = resolve(&m, &cell(3), Tier::Photoreal).unwrap();
assert_eq!(r.tier, Tier::Cache);
assert!(!r.fell_back);
}
#[test]
fn uncovered_region_is_an_error() {
let m = Mock::default(); // nothing present, including the floor
assert!(matches!(resolve(&m, &cell(9), Tier::Base), Err(CascadeError::UncoveredRegion)));
}
}