tracing_capture/predicates/
ext.rs1use std::fmt;
4
5use predicates::Predicate;
6
7use crate::{CapturedEvent, CapturedEvents, CapturedSpan, CapturedSpans, DescendantSpans, Storage};
8
9pub trait ScanExt<'a>: Sized {
16 fn scan_spans(self) -> Scanner<Self, CapturedSpans<'a>>;
20 fn scan_events(self) -> Scanner<Self, CapturedEvents<'a>>;
24}
25
26impl<'a> ScanExt<'a> for &'a Storage {
28 fn scan_spans(self) -> Scanner<Self, CapturedSpans<'a>> {
29 Scanner::new(self, Storage::all_spans)
30 }
31
32 fn scan_events(self) -> Scanner<Self, CapturedEvents<'a>> {
33 Scanner::new(self, Storage::all_events)
34 }
35}
36
37impl<'a> ScanExt<'a> for CapturedSpan<'a> {
39 fn scan_spans(self) -> Scanner<Self, CapturedSpans<'a>> {
40 Scanner::new(self, |span| span.children())
41 }
42
43 fn scan_events(self) -> Scanner<Self, CapturedEvents<'a>> {
44 Scanner::new(self, |span| span.events())
45 }
46}
47
48impl<'a> CapturedSpan<'a> {
49 pub fn deep_scan_spans(self) -> Scanner<Self, DescendantSpans<'a>> {
51 Scanner::new(self, |span| span.descendants())
52 }
53
54 pub fn deep_scan_events(self) -> Scanner<Self, impl Iterator<Item = CapturedEvent<'a>> + 'a> {
56 Scanner::new(self, |span| span.events().chain(span.descendant_events()))
57 }
58}
59
60#[derive(Debug)]
65pub struct Scanner<T, I> {
66 items: T,
67 into_iter: fn(T) -> I,
68}
69
70impl<T: Clone, I> Clone for Scanner<T, I> {
71 fn clone(&self) -> Self {
72 Self {
73 items: self.items.clone(),
74 into_iter: self.into_iter,
75 }
76 }
77}
78
79impl<T: Copy, I> Copy for Scanner<T, I> {}
80
81impl<T, I> Scanner<T, I>
82where
83 I: Iterator,
84 I::Item: fmt::Debug,
85{
86 fn new(items: T, into_iter: fn(T) -> I) -> Self {
87 Self { items, into_iter }
88 }
89
90 fn iter(self) -> I {
91 (self.into_iter)(self.items)
92 }
93
94 pub fn single<P: Predicate<I::Item> + ?Sized>(self, predicate: &P) -> I::Item {
100 let mut iter = self.iter();
101 let first = iter
102 .find(|item| predicate.eval(item))
103 .unwrap_or_else(|| panic!("no items have matched predicate {predicate}"));
104
105 let second = iter.find(|item| predicate.eval(item));
106 if let Some(second) = second {
107 panic!(
108 "multiple items match predicate {predicate}: {:#?}",
109 [first, second]
110 );
111 }
112 first
113 }
114
115 pub fn first<P: Predicate<I::Item> + ?Sized>(self, predicate: &P) -> I::Item {
121 let mut iter = self.iter();
122 iter.find(|item| predicate.eval(item))
123 .unwrap_or_else(|| panic!("no items have matched predicate {predicate}"))
124 }
125
126 pub fn all<P: Predicate<I::Item> + ?Sized>(self, predicate: &P) {
132 let mut iter = self.iter();
133 if let Some(item) = iter.find(|item| !predicate.eval(item)) {
134 panic!("item does not match predicate {predicate}: {item:#?}");
135 }
136 }
137
138 pub fn none<P: Predicate<I::Item> + ?Sized>(self, predicate: &P) {
144 let mut iter = self.iter();
145 if let Some(item) = iter.find(|item| predicate.eval(item)) {
146 panic!("item matched predicate {predicate}: {item:#?}");
147 }
148 }
149}
150
151impl<T, I> Scanner<T, I>
152where
153 I: DoubleEndedIterator,
154 I::Item: fmt::Debug,
155{
156 pub fn last<P: Predicate<I::Item> + ?Sized>(self, predicate: &P) -> I::Item {
162 let mut iter = self.iter().rev();
163 iter.find(|item| predicate.eval(item))
164 .unwrap_or_else(|| panic!("no items have matched predicate {predicate}"))
165 }
166}