1use rsynko_session::*;
2use std::cell::Cell;
3use std::rc::Rc;
4use std::time::Duration;
5
6#[derive(Debug, Default)]
11pub struct ReferenceSession {
12 requests: Vec<ReferenceRequest>,
13 clock: Duration,
14}
15
16#[derive(Debug)]
18struct ReferenceRequest {
19 id: usize,
20 wanted: Wanted,
21 says: usize,
22 beginnable: bool,
23 attended: bool,
24 told: Vec<Telling>,
25 abandonments: Rc<Cell<usize>>,
26}
27
28#[derive(Debug)]
30pub struct ReferenceRun {
31 work: usize,
32 said: Vec<usize>,
33 held: bool,
34 abandoning: bool,
35 abandonments: Rc<Cell<usize>>,
36}
37
38impl ReferenceSession {
39 fn request(&self, id: usize) -> &ReferenceRequest {
41 self.requests
42 .iter()
43 .find(|request| request.id == id)
44 .expect("an authored request")
45 }
46
47 fn request_mut(&mut self, id: usize) -> &mut ReferenceRequest {
49 self.requests
50 .iter_mut()
51 .find(|request| request.id == id)
52 .expect("an authored request")
53 }
54
55 fn author(&mut self, says: usize, beginnable: bool) -> usize {
57 let id = self.requests.len();
58 self.requests.push(ReferenceRequest {
59 id,
60 wanted: Wanted::Running,
61 says,
62 beginnable,
63 attended: false,
64 told: Vec::new(),
65 abandonments: Rc::new(Cell::new(0)),
66 });
67 id
68 }
69}
70
71impl SessionSorts for ReferenceSession {
72 type Id = usize;
73 type Run = ReferenceRun;
74 type Report = usize;
75 type Ending = ();
76 type Refusal = String;
77}
78
79impl UndertakingAlg for ReferenceSession {
80 fn unattended(&self) -> Vec<usize> {
81 self.requests
82 .iter()
83 .filter(|request| !request.attended)
84 .map(|request| request.id)
85 .collect()
86 }
87
88 fn begin(&self, id: &usize) -> Result<ReferenceRun, String> {
89 let request = self.request(*id);
90 if !request.beginnable {
91 return Err("the work refuses to begin".to_owned());
92 }
93 Ok(ReferenceRun {
94 work: request.says,
95 said: Vec::new(),
96 held: false,
97 abandoning: false,
98 abandonments: Rc::clone(&request.abandonments),
99 })
100 }
101}
102
103impl RunReadAlg for ReferenceSession {
104 fn run_is_over(&self, run: &ReferenceRun) -> bool {
105 run.work == 0
106 }
107
108 fn read_run(&self, run: &mut ReferenceRun) -> Vec<usize> {
109 if run.abandoning {
110 run.work = 0;
112 run.said.clear();
113 return Vec::new();
114 }
115 if run.held {
116 return Vec::new();
117 }
118 let said = std::mem::take(&mut run.said);
121 if run.work > 0 {
122 run.work -= 1;
123 run.said.push(run.work);
124 }
125 said
126 }
127
128 fn end_run(&self, _run: ReferenceRun) -> Result<(), String> {
129 Ok(())
130 }
131}
132
133impl RunHoldAlg for ReferenceSession {
134 fn holding_is_possible(&self) -> bool {
135 true
136 }
137
138 fn hold_run(&self, run: &mut ReferenceRun, held: bool) {
139 run.held = held;
140 }
141
142 fn abandon_run(&self, run: &mut ReferenceRun) {
143 run.abandoning = true;
144 run.abandonments.set(run.abandonments.get() + 1);
145 }
146}
147
148impl AttentionAlg for ReferenceSession {
149 fn begun(&mut self, id: &usize, _holdable: bool) {
150 let request = self.request_mut(*id);
151 request.attended = true;
152 request.told.push(Telling::Begun);
153 }
154
155 fn heard(&mut self, id: &usize, _report: usize) {
156 self.request_mut(*id).told.push(Telling::Heard);
157 }
158
159 fn ran_for(&mut self, id: &usize, elapsed: Duration) {
160 self.request_mut(*id).told.push(Telling::RanFor(elapsed));
161 }
162
163 fn ended(&mut self, id: &usize, ending: Result<(), String>) {
164 let request = self.request_mut(*id);
165 request.attended = true;
167 request.told.push(match ending {
168 Ok(()) => Telling::Ended,
169 Err(_) => Telling::Refused,
170 });
171 }
172
173 fn wanted(&self, id: &usize) -> Wanted {
174 self.request(*id).wanted
175 }
176}
177
178impl ClockAlg for ReferenceSession {
179 type Moment = Duration;
180
181 fn now(&self) -> Duration {
182 self.clock
183 }
184
185 fn since(&self, moment: &Duration) -> Duration {
186 self.clock.saturating_sub(*moment)
187 }
188}
189
190impl SessionLawFixture for ReferenceSession {
191 fn law_wanting(&mut self, says: usize) -> usize {
192 self.author(says, true)
193 }
194
195 fn law_unbeginnable(&mut self) -> usize {
196 self.author(0, false)
197 }
198
199 fn law_wants(&mut self, id: &usize, wanted: Wanted) {
200 self.request_mut(*id).wanted = wanted;
201 }
202
203 fn law_passes(&mut self, elapsed: Duration) {
204 self.clock = self.clock.saturating_add(elapsed);
205 }
206
207 fn law_told(&self, id: &usize) -> Vec<Telling> {
208 self.request(*id).told.clone()
209 }
210
211 fn law_abandonments(&self, id: &usize) -> usize {
212 self.request(*id).abandonments.get()
213 }
214}