Skip to main content

vernier_partial/
traits.rs

1//! Trait surface for paradigm-specific partial bodies.
2//!
3//! `vernier-partial` owns the wire envelope (magic, version, CRC,
4//! header) and the partition + rank-collision policy; each paradigm
5//! crate owns its body type and its merge accumulator. The traits
6//! here are the seam.
7//!
8//! Encode and decode are routed through [`crate::envelope::encode`]
9//! and [`crate::envelope::with_validated_envelope`] respectively, both
10//! of which take the body archive bytes as already-rkyv-archived
11//! `&[u8]` so this crate never touches paradigm-specific rkyv
12//! generics.
13
14/// Paradigm discriminator carried in the wire envelope header.
15///
16/// Stable u8 values: load-bearing across the format-version boundary
17/// because cross-paradigm partials are rejected by integer compare on
18/// this byte (see [`crate::error::PartialFormatErrorKind::ParadigmMismatch`]).
19#[repr(u8)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21pub enum ParadigmKind {
22    /// Instance detection (bbox / segm / boundary / keypoints) —
23    /// the AP fold from `vernier-core`.
24    Instance = 0,
25    /// Semantic segmentation — confusion-matrix fold from
26    /// `vernier-semantic`.
27    Semantic = 1,
28    /// Panoptic quality — per-category PqStat fold from
29    /// `vernier-panoptic`.
30    Panoptic = 2,
31}
32
33impl ParadigmKind {
34    /// Map a wire byte back to the typed enum. Returns `None` if the
35    /// byte is unknown — the receiver surfaces this as
36    /// [`PartialError::Format`](crate::error::PartialError::Format) with kind
37    /// [`crate::error::PartialFormatErrorKind::ParadigmMismatch`].
38    pub fn from_u8(b: u8) -> Option<Self> {
39        match b {
40            0 => Some(Self::Instance),
41            1 => Some(Self::Semantic),
42            2 => Some(Self::Panoptic),
43            _ => None,
44        }
45    }
46
47    /// The wire byte for this paradigm.
48    pub const fn as_u8(self) -> u8 {
49        self as u8
50    }
51}
52
53/// Receiving rank's expectation of what a partial should look like.
54/// Each paradigm builds one from its own (dataset, params, parity_mode,
55/// evaluator config) and passes it to [`crate::envelope::with_validated_envelope`].
56///
57/// Validation is paradigm-agnostic byte compare except for
58/// `shape_fingerprint`, where the receiver supplies its own values
59/// and the four-slot interpretation is paradigm-specific (instance:
60/// `(n_categories, n_area_ranges, n_images, retain_iou)`; semantic:
61/// `(n_classes, 0, n_images, 0)`; panoptic: `(n_categories, 0,
62/// n_images, things_stuff_split)`).
63#[derive(Debug, Clone)]
64pub struct PartialExpectation {
65    /// Receiving evaluator's paradigm.
66    pub paradigm: ParadigmKind,
67    /// Paradigm-defined sub-kind (instance: `KernelKind` discriminant;
68    /// semantic / panoptic: `0`).
69    pub discriminator: u32,
70    /// `ParityMode` discriminant. Strict and corrected cells differ
71    /// by construction so a mismatched mode means the partial cannot
72    /// be merged.
73    pub parity_mode: u8,
74    /// Receiving rank's `dataset_hash`. Partial must match exactly.
75    pub dataset_hash: [u8; 32],
76    /// Receiving rank's `params_hash`. Partial must match exactly.
77    pub params_hash: [u8; 32],
78    /// Paradigm-specific four-slot fingerprint.
79    pub shape_fingerprint: [u32; 4],
80    /// Whether the receiving evaluator is in strict mode. Affects the
81    /// rank-collision check (corrected mode tolerates duplicate ranks;
82    /// strict refuses).
83    pub strict_mode: bool,
84}
85
86/// Marker trait declaring the paradigm a partial body type belongs to.
87/// Each paradigm crate implements this on its `WirePartialBody` (or
88/// equivalent) wire-form struct.
89///
90/// The trait does not carry rkyv bounds because each paradigm is
91/// responsible for its own body archive — `vernier-partial` only
92/// transports already-archived body bytes.
93pub trait Partial {
94    /// Which paradigm this partial body belongs to. Carried in the
95    /// wire envelope header for cross-paradigm rejection.
96    const PARADIGM: ParadigmKind;
97}