msgpack-tracing 0.1.2

Compact storage for tracing using msgpack
Documentation
use crate::tape::{Instruction, InstructionSet, SpanRecords, TapeMachine};
use std::{collections::HashMap, num::NonZeroU64};

pub struct RestartableMachine<T> {
    forward: T,
    span: HashMap<NonZeroU64, SpanRecords>,
    current_span: Option<(NonZeroU64, SpanRecords)>,
}
impl<T> RestartableMachine<T>
where
    T: TapeMachine<InstructionSet>,
{
    pub fn new(forward: T) -> Self {
        Self {
            forward,
            span: Default::default(),
            current_span: None,
        }
    }
}
impl<T> TapeMachine<InstructionSet> for RestartableMachine<T>
where
    T: TapeMachine<InstructionSet>,
{
    fn needs_restart(&mut self) -> bool {
        self.forward.needs_restart()
    }

    fn handle(&mut self, instruction: Instruction) {
        match instruction {
            Instruction::Restart => {
                self.forward.handle(Instruction::Restart);

                for (span, records) in self.span.iter() {
                    self.forward.handle(Instruction::NewSpan {
                        parent: records.parent,
                        span: *span,
                        name: records.name.as_ref(),
                    });

                    for record in records.records.iter() {
                        self.forward.handle(Instruction::AddValue(record.as_ref()));
                    }

                    self.forward.handle(Instruction::FinishedSpan);
                }
            }
            Instruction::NewSpan { parent, span, name } => {
                assert!(self.current_span.is_none());
                self.current_span = Some((
                    span,
                    SpanRecords {
                        parent,
                        name: name.to_owned(),
                        records: Default::default(),
                    },
                ));

                self.forward
                    .handle(Instruction::NewSpan { parent, span, name });
            }
            Instruction::FinishedSpan => {
                let (k, v) = self.current_span.take().unwrap();
                self.span.insert(k, v);
                self.forward.handle(Instruction::FinishedSpan)
            }
            Instruction::NewRecord(span) => {
                assert!(self.current_span.is_none());
                self.current_span = Some(self.span.remove_entry(&span).unwrap());
                self.forward.handle(Instruction::NewRecord(span));
            }
            Instruction::FinishedRecord => {
                let (k, v) = self.current_span.take().unwrap();
                self.span.insert(k, v);
                self.forward.handle(Instruction::FinishedRecord)
            }
            Instruction::StartEvent {
                time,
                span,
                target,
                priority,
            } => {
                self.forward.handle(Instruction::StartEvent {
                    time,
                    span,
                    target,
                    priority,
                });
            }
            Instruction::FinishedEvent => self.forward.handle(Instruction::FinishedEvent),
            Instruction::AddValue(field_value) => {
                if let Some((_, current_span)) = self.current_span.as_mut() {
                    current_span.records.push(field_value.to_owned());
                }
                self.forward.handle(Instruction::AddValue(field_value));
            }
            Instruction::DeleteSpan(span) => {
                self.span.remove(&span);
                self.forward.handle(Instruction::DeleteSpan(span));
            }
        }
    }
}