1use alloc::format;
30use alloc::string::{String, ToString};
31use alloc::vec::Vec;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum ConformanceDimension {
36 Instantiate,
38 Properties,
41 RoundTrip,
44 LossResilience,
47 Quality,
51 ZeroCopy,
54 Latency,
57 Oracle,
60 Hardware,
63}
64
65impl ConformanceDimension {
66 pub const ALL: [ConformanceDimension; 9] = [
68 ConformanceDimension::Instantiate,
69 ConformanceDimension::Properties,
70 ConformanceDimension::RoundTrip,
71 ConformanceDimension::LossResilience,
72 ConformanceDimension::Quality,
73 ConformanceDimension::ZeroCopy,
74 ConformanceDimension::Latency,
75 ConformanceDimension::Oracle,
76 ConformanceDimension::Hardware,
77 ];
78
79 pub fn label(self) -> &'static str {
81 match self {
82 ConformanceDimension::Instantiate => "instantiate",
83 ConformanceDimension::Properties => "properties",
84 ConformanceDimension::RoundTrip => "round-trip",
85 ConformanceDimension::LossResilience => "loss-resilience",
86 ConformanceDimension::Quality => "quality",
87 ConformanceDimension::ZeroCopy => "zero-copy",
88 ConformanceDimension::Latency => "latency",
89 ConformanceDimension::Oracle => "oracle",
90 ConformanceDimension::Hardware => "hardware",
91 }
92 }
93
94 pub fn from_label(s: &str) -> Option<Self> {
97 Self::ALL.into_iter().find(|d| d.label() == s)
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
105pub struct Evidence {
106 pub dimension: ConformanceDimension,
108 pub platform: Option<String>,
111 pub codec: Option<String>,
113 pub peer: Option<String>,
116 pub detail: Option<String>,
118}
119
120impl Evidence {
121 pub fn new(dimension: ConformanceDimension) -> Self {
123 Self {
124 dimension,
125 platform: None,
126 codec: None,
127 peer: None,
128 detail: None,
129 }
130 }
131
132 pub fn platform(mut self, p: impl Into<String>) -> Self {
134 self.platform = Some(p.into());
135 self
136 }
137
138 pub fn codec(mut self, c: impl Into<String>) -> Self {
140 self.codec = Some(c.into());
141 self
142 }
143
144 pub fn peer(mut self, p: impl Into<String>) -> Self {
146 self.peer = Some(p.into());
147 self
148 }
149
150 pub fn detail(mut self, d: impl Into<String>) -> Self {
152 self.detail = Some(d.into());
153 self
154 }
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
160pub enum MaturityLevel {
161 Unverified,
163 Instantiated,
165 UnitTested,
168 InteropTested,
170 HardwareValidated,
172}
173
174impl MaturityLevel {
175 pub fn label(self) -> &'static str {
177 match self {
178 MaturityLevel::Unverified => "unverified",
179 MaturityLevel::Instantiated => "instantiated",
180 MaturityLevel::UnitTested => "unit-tested",
181 MaturityLevel::InteropTested => "interop-tested",
182 MaturityLevel::HardwareValidated => "hardware-validated",
183 }
184 }
185}
186
187#[derive(Debug, Clone, PartialEq, Eq)]
190pub struct MaturityRecord {
191 pub element: String,
193 pub evidence: Vec<Evidence>,
195}
196
197impl MaturityRecord {
198 pub fn new(element: impl Into<String>) -> Self {
202 Self {
203 element: element.into(),
204 evidence: Vec::new(),
205 }
206 }
207
208 pub fn with(mut self, e: Evidence) -> Self {
210 self.evidence.push(e);
211 self
212 }
213
214 pub fn add(&mut self, e: Evidence) {
216 self.evidence.push(e);
217 }
218
219 pub fn has(&self, dimension: ConformanceDimension) -> bool {
221 self.evidence.iter().any(|e| e.dimension == dimension)
222 }
223
224 pub fn dimensions(&self) -> Vec<ConformanceDimension> {
226 ConformanceDimension::ALL
227 .into_iter()
228 .filter(|&d| self.has(d))
229 .collect()
230 }
231
232 pub fn peers(&self) -> Vec<&str> {
234 let mut v: Vec<&str> = self
235 .evidence
236 .iter()
237 .filter_map(|e| e.peer.as_deref())
238 .collect();
239 v.sort_unstable();
240 v.dedup();
241 v
242 }
243
244 pub fn platforms(&self) -> Vec<&str> {
246 let mut v: Vec<&str> = self
247 .evidence
248 .iter()
249 .filter_map(|e| e.platform.as_deref())
250 .collect();
251 v.sort_unstable();
252 v.dedup();
253 v
254 }
255
256 pub fn level(&self) -> MaturityLevel {
260 use ConformanceDimension as D;
261 let has_hardware = self
262 .evidence
263 .iter()
264 .any(|e| e.dimension == D::Hardware && e.platform.is_some());
265 let has_interop = self
266 .evidence
267 .iter()
268 .any(|e| e.dimension == D::Oracle && e.peer.is_some());
269 let behavioral = self.has(D::RoundTrip)
270 || self.has(D::LossResilience)
271 || self.has(D::Quality)
272 || self.has(D::ZeroCopy);
273 let advertised = self.has(D::Instantiate) || self.has(D::Properties);
274 if has_hardware {
275 MaturityLevel::HardwareValidated
276 } else if has_interop {
277 MaturityLevel::InteropTested
278 } else if behavioral {
279 MaturityLevel::UnitTested
280 } else if advertised {
281 MaturityLevel::Instantiated
282 } else {
283 MaturityLevel::Unverified
284 }
285 }
286}
287
288#[derive(Debug, Clone, Default)]
290pub struct ConformanceReport {
291 pub records: Vec<MaturityRecord>,
293}
294
295impl ConformanceReport {
296 pub fn new() -> Self {
298 Self::default()
299 }
300
301 pub fn push(&mut self, record: MaturityRecord) {
303 self.records.push(record);
304 }
305
306 pub fn record_mut(&mut self, element: &str) -> &mut MaturityRecord {
308 if let Some(i) = self.records.iter().position(|r| r.element == element) {
309 &mut self.records[i]
310 } else {
311 self.records.push(MaturityRecord::new(element));
312 self.records.last_mut().expect("just pushed")
313 }
314 }
315
316 pub fn absorb(&mut self, other: ConformanceReport) {
321 for record in other.records {
322 let dst = self.record_mut(&record.element);
323 for ev in record.evidence {
324 if !dst.evidence.contains(&ev) {
325 dst.evidence.push(ev);
326 }
327 }
328 }
329 }
330
331 pub fn min_level(&self) -> MaturityLevel {
334 self.records
335 .iter()
336 .map(MaturityRecord::level)
337 .min()
338 .unwrap_or(MaturityLevel::Unverified)
339 }
340
341 pub fn to_table(&self) -> String {
344 let rows: Vec<(String, String, String, String)> = self
345 .records
346 .iter()
347 .map(|r| {
348 let dims = r
349 .dimensions()
350 .iter()
351 .map(|d| d.label())
352 .collect::<Vec<_>>()
353 .join(", ");
354 let mut context = Vec::new();
355 let peers = r.peers();
356 if !peers.is_empty() {
357 context.push(format!("peers: {}", peers.join(", ")));
358 }
359 let plats = r.platforms();
360 if !plats.is_empty() {
361 context.push(format!("platforms: {}", plats.join(", ")));
362 }
363 (
364 r.element.clone(),
365 r.level().label().to_string(),
366 dims,
367 context.join("; "),
368 )
369 })
370 .collect();
371
372 let w_el = rows.iter().map(|r| r.0.len()).chain([7]).max().unwrap_or(7);
373 let w_lv = rows.iter().map(|r| r.1.len()).chain([5]).max().unwrap_or(5);
374 let mut s = String::new();
375 s.push_str(&format!(
376 "{:<w_el$} {:<w_lv$} dimensions\n",
377 "element", "maturity"
378 ));
379 for (el, lv, dims, ctx) in &rows {
380 s.push_str(&format!("{el:<w_el$} {lv:<w_lv$} {dims}\n"));
381 if !ctx.is_empty() {
382 s.push_str(&format!("{:<w_el$} {:<w_lv$} ({ctx})\n", "", ""));
383 }
384 }
385 s
386 }
387}
388
389#[cfg(test)]
390mod tests {
391 use super::*;
392
393 #[test]
394 fn empty_record_is_unverified() {
395 assert_eq!(MaturityRecord::new("x").level(), MaturityLevel::Unverified);
396 }
397
398 #[test]
399 fn instantiate_alone_is_instantiated() {
400 let r = MaturityRecord::new("capsfilter")
401 .with(Evidence::new(ConformanceDimension::Instantiate))
402 .with(Evidence::new(ConformanceDimension::Properties));
403 assert_eq!(r.level(), MaturityLevel::Instantiated);
404 }
405
406 #[test]
407 fn a_round_trip_reaches_unit_tested_but_not_interop() {
408 let r = MaturityRecord::new("st2110video")
411 .with(Evidence::new(ConformanceDimension::Instantiate))
412 .with(Evidence::new(ConformanceDimension::RoundTrip).codec("rgba8"));
413 assert_eq!(r.level(), MaturityLevel::UnitTested);
414 assert!(!r.has(ConformanceDimension::Oracle), "no interop claim");
415 }
416
417 #[test]
418 fn a_golden_quality_check_reaches_unit_tested_but_not_interop() {
419 let r = MaturityRecord::new("rav1ddec")
422 .with(Evidence::new(ConformanceDimension::Quality).codec("av1"));
423 assert_eq!(r.level(), MaturityLevel::UnitTested);
424 assert!(!r.has(ConformanceDimension::Oracle));
425 }
426
427 #[test]
428 fn oracle_without_a_peer_does_not_reach_interop() {
429 let r = MaturityRecord::new("h264enc")
432 .with(Evidence::new(ConformanceDimension::RoundTrip))
433 .with(Evidence::new(ConformanceDimension::Oracle));
434 assert_eq!(r.level(), MaturityLevel::UnitTested);
435 }
436
437 #[test]
438 fn oracle_with_a_peer_reaches_interop() {
439 let r = MaturityRecord::new("h264enc")
440 .with(Evidence::new(ConformanceDimension::RoundTrip))
441 .with(
442 Evidence::new(ConformanceDimension::Oracle)
443 .peer("ffmpeg")
444 .codec("h264"),
445 );
446 assert_eq!(r.level(), MaturityLevel::InteropTested);
447 assert_eq!(r.peers(), alloc::vec!["ffmpeg"]);
448 }
449
450 #[test]
451 fn hardware_with_a_platform_is_the_top_level() {
452 let r = MaturityRecord::new("nvh264dec")
453 .with(Evidence::new(ConformanceDimension::Oracle).peer("ffmpeg"))
454 .with(Evidence::new(ConformanceDimension::Hardware).platform("rtx-3060"));
455 assert_eq!(r.level(), MaturityLevel::HardwareValidated);
456 assert_eq!(r.platforms(), alloc::vec!["rtx-3060"]);
457 }
458
459 #[test]
460 fn levels_are_ordered() {
461 assert!(MaturityLevel::Unverified < MaturityLevel::Instantiated);
462 assert!(MaturityLevel::UnitTested < MaturityLevel::InteropTested);
463 assert!(MaturityLevel::InteropTested < MaturityLevel::HardwareValidated);
464 }
465
466 #[test]
467 fn dimension_labels_round_trip() {
468 for d in ConformanceDimension::ALL {
469 assert_eq!(ConformanceDimension::from_label(d.label()), Some(d));
470 }
471 assert_eq!(ConformanceDimension::from_label("bogus"), None);
472 }
473
474 #[test]
475 fn absorb_merges_persisted_evidence_and_raises_the_level() {
476 let mut base = ConformanceReport::new();
479 base.push(
480 MaturityRecord::new("mp4mux")
481 .with(Evidence::new(ConformanceDimension::Instantiate))
482 .with(Evidence::new(ConformanceDimension::RoundTrip)),
483 );
484 assert_eq!(base.record_mut("mp4mux").level(), MaturityLevel::UnitTested);
485
486 let mut persisted = ConformanceReport::new();
487 persisted.push(
488 MaturityRecord::new("mp4mux").with(
489 Evidence::new(ConformanceDimension::Oracle)
490 .peer("ffmpeg")
491 .codec("h264"),
492 ),
493 );
494 base.absorb(persisted);
495 assert_eq!(
496 base.record_mut("mp4mux").level(),
497 MaturityLevel::InteropTested
498 );
499 assert_eq!(
500 base.records.len(),
501 1,
502 "merged into the existing element, not duplicated"
503 );
504 }
505
506 #[test]
507 fn absorb_deduplicates_identical_evidence() {
508 let mut a = ConformanceReport::new();
509 a.push(MaturityRecord::new("x").with(Evidence::new(ConformanceDimension::RoundTrip)));
510 let mut b = ConformanceReport::new();
511 b.push(MaturityRecord::new("x").with(Evidence::new(ConformanceDimension::RoundTrip)));
512 a.absorb(b);
513 assert_eq!(
514 a.record_mut("x").evidence.len(),
515 1,
516 "identical evidence is not doubled"
517 );
518 }
519
520 #[test]
521 fn report_table_lists_rows_and_min_level() {
522 let mut report = ConformanceReport::new();
523 report.push(
524 MaturityRecord::new("st2110video")
525 .with(Evidence::new(ConformanceDimension::Instantiate))
526 .with(Evidence::new(ConformanceDimension::RoundTrip)),
527 );
528 report.push(MaturityRecord::new("unchecked"));
529 let table = report.to_table();
530 assert!(table.contains("st2110video"), "row present:\n{table}");
531 assert!(
532 table.contains("unit-tested"),
533 "derived level shown:\n{table}"
534 );
535 assert!(table.contains("round-trip"), "dimension shown:\n{table}");
536 assert_eq!(
537 report.min_level(),
538 MaturityLevel::Unverified,
539 "the unchecked element drags the min down"
540 );
541 }
542}