emboss_runtime/
typestate.rs1#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
19pub struct UncheckedState;
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
23pub struct CompleteState;
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
27pub struct OkState;
28
29pub type Ok = OkState;
31
32pub trait State {
34 type OnLayoutMutation: State;
35 type OnValidMutation: State;
36}
37
38impl State for UncheckedState {
39 type OnLayoutMutation = UncheckedState;
40 type OnValidMutation = UncheckedState;
41}
42
43impl State for CompleteState {
44 type OnLayoutMutation = UncheckedState;
45 type OnValidMutation = CompleteState;
46}
47
48impl State for OkState {
49 type OnLayoutMutation = UncheckedState;
50 type OnValidMutation = CompleteState;
51}
52
53pub trait IsComplete: State {}
55impl IsComplete for CompleteState {}
56impl IsComplete for OkState {}
57
58pub trait IsOk: IsComplete {}
60impl IsOk for OkState {}
61
62pub trait InfallibleRead {
64 type ReadValue;
65 fn read(&self) -> Self::ReadValue;
66}
67
68pub trait InfallibleWrite {
70 type WriteValue;
71 type Output;
72 fn write(self, val: Self::WriteValue) -> Self::Output;
73}
74
75pub trait CheckComplete {
77 type Completed;
78 fn check_complete(self) -> Result<Self::Completed, crate::Error>;
79}
80
81pub trait CheckOk {
83 type Ok;
84 fn check_ok(self) -> Result<Self::Ok, crate::Error>;
85}
86
87pub trait IntoWriter {
89 type Writer;
90 fn into_writer(self) -> Self::Writer;
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::{LittleEndian, Storage, UInt};
97
98 const TEST_VALUE: u32 = 0x12345678;
99
100 fn assert_state<S: State>() {}
101 fn assert_complete<S: IsComplete>() {}
102 fn assert_ok<S: IsOk>() {}
103
104 #[test]
105 fn test_state_marker_traits() {
106 assert_state::<UncheckedState>();
107 assert_state::<CompleteState>();
108 assert_state::<OkState>();
109
110 assert_complete::<CompleteState>();
111 assert_complete::<OkState>();
112
113 assert_ok::<OkState>();
114 }
115
116 #[test]
117 fn test_on_layout_mutation_transitions() {
118 fn assert_is_unchecked<S: Storage>(_view: &UInt<32, LittleEndian, S, UncheckedState>) {}
119
120 let mut buf = [0u8; 4];
121 let ok_view =
122 UInt::<32, LittleEndian, &mut [u8; 4], OkState>::new(&mut buf);
123 assert_eq!(ok_view.read(), 0);
124
125 let mutated_view = ok_view.write(TEST_VALUE);
127 assert_is_unchecked(&mutated_view);
128
129 assert_eq!(mutated_view.try_read().expect("valid read"), TEST_VALUE);
131 }
132
133 #[test]
134 fn test_infallible_uint_read_write() {
135 let mut buf = [0u8; 4];
136 let uint_view = UInt::<32, LittleEndian, &mut [u8; 4], OkState>::new(&mut buf);
137 let _ = uint_view.write(TEST_VALUE);
138 let read_view = UInt::<32, LittleEndian, &[u8; 4], OkState>::new(&buf);
139 assert_eq!(read_view.read(), TEST_VALUE);
140 }
141
142 #[test]
143 fn test_into_writer_conversion() {
144 struct MockMut<S>(S);
145 struct MockWriter<S, ST: State>(S, core::marker::PhantomData<ST>);
146
147 impl<S> IntoWriter for MockMut<S> {
148 type Writer = MockWriter<S, UncheckedState>;
149 fn into_writer(self) -> Self::Writer {
150 MockWriter(self.0, core::marker::PhantomData)
151 }
152 }
153
154 impl<S> CheckComplete for MockWriter<S, UncheckedState> {
155 type Completed = MockWriter<S, CompleteState>;
156 fn check_complete(self) -> Result<Self::Completed, crate::Error> {
157 Ok(MockWriter(self.0, core::marker::PhantomData))
158 }
159 }
160
161 impl<S> CheckOk for MockWriter<S, UncheckedState> {
162 type Ok = MockWriter<S, OkState>;
163 fn check_ok(self) -> Result<Self::Ok, crate::Error> {
164 Ok(MockWriter(self.0, core::marker::PhantomData))
165 }
166 }
167
168 let mut buf = [0u8; 4];
169 let mock_mut = MockMut(&mut buf);
170 let _complete_writer: MockWriter<&mut [u8; 4], CompleteState> =
171 mock_mut.into_writer().check_complete().expect("complete writer");
172
173 let mock_mut2 = MockMut(&mut buf);
174 let _ok_writer: MockWriter<&mut [u8; 4], OkState> =
175 mock_mut2.into_writer().check_ok().expect("ok writer");
176 }
177}