1use std::io::BufRead;
7
8use capnp::serialize_packed;
9
10use crate::entity::Capacity;
11use crate::gwr_track_capnp::log::LogLevel;
12use crate::{Id, gwr_track_capnp};
13
14pub trait TraceVisitor {
20 fn log(&mut self, id: Id, level: log::Level, message: &str) {
28 let _ = id;
30 let _ = level;
31 let _ = message;
32 }
33
34 fn create_entity(&mut self, created_by: Id, id: Id, name: &str) {
42 let _ = created_by;
43 let _ = id;
44 let _ = name;
45 }
46
47 fn create_monitor(&mut self, created_by: Id, id: Id, name: &str) {
55 let _ = created_by;
56 let _ = id;
57 let _ = name;
58 }
59
60 fn create_lane(&mut self, created_by: Id, id: Id, name: &str) {
68 let _ = created_by;
69 let _ = id;
70 let _ = name;
71 }
72
73 fn create_group(&mut self, created_by: Id, id: Id, name: &str) {
81 let _ = created_by;
82 let _ = id;
83 let _ = name;
84 }
85
86 fn create_object(
97 &mut self,
98 created_by: Id,
99 id: Id,
100 size: usize,
101 units: &str,
102 req_type: u8,
103 details: &str,
104 ) {
105 let _ = created_by;
106 let _ = id;
107 let _ = size;
108 let _ = units;
109 let _ = req_type;
110 let _ = details;
111 }
112
113 fn destroy(&mut self, destroyed_by: Id, id: Id) {
120 let _ = destroyed_by;
122 let _ = id;
123 }
124
125 fn connect(&mut self, connect_from: Id, connect_to: Id) {
132 let _ = connect_from;
134 let _ = connect_to;
135 }
136
137 fn enter(&mut self, id: Id, entered: Id) {
144 let _ = id;
146 let _ = entered;
147 }
148
149 fn exit(&mut self, id: Id, exited: Id) {
156 let _ = id;
158 let _ = exited;
159 }
160
161 fn value(&mut self, id: Id, value: f64) {
168 let _ = id;
170 let _ = value;
171 }
172
173 fn add_to_group(&mut self, id: Id, group_id: Id) {
180 let _ = id;
181 let _ = group_id;
182 }
183
184 fn remove_from_group(&mut self, id: Id, group_id: Id) {
191 let _ = id;
192 let _ = group_id;
193 }
194
195 fn begin_activity(&mut self, activity: Id, lane: Id, name: &str) {
203 let _ = activity;
204 let _ = lane;
205 let _ = name;
206 }
207
208 fn end_activity(&mut self, activity: Id) {
214 let _ = activity;
215 }
216
217 fn capacity(&mut self, id: Id, capacity: Capacity) {
224 let _ = id;
226 let _ = capacity;
227 }
228
229 fn time(&mut self, id: Id, time_ns: f64) {
236 let _ = id;
238 let _ = time_ns;
239 }
240}
241
242pub fn process_capnp<R>(mut reader: R, visitor: &mut dyn TraceVisitor)
282where
283 R: BufRead,
284{
285 while let Ok(event_reader) =
286 serialize_packed::read_message(&mut reader, ::capnp::message::ReaderOptions::new())
287 {
288 let event = event_reader
289 .get_root::<gwr_track_capnp::event::Reader>()
290 .expect("should be able to parse event");
291
292 let id = Id(event.get_id());
293 match event.which() {
294 Ok(gwr_track_capnp::event::Which::Log(builder)) => handle_log(visitor, id, builder),
295 Ok(gwr_track_capnp::event::Which::Create(builder)) => {
296 handle_create(visitor, id, builder);
297 }
298 Ok(gwr_track_capnp::event::Which::Destroy(destroyed_by)) => {
299 handle_destroy(visitor, id, destroyed_by);
300 }
301 Ok(gwr_track_capnp::event::Which::Connect(connect_to)) => {
302 handle_connect(visitor, id, connect_to);
303 }
304 Ok(gwr_track_capnp::event::Which::Enter(entered)) => handle_enter(visitor, id, entered),
305 Ok(gwr_track_capnp::event::Which::Exit(exited)) => handle_exit(visitor, id, exited),
306 Ok(gwr_track_capnp::event::Which::Value(value)) => handle_value(visitor, id, value),
307 Ok(gwr_track_capnp::event::Which::AddToGroup(group_id)) => {
308 handle_add_to_group(visitor, id, group_id);
309 }
310 Ok(gwr_track_capnp::event::Which::RemoveFromGroup(group_id)) => {
311 handle_remove_from_group(visitor, id, group_id);
312 }
313 Ok(gwr_track_capnp::event::Which::BeginActivity(begin_activity)) => {
314 handle_begin_activity(visitor, id, begin_activity);
315 }
316 Ok(gwr_track_capnp::event::Which::EndActivity(())) => {
317 handle_end_activity(visitor, id);
318 }
319 Ok(gwr_track_capnp::event::Which::Capacity(capacity)) => {
320 handle_capacity(visitor, id, capacity);
321 }
322 Ok(gwr_track_capnp::event::Which::Time(time)) => handle_time(visitor, id, time),
323 Err(e) => {
324 panic!("should be able to parse event ({e})");
325 }
326 }
327 }
328}
329
330fn handle_log(
331 visitor: &mut dyn TraceVisitor,
332 id: Id,
333 builder: capnp::Result<gwr_track_capnp::log::Reader<'_>>,
334) {
335 let access = builder.expect("should be able to parse Log event");
336 visitor.log(
337 id,
338 to_log_level(
339 access
340 .get_level()
341 .expect("should be able to parse Log level"),
342 ),
343 access
344 .get_message()
345 .expect("should be able to parse Log message")
346 .to_str()
347 .expect("Log message should be valid UTF-8 string"),
348 );
349}
350
351fn handle_create(
352 visitor: &mut dyn TraceVisitor,
353 id: Id,
354 builder: capnp::Result<gwr_track_capnp::create::Reader<'_>>,
355) {
356 let access = builder.expect("should be able to parse Create event");
357 let created_id = Id(access.get_id());
358 match access.which() {
359 Ok(gwr_track_capnp::create::Which::Entity(entity)) => {
360 let entity = entity.expect("should be able to parse Create Entity");
361 visitor.create_entity(
362 id,
363 created_id,
364 entity
365 .get_name()
366 .expect("should be able to parse Entity name")
367 .to_str()
368 .expect("Create Entity name should be valid UTF-8 string"),
369 );
370 }
371 Ok(gwr_track_capnp::create::Which::Monitor(monitor)) => {
372 let monitor = monitor.expect("should be able to parse Create Monitor");
373 visitor.create_monitor(
374 id,
375 created_id,
376 monitor
377 .get_name()
378 .expect("should be able to parse Monitor name")
379 .to_str()
380 .expect("Create Monitor name should be valid UTF-8 string"),
381 );
382 }
383 Ok(gwr_track_capnp::create::Which::Lane(lane)) => {
384 let lane = lane.expect("should be able to parse Create Lane");
385 visitor.create_lane(
386 id,
387 created_id,
388 lane.get_name()
389 .expect("should be able to parse Lane name")
390 .to_str()
391 .expect("Create Lane name should be valid UTF-8 string"),
392 );
393 }
394 Ok(gwr_track_capnp::create::Which::Group(group)) => {
395 let group = group.expect("should be able to parse Create Group");
396 visitor.create_group(
397 id,
398 created_id,
399 group
400 .get_name()
401 .expect("should be able to parse Group name")
402 .to_str()
403 .expect("Create Group name should be valid UTF-8 string"),
404 );
405 }
406 Ok(gwr_track_capnp::create::Which::Object(object)) => {
407 let object = object.expect("should be able to parse Create Object");
408 visitor.create_object(
409 id,
410 created_id,
411 object.get_size() as usize,
412 object
413 .get_units()
414 .expect("should be able to parse Object units")
415 .to_str()
416 .expect("Create Object units should be valid UTF-8 string"),
417 object.get_type(),
418 object
419 .get_details()
420 .expect("should be able to parse Object details")
421 .to_str()
422 .expect("Create Object details should be valid UTF-8 string"),
423 );
424 }
425 Err(e) => panic!("should be able to parse create event ({e})"),
426 }
427}
428
429fn handle_destroy(visitor: &mut dyn TraceVisitor, id: Id, destroyed_by: u64) {
430 visitor.destroy(id, Id(destroyed_by));
431}
432
433fn handle_connect(visitor: &mut dyn TraceVisitor, id: Id, connect_to: u64) {
434 visitor.connect(id, Id(connect_to));
435}
436
437fn handle_enter(visitor: &mut dyn TraceVisitor, id: Id, entered: u64) {
438 visitor.enter(id, Id(entered));
439}
440
441fn handle_exit(visitor: &mut dyn TraceVisitor, id: Id, exited: u64) {
442 visitor.exit(id, Id(exited));
443}
444
445fn handle_value(visitor: &mut dyn TraceVisitor, id: Id, value: f64) {
446 visitor.value(id, value);
447}
448
449fn handle_add_to_group(visitor: &mut dyn TraceVisitor, id: Id, group_id: u64) {
450 visitor.add_to_group(id, Id(group_id));
451}
452
453fn handle_remove_from_group(visitor: &mut dyn TraceVisitor, id: Id, group_id: u64) {
454 visitor.remove_from_group(id, Id(group_id));
455}
456
457fn handle_begin_activity(
458 visitor: &mut dyn TraceVisitor,
459 id: Id,
460 begin_activity: capnp::Result<gwr_track_capnp::begin_activity::Reader<'_>>,
461) {
462 let begin_activity = begin_activity.expect("should be able to parse BeginActivity event");
463 visitor.begin_activity(
464 id,
465 Id(begin_activity.get_lane()),
466 begin_activity
467 .get_name()
468 .expect("should be able to parse activity name")
469 .to_str()
470 .expect("Activity name should be valid UTF-8 string"),
471 );
472}
473
474fn handle_end_activity(visitor: &mut dyn TraceVisitor, id: Id) {
475 visitor.end_activity(id);
476}
477
478fn handle_capacity(
479 visitor: &mut dyn TraceVisitor,
480 id: Id,
481 capacity: capnp::Result<gwr_track_capnp::capacity::Reader<'_>>,
482) {
483 let capacity = capacity.expect("should be able to parse Capacity event");
484 visitor.capacity(
485 id,
486 Capacity::new(
487 capacity.get_value() as usize,
488 capacity
489 .get_units()
490 .expect("should be able to parse Capacity units")
491 .to_str()
492 .expect("Capacity units should be valid UTF-8 string"),
493 ),
494 );
495}
496
497fn handle_time(visitor: &mut dyn TraceVisitor, id: Id, time: f64) {
498 visitor.time(id, time);
499}
500
501fn to_log_level(level: LogLevel) -> log::Level {
502 match level {
503 LogLevel::Error => log::Level::Error,
504 LogLevel::Warn => log::Level::Warn,
505 LogLevel::Info => log::Level::Info,
506 LogLevel::Debug => log::Level::Debug,
507 LogLevel::Trace => log::Level::Trace,
508 }
509}