Skip to main content

score_set/
lib.rs

1//! # score-set
2//!
3//! A `#![no_std]` + `alloc` Rust library for building **weighted scoring
4//! operators** — define metrics via a builder pipeline, combine them into a
5//! zero-vtable flat scorer with the [`score_set32!`] macro.
6//!
7//! # Quick example
8//!
9//! ```ignore
10//! use score_set::*;
11//!
12//! struct Restaurant {
13//!     cleanliness: f32,
14//!     food_quality: f32,
15//! }
16//!
17//! let clean = metric32("cleanliness")
18//!     .measure()
19//!     .by(|r: &Restaurant| r.cleanliness)
20//!     .map01()
21//!     .linear(100.0);
22//!
23//! let food = metric32("food")
24//!     .measure()
25//!     .by(|r: &Restaurant| r.food_quality)
26//!     .map01()
27//!     .identity();
28//!
29//! let scorer = score_set32! { 2.0 => clean, 1.0 => food }?;
30//!
31//! let r = Restaurant { cleanliness: 80.0, food_quality: 4.0 };
32//! let total: f32 = scorer.score(&r);
33//! let rows = scorer.breakdown(&r);
34//! # Ok::<(), &'static str>(())
35//! ```
36//!
37//! # Partial application
38//!
39//! [`by()`](MeasureStage32::by) accepts capturing closures, enabling parameter
40//! binding at construction time:
41//!
42//! ```ignore
43//! let threshold: f32 = 0.6;
44//! let quality = metric32("quality")
45//!     .measure()
46//!     .by(move |ctx: &MyCtx| if ctx.value > threshold { ctx.value } else { 0.0 })
47//!     .map01()
48//!     .identity();
49//!
50//! let scorer = score_set32! { 1.0 => quality }?;
51//! // scorer only needs &MyCtx — threshold is baked in
52//! ```
53//!
54//! # no_std
55//!
56//! This crate is `#![no_std]` with `extern crate alloc` — it only needs
57//! `Vec` from the allocator and works on bare-metal targets.
58
59#![no_std]
60extern crate alloc;
61
62#[cfg(test)]
63extern crate std;
64
65// Three-state precision selection:
66//   default        → f32  only (ScoreSet32, Metric32, … at crate root)
67//   f64            → f64  only (ScoreSet64, Metric64, … at crate root)
68//   f64 + both     → f32 + f64 (ScoreSet32 + ScoreSet64 at crate root)
69// All modules are private — users only depend on re-exported types.
70
71#[cfg(not(feature = "f64"))]
72mod metric_f32;
73#[cfg(not(feature = "f64"))]
74pub use metric_f32::*;
75
76#[cfg(all(feature = "f64", not(feature = "both")))]
77mod metric_f64;
78#[cfg(all(feature = "f64", not(feature = "both")))]
79pub use metric_f64::*;
80
81#[cfg(all(feature = "f64", feature = "both"))]
82mod metric_f32;
83#[cfg(all(feature = "f64", feature = "both"))]
84mod metric_f64;
85#[cfg(all(feature = "f64", feature = "both"))]
86pub use metric_f32::*;
87#[cfg(all(feature = "f64", feature = "both"))]
88pub use metric_f64::*;
89
90mod value;
91pub use value::{GtZero, NormalizedContainer, NormalizedWeight, Value01};
92pub use witnessed::{WitnessExt, Witnessed};
93
94// Generated score_set32! macro (f32).  Active by default and in `both` mode.
95#[cfg(any(not(feature = "f64"), all(feature = "f64", feature = "both")))]
96mod gen_score_set32;
97
98// Generated score_set64! macro (f64).  Active when `f64` or `both` is enabled.
99#[cfg(feature = "f64")]
100mod gen_score_set64;
101
102#[cfg(test)]
103mod test_support;