1use serde::{Deserialize, Serialize};
4use std::sync::atomic::{AtomicU64, Ordering};
5
6static NEXT_PROGRAM: AtomicU64 = AtomicU64::new(1);
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
10pub struct ProgramId(u64);
11
12impl ProgramId {
13 pub(crate) fn next() -> Self {
15 Self(NEXT_PROGRAM.fetch_add(1, Ordering::Relaxed))
16 }
17
18 pub fn index(self) -> u64 {
20 self.0
21 }
22}
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
27#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
28#[serde(transparent)]
29pub struct WorkflowIx(u32);
30
31impl WorkflowIx {
32 pub(crate) fn new(index: u32) -> Self {
34 Self(index)
35 }
36
37 pub fn index(self) -> u32 {
39 self.0
40 }
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
47#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
48#[serde(transparent)]
49pub struct TaskIx(u32);
50
51impl TaskIx {
52 pub(crate) fn new(index: u32) -> Self {
54 Self(index)
55 }
56
57 pub fn index(self) -> u32 {
59 self.0
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn program_ids_are_distinct() {
69 assert_ne!(ProgramId::next(), ProgramId::next());
70 assert!(ProgramId::next().index() > 0);
71 }
72
73 #[test]
74 fn a_position_is_its_number() {
75 assert_eq!(WorkflowIx::new(3).index(), 3);
76 assert_eq!(TaskIx::new(7).index(), 7);
77 assert!(TaskIx::new(1) < TaskIx::new(2));
78 }
79}