console_subscriber/
stack.rs

1use tracing_core::span::Id;
2
3// This has been copied from tracing-subscriber. Once the library adds
4// the ability to iterate over entered spans, this code will
5// no longer be needed here
6//
7// https://github.com/tokio-rs/tracing/blob/master/tracing-subscriber/src/registry/stack.rs
8#[derive(Debug, Clone)]
9pub(crate) struct ContextId {
10    id: Id,
11    duplicate: bool,
12}
13
14impl ContextId {
15    pub fn id(&self) -> &Id {
16        &self.id
17    }
18}
19
20/// `SpanStack` tracks what spans are currently executing on a thread-local basis.
21///
22/// A "separate current span" for each thread is a semantic choice, as each span
23/// can be executing in a different thread.
24#[derive(Debug, Default)]
25pub(crate) struct SpanStack {
26    stack: Vec<ContextId>,
27}
28
29impl SpanStack {
30    #[inline]
31    pub(crate) fn push(&mut self, id: Id) -> bool {
32        let duplicate = self.stack.iter().any(|i| i.id == id);
33        self.stack.push(ContextId { id, duplicate });
34        !duplicate
35    }
36
37    /// Pop a currently entered span.
38    ///
39    /// Returns `true` if the span was actually exited.
40    #[inline]
41    pub(crate) fn pop(&mut self, expected_id: &Id) -> bool {
42        if let Some((idx, _)) = self
43            .stack
44            .iter()
45            .enumerate()
46            .rev()
47            .find(|(_, ctx_id)| ctx_id.id == *expected_id)
48        {
49            let ContextId { id: _, duplicate } = self.stack.remove(idx);
50            return !duplicate;
51        }
52        false
53    }
54
55    pub(crate) fn iter(&self) -> impl Iterator<Item = &Id> {
56        self.stack
57            .iter()
58            .filter_map(|ContextId { id, duplicate }| if *duplicate { None } else { Some(id) })
59    }
60
61    pub(crate) fn stack(&self) -> &Vec<ContextId> {
62        &self.stack
63    }
64}