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.iter().find(|request| request.id == id).expect("an authored request")
42 }
43
44 fn request_mut(&mut self, id: usize) -> &mut ReferenceRequest {
46 self.requests.iter_mut().find(|request| request.id == id).expect("an authored request")
47 }
48
49 fn author(&mut self, says: usize, beginnable: bool) -> usize {
51 let id = self.requests.len();
52 self.requests.push(ReferenceRequest {
53 id,
54 wanted: Wanted::Running,
55 says,
56 beginnable,
57 attended: false,
58 told: Vec::new(),
59 abandonments: Rc::new(Cell::new(0)),
60 });
61 id
62 }
63}
64
65impl SessionSorts for ReferenceSession {
66 type Id = usize;
67 type Run = ReferenceRun;
68 type Report = usize;
69 type Ending = ();
70 type Refusal = String;
71}
72
73impl UndertakingAlg for ReferenceSession {
74 fn unattended(&self) -> Vec<usize> {
75 self.requests.iter().filter(|request| !request.attended).map(|request| request.id).collect()
76 }
77
78 fn begin(&self, id: &usize) -> Result<ReferenceRun, String> {
79 let request = self.request(*id);
80 if !request.beginnable {
81 return Err("the work refuses to begin".to_owned());
82 }
83 Ok(ReferenceRun {
84 work: request.says,
85 said: Vec::new(),
86 held: false,
87 abandoning: false,
88 abandonments: Rc::clone(&request.abandonments),
89 })
90 }
91}
92
93impl RunReadAlg for ReferenceSession {
94 fn run_is_over(&self, run: &ReferenceRun) -> bool {
95 run.work == 0
96 }
97
98 fn read_run(&self, run: &mut ReferenceRun) -> Vec<usize> {
99 if run.abandoning {
100 run.work = 0;
102 run.said.clear();
103 return Vec::new();
104 }
105 if run.held {
106 return Vec::new();
107 }
108 let said = std::mem::take(&mut run.said);
111 if run.work > 0 {
112 run.work -= 1;
113 run.said.push(run.work);
114 }
115 said
116 }
117
118 fn end_run(&self, _run: ReferenceRun) -> Result<(), String> {
119 Ok(())
120 }
121}
122
123impl RunHoldAlg for ReferenceSession {
124 fn holding_is_possible(&self) -> bool {
125 true
126 }
127
128 fn hold_run(&self, run: &mut ReferenceRun, held: bool) {
129 run.held = held;
130 }
131
132 fn abandon_run(&self, run: &mut ReferenceRun) {
133 run.abandoning = true;
134 run.abandonments.set(run.abandonments.get() + 1);
135 }
136}
137
138impl AttentionAlg for ReferenceSession {
139 fn begun(&mut self, id: &usize, _holdable: bool) {
140 let request = self.request_mut(*id);
141 request.attended = true;
142 request.told.push(Telling::Begun);
143 }
144
145 fn heard(&mut self, id: &usize, _report: usize) {
146 self.request_mut(*id).told.push(Telling::Heard);
147 }
148
149 fn ran_for(&mut self, id: &usize, elapsed: Duration) {
150 self.request_mut(*id).told.push(Telling::RanFor(elapsed));
151 }
152
153 fn ended(&mut self, id: &usize, ending: Result<(), String>) {
154 let request = self.request_mut(*id);
155 request.attended = true;
157 request.told.push(match ending {
158 Ok(()) => Telling::Ended,
159 Err(_) => Telling::Refused,
160 });
161 }
162
163 fn wanted(&self, id: &usize) -> Wanted {
164 self.request(*id).wanted
165 }
166}
167
168impl ClockAlg for ReferenceSession {
169 type Moment = Duration;
170
171 fn now(&self) -> Duration {
172 self.clock
173 }
174
175 fn since(&self, moment: &Duration) -> Duration {
176 self.clock.saturating_sub(*moment)
177 }
178}
179
180impl SessionLawFixture for ReferenceSession {
181 fn law_wanting(&mut self, says: usize) -> usize {
182 self.author(says, true)
183 }
184
185 fn law_unbeginnable(&mut self) -> usize {
186 self.author(0, false)
187 }
188
189 fn law_wants(&mut self, id: &usize, wanted: Wanted) {
190 self.request_mut(*id).wanted = wanted;
191 }
192
193 fn law_passes(&mut self, elapsed: Duration) {
194 self.clock = self.clock.saturating_add(elapsed);
195 }
196
197 fn law_told(&self, id: &usize) -> Vec<Telling> {
198 self.request(*id).told.clone()
199 }
200
201 fn law_abandonments(&self, id: &usize) -> usize {
202 self.request(*id).abandonments.get()
203 }
204}