1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*******************************************************************************
*
* Copyright (c) 2025 - 2026 Haixing Hu.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0.
*
******************************************************************************/
// qubit-style: allow inline-tests
use super::task_status::TaskStatus;
/// Event codes accepted by the task status state machine (`#[repr(usize)]` discriminants `0..8`).
#[repr(usize)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(super) enum TaskStatusEvent {
/// Start running a pending task.
Start = 0,
/// Cancel a task before it starts.
CancelPending = 1,
/// Complete a running task successfully.
CompleteSucceeded = 2,
/// Complete a running task with a user error.
CompleteFailed = 3,
/// Complete a running task after panic conversion.
CompletePanicked = 4,
/// Drop a pending or running task slot before normal completion.
DropUnfinished = 5,
}
impl TaskStatusEvent {
/// Returns the compact event code used by [`FastStateMachine`].
///
/// # Returns
///
/// A stable integer code in `0..TASK_STATUS_EVENT_COUNT`.
#[inline]
pub(super) fn as_usize(self) -> usize {
self as usize
}
/// Returns the completion event matching a normal running-task terminal status.
///
/// # Parameters
///
/// * `status` - Terminal status represented by a normal task result.
///
/// # Returns
///
/// `Some(event)` for success, failure, and panic statuses; `None` for
/// non-terminal states and terminal states owned by explicit cancel/drop APIs.
pub(super) fn from_completion_status(status: TaskStatus) -> Option<Self> {
match status {
TaskStatus::Succeeded => Some(Self::CompleteSucceeded),
TaskStatus::Failed => Some(Self::CompleteFailed),
TaskStatus::Panicked => Some(Self::CompletePanicked),
TaskStatus::Pending
| TaskStatus::Running
| TaskStatus::Cancelled
| TaskStatus::Dropped => None,
}
}
}
#[cfg(test)]
mod tests {
use super::super::task_status_machine::TASK_STATUS_EVENT_COUNT;
use super::TaskStatusEvent;
#[test]
fn task_status_event_as_usize_matches_stable_discriminants() {
assert_eq!(TaskStatusEvent::Start.as_usize(), 0);
assert_eq!(TaskStatusEvent::CancelPending.as_usize(), 1);
assert_eq!(TaskStatusEvent::CompleteSucceeded.as_usize(), 2);
assert_eq!(TaskStatusEvent::CompleteFailed.as_usize(), 3);
assert_eq!(TaskStatusEvent::CompletePanicked.as_usize(), 4);
assert_eq!(TaskStatusEvent::DropUnfinished.as_usize(), 5);
}
#[test]
fn task_status_event_codes_are_zero_through_seven_in_declaration_order() {
let events = [
TaskStatusEvent::Start,
TaskStatusEvent::CancelPending,
TaskStatusEvent::CompleteSucceeded,
TaskStatusEvent::CompleteFailed,
TaskStatusEvent::CompletePanicked,
TaskStatusEvent::DropUnfinished,
];
for (i, event) in events.iter().enumerate() {
assert_eq!(event.as_usize(), i, "event index {i}");
}
}
#[test]
fn task_status_event_count_matches_variants() {
assert_eq!(
TaskStatusEvent::DropUnfinished as usize + 1,
TASK_STATUS_EVENT_COUNT,
"last event discriminant + 1 must equal TASK_STATUS_EVENT_COUNT"
);
}
}