Skip to main content

mesh_llm_runtime_event_contracts/
fact_data.rs

1use std::time::Duration;
2
3const MAX_ID_BYTES: usize = 256;
4const MAX_STATE_BYTES: usize = 64;
5const MAX_REASON_BYTES: usize = 128;
6const MAX_SUMMARY_KEY_BYTES: usize = 64;
7const MAX_HUMAN_SUMMARY_BYTES: usize = 512;
8const MAX_NUMERIC_SUMMARIES: usize = 16;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum BoundedTextError {
12    Empty,
13    TooLong,
14}
15
16fn bounded_text(value: &str, max_bytes: usize) -> Result<String, BoundedTextError> {
17    if value.is_empty() {
18        return Err(BoundedTextError::Empty);
19    }
20    if value.len() > max_bytes {
21        return Err(BoundedTextError::TooLong);
22    }
23    Ok(value.to_owned())
24}
25
26macro_rules! string_value {
27    ($name:ident, $max:expr) => {
28        #[derive(Debug, Clone, PartialEq, Eq, Hash)]
29        pub struct $name(String);
30
31        impl $name {
32            pub fn new(value: &str) -> Result<Self, BoundedTextError> {
33                bounded_text(value, $max).map(Self)
34            }
35
36            #[must_use]
37            pub fn as_str(&self) -> &str {
38                &self.0
39            }
40        }
41    };
42}
43
44string_value!(LogicalModelId, MAX_ID_BYTES);
45string_value!(TopologyId, MAX_ID_BYTES);
46string_value!(StageId, MAX_ID_BYTES);
47string_value!(SessionId, MAX_ID_BYTES);
48string_value!(RequestId, MAX_ID_BYTES);
49string_value!(DeviceId, MAX_ID_BYTES);
50string_value!(StateName, MAX_STATE_BYTES);
51string_value!(UnknownReasonCode, MAX_REASON_BYTES);
52string_value!(NumericSummaryKey, MAX_SUMMARY_KEY_BYTES);
53string_value!(HumanSummary, MAX_HUMAN_SUMMARY_BYTES);
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct StageIdentity {
57    pub id: StageId,
58    pub index: u32,
59}
60
61impl StageIdentity {
62    #[must_use]
63    pub const fn new(id: StageId, index: u32) -> Self {
64        Self { id, index }
65    }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Default)]
69pub struct ScopeIdentities {
70    pub model_id: Option<LogicalModelId>,
71    pub topology_id: Option<TopologyId>,
72    pub stage: Option<StageIdentity>,
73    pub session_id: Option<SessionId>,
74    pub request_id: Option<RequestId>,
75    pub device_id: Option<DeviceId>,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct StateTransition {
80    pub previous: Option<StateName>,
81    pub current: StateName,
82}
83
84impl StateTransition {
85    #[must_use]
86    pub const fn new(previous: Option<StateName>, current: StateName) -> Self {
87        Self { previous, current }
88    }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum ProgressUnit {
93    None,
94    Bytes,
95    Items,
96    Tensors,
97    Steps,
98    Tokens,
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub struct Progress {
103    pub current: u64,
104    pub total: Option<u64>,
105    pub unit: ProgressUnit,
106}
107
108impl Progress {
109    #[must_use]
110    pub const fn new(current: u64, total: Option<u64>, unit: ProgressUnit) -> Self {
111        Self {
112            current,
113            total,
114            unit,
115        }
116    }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub enum Outcome {
121    Success,
122    Failure,
123    Rejected,
124    Cancelled,
125    Unknown,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub enum ReasonCode {
130    InvalidConfiguration,
131    UnsupportedCapability,
132    MissingArtifact,
133    ArtifactIoFailure,
134    ModelFormatOrLoadFailure,
135    BackendInitializationFailure,
136    DeviceUnavailable,
137    ResourceAllocationFailure,
138    OutOfMemory,
139    ContextExhausted,
140    StageUnavailable,
141    Timeout,
142    Cancellation,
143    ProcessCrash,
144    IncompatibleAbiOrFeatureSet,
145    InternalRuntimeFailure,
146    UnknownFailure,
147    TerminalNotDelivered,
148    ReservationExhausted,
149    Unknown(UnknownReasonCode),
150}
151
152#[derive(Debug, Clone, Copy, PartialEq)]
153pub enum NumericValue {
154    Unsigned(u64),
155    Signed(i64),
156    Floating(f64),
157}
158
159#[derive(Debug, Clone, PartialEq)]
160pub struct NumericSummary {
161    pub key: NumericSummaryKey,
162    pub value: NumericValue,
163}
164
165impl NumericSummary {
166    #[must_use]
167    pub const fn new(key: NumericSummaryKey, value: NumericValue) -> Self {
168        Self { key, value }
169    }
170}
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub struct TooManyNumericSummaries;
174
175#[derive(Debug, Clone, PartialEq, Default)]
176pub struct BoundedNumericSummaries(Vec<NumericSummary>);
177
178impl BoundedNumericSummaries {
179    pub fn new(values: Vec<NumericSummary>) -> Result<Self, TooManyNumericSummaries> {
180        if values.len() > MAX_NUMERIC_SUMMARIES {
181            return Err(TooManyNumericSummaries);
182        }
183        Ok(Self(values))
184    }
185
186    #[must_use]
187    pub fn as_slice(&self) -> &[NumericSummary] {
188        &self.0
189    }
190}
191
192#[derive(Debug, Clone, PartialEq, Default)]
193pub struct FactData {
194    pub scope: ScopeIdentities,
195    pub state: Option<StateTransition>,
196    pub progress: Option<Progress>,
197    pub outcome: Option<Outcome>,
198    pub reason: Option<ReasonCode>,
199    pub duration: Option<Duration>,
200    pub numeric_summaries: BoundedNumericSummaries,
201    pub summary: Option<HumanSummary>,
202}