1#![doc(html_logo_url = "https://raw.githubusercontent.com/emit-rs/emit/main/asset/logo.svg")]
14#![deny(missing_docs)]
15#![cfg_attr(not(test), no_std)]
16
17#[cfg(feature = "std")]
18extern crate std;
19
20#[cfg(feature = "alloc")]
21extern crate alloc;
22
23extern crate core;
24
25mod buf;
26
27pub mod and;
28pub mod clock;
29pub mod ctxt;
30pub mod emitter;
31pub mod empty;
32pub mod event;
33pub mod extent;
34pub mod filter;
35pub mod or;
36pub mod path;
37pub mod props;
38pub mod rng;
39pub mod runtime;
40pub mod str;
41pub mod template;
42pub mod timestamp;
43pub mod value;
44pub mod well_known;
45
46pub fn emit(
57 emitter: impl emitter::Emitter,
58 filter: impl filter::Filter,
59 ctxt: impl ctxt::Ctxt,
60 clock: impl clock::Clock,
61 evt: impl event::ToEvent,
62) {
63 use self::{extent::ToExtent, props::Props};
64
65 ctxt.with_current(|ctxt| {
66 let evt = evt.to_event();
67
68 let extent = evt.extent().cloned().or_else(|| clock.now().to_extent());
69
70 let evt = evt
71 .with_extent(extent)
72 .map_props(|props| props.and_props(ctxt));
73
74 if filter.matches(&evt) {
75 emitter.emit(evt);
76 }
77 });
78}
79
80mod internal {
81 pub struct Erased<T>(pub(crate) T);
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 use std::{cell::Cell, time::Duration};
89
90 use crate::props::Props as _;
91
92 struct MyClock(Option<timestamp::Timestamp>);
93
94 impl clock::Clock for MyClock {
95 fn now(&self) -> Option<timestamp::Timestamp> {
96 self.0
97 }
98 }
99
100 struct MyCtxt(&'static str, usize);
101
102 impl ctxt::Ctxt for MyCtxt {
103 type Current = (&'static str, usize);
104 type Frame = ();
105
106 fn open_root<P: props::Props>(&self, _: P) -> Self::Frame {}
107
108 fn enter(&self, _: &mut Self::Frame) {}
109
110 fn exit(&self, _: &mut Self::Frame) {}
111
112 fn close(&self, _: Self::Frame) {}
113
114 fn with_current<R, F: FnOnce(&Self::Current) -> R>(&self, with: F) -> R {
115 with(&(self.0, self.1))
116 }
117 }
118
119 #[test]
120 fn emit_uses_clock_ctxt() {
121 let called = Cell::new(false);
122
123 emit(
124 emitter::from_fn(|evt| {
125 assert_eq!(13, evt.props().pull::<usize, _>("ctxt_prop").unwrap());
126 assert_eq!(true, evt.props().pull::<bool, _>("evt_prop").unwrap());
127
128 assert_eq!(
129 timestamp::Timestamp::from_unix(Duration::from_secs(77)).unwrap(),
130 evt.extent().unwrap().as_point()
131 );
132
133 called.set(true);
134 }),
135 empty::Empty,
136 MyCtxt("ctxt_prop", 13),
137 MyClock(timestamp::Timestamp::from_unix(Duration::from_secs(77))),
138 event::Event::new(
139 path::Path::new_raw("test"),
140 template::Template::literal("text"),
141 empty::Empty,
142 ("evt_prop", true),
143 ),
144 );
145
146 assert!(called.get());
147 }
148
149 #[test]
150 fn emit_uses_filter() {
151 emit(
152 emitter::from_fn(|_| panic!("filter should apply")),
153 filter::from_fn(|_| false),
154 empty::Empty,
155 empty::Empty,
156 event::Event::new(
157 path::Path::new_raw("test"),
158 template::Template::literal("text"),
159 empty::Empty,
160 ("evt_prop", true),
161 ),
162 );
163 }
164}