1use core::ops::Deref;
4use cu29_clock::{RobotClock, RobotClockMock};
5
6#[derive(Clone, Debug)]
23pub struct CuContext {
24 pub clock: RobotClock,
26 cl_id: u64,
27 instance_id: u32,
28 subsystem_code: u16,
29 task_ids: &'static [&'static str],
30 current_task_index: Option<usize>,
31}
32
33impl CuContext {
34 pub fn builder(clock: RobotClock) -> CuContextBuilder {
36 CuContextBuilder {
37 clock,
38 cl_id: 0,
39 instance_id: 0,
40 subsystem_code: 0,
41 task_ids: &[],
42 }
43 }
44
45 pub fn from_clock(clock: RobotClock) -> Self {
51 Self::builder(clock).build()
52 }
53
54 #[cfg(feature = "std")]
60 pub fn new_with_clock() -> Self {
61 Self::from_clock(RobotClock::new())
62 }
63
64 pub fn new_mock_clock() -> (Self, RobotClockMock) {
68 let (clock, mock) = RobotClock::mock();
69 (Self::from_clock(clock), mock)
70 }
71
72 pub(crate) fn new(
74 clock: RobotClock,
75 clid: u64,
76 instance_id: u32,
77 subsystem_code: u16,
78 task_ids: &'static [&'static str],
79 ) -> Self {
80 Self {
81 clock,
82 cl_id: clid,
83 instance_id,
84 subsystem_code,
85 task_ids,
86 current_task_index: None,
87 }
88 }
89
90 #[doc(hidden)]
92 pub fn from_runtime_metadata(
93 clock: RobotClock,
94 clid: u64,
95 instance_id: u32,
96 subsystem_code: u16,
97 task_ids: &'static [&'static str],
98 ) -> Self {
99 Self::new(clock, clid, instance_id, subsystem_code, task_ids)
100 }
101
102 pub fn set_current_task(&mut self, task_index: usize) {
104 self.current_task_index = Some(task_index);
105 }
106
107 pub fn clear_current_task(&mut self) {
109 self.current_task_index = None;
110 }
111
112 pub fn cl_id(&self) -> u64 {
118 self.cl_id
119 }
120
121 pub fn instance_id(&self) -> u32 {
123 self.instance_id
124 }
125
126 pub fn subsystem_code(&self) -> u16 {
128 self.subsystem_code
129 }
130
131 pub fn task_index(&self) -> Option<usize> {
133 self.current_task_index
134 }
135
136 pub fn task_id(&self) -> Option<&'static str> {
138 self.current_task_index
139 .and_then(|idx| self.task_ids.get(idx).copied())
140 }
141}
142
143#[derive(Clone, Debug)]
145pub struct CuContextBuilder {
146 clock: RobotClock,
147 cl_id: u64,
148 instance_id: u32,
149 subsystem_code: u16,
150 task_ids: &'static [&'static str],
151}
152
153impl CuContextBuilder {
154 pub fn cl_id(mut self, cl_id: u64) -> Self {
156 self.cl_id = cl_id;
157 self
158 }
159
160 pub fn instance_id(mut self, instance_id: u32) -> Self {
162 self.instance_id = instance_id;
163 self
164 }
165
166 pub fn task_ids(mut self, task_ids: &'static [&'static str]) -> Self {
168 self.task_ids = task_ids;
169 self
170 }
171
172 pub fn build(self) -> CuContext {
174 CuContext::new(
175 self.clock,
176 self.cl_id,
177 self.instance_id,
178 self.subsystem_code,
179 self.task_ids,
180 )
181 }
182}
183
184impl Deref for CuContext {
185 type Target = RobotClock;
186
187 fn deref(&self) -> &Self::Target {
188 &self.clock
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::CuContext;
195 use cu29_clock::RobotClock;
196
197 #[test]
198 fn default_instance_id_is_zero() {
199 let ctx = CuContext::from_clock(RobotClock::default());
200 assert_eq!(ctx.instance_id(), 0);
201 assert_eq!(ctx.subsystem_code(), 0);
202 }
203
204 #[test]
205 fn builder_overrides_instance_id() {
206 let ctx = CuContext::builder(RobotClock::default())
207 .cl_id(7)
208 .instance_id(42)
209 .build();
210 assert_eq!(ctx.cl_id(), 7);
211 assert_eq!(ctx.instance_id(), 42);
212 assert_eq!(ctx.subsystem_code(), 0);
213 }
214
215 #[test]
216 fn runtime_metadata_sets_subsystem_code() {
217 let ctx = CuContext::from_runtime_metadata(RobotClock::default(), 9, 42, 7, &[]);
218 assert_eq!(ctx.cl_id(), 9);
219 assert_eq!(ctx.instance_id(), 42);
220 assert_eq!(ctx.subsystem_code(), 7);
221 }
222}