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