1#![allow(clippy::needless_lifetimes)]
2
3#[cxx::bridge(namespace = "cloudchamber")]
4pub mod ffi {
5
6 pub struct Metadata<'a> {
7 name: &'static str,
8 target: &'a str,
9 level: Level,
10 file: &'static str,
11 line: u32,
12 fields: &'static [&'static str],
13 callsite: &'static Callsite,
14 kind: Kind,
15 }
16
17 #[namespace = "cloudchamber::detail"]
18 pub enum LevelValue {
19 ERROR,
20 WARN,
21 INFO,
22 DEBUG,
23 TRACE,
24 }
25
26 pub struct Level {
27 value: LevelValue,
28 }
29
30 #[namespace = "cloudchamber::detail"]
31 pub enum KindValue {
32 EVENT,
33 SPAN,
34 HINT,
35 }
36
37 pub struct Kind {
38 value: KindValue,
39 }
40
41 #[namespace = "cloudchamber::detail"]
42 pub enum InterestKind {
43 NEVER,
44 SOMERTIMES,
45 ALWAYS,
46 }
47
48 pub struct Interest {
49 value: InterestKind,
50 }
51
52 #[namespace = "cloudchamber::detail"]
53 pub enum FieldValueKind {
54 U8,
55 U16,
56 U32,
57 U64,
58 I8,
59 I16,
60 I32,
61 I64,
62 F32,
63 F64,
64 STRING,
65 STR,
66 BOOL,
67 DEBUG,
68 EMPTY,
69 }
70
71 unsafe extern "C++" {
72 include!("tracing-cloudchamber/src/lib.h");
73
74 type Callsite;
75
76 #[rust_name = "register"]
77 pub fn register_site(self: &Callsite) -> Interest;
78 pub fn store_interest(self: &Callsite, value: &Interest);
79 pub fn get_meta<'a>(self: &Callsite) -> &Box<RustMetadata<'a>>;
80
81 }
82
83 extern "C++" {
84 include!("tracing-cloudchamber/src/lib.h");
85
86 #[namespace = "cloudchamber::detail"]
87 type FieldValueKind;
88 }
89
90 unsafe extern "C++" {
91 include!("tracing-cloudchamber/src/lib.h");
92
93 type FieldValue;
94
95 fn get_u8(&self) -> &u8;
96 fn get_u16(&self) -> &u16;
97 fn get_u32(&self) -> &u32;
98 fn get_u64(&self) -> &u64;
99 fn get_i8(&self) -> &i8;
100 fn get_i16(&self) -> &i16;
101 fn get_i32(&self) -> &i32;
102 fn get_i64(&self) -> &i64;
103 fn get_f32(&self) -> &f32;
104 fn get_f64(&self) -> &f64;
105 fn get_bool(&self) -> &bool;
106 fn get_string(&self) -> &String;
107 fn get_str(&self) -> &String;
108 fn get_debug(&self) -> Result<&Box<DisplayValue>>;
109
110 fn get_type(&self) -> FieldValueKind;
111 }
112
113 unsafe extern "C++" {
114 type ScopeLambda;
115 fn call(&self);
116 }
117
118 extern "Rust" {
119 type DisplayValue;
120 pub fn string_to_display_value(value: String) -> Box<DisplayValue>;
121 }
122
123 extern "Rust" {
124 fn as_str(self: &Level) -> &'static str;
125
126 type RustMetadata<'a>;
127 unsafe fn new_rust_metadata<'a>(meta: &'static Metadata<'a>) -> Box<RustMetadata<'a>>;
128
129 fn is_enabled(self: &Level) -> bool;
131
132 fn default_enabled_for_meta(interest: &Interest, meta: &Box<RustMetadata>) -> bool;
133 fn dispatch_tracing_event(meta: &'static Box<RustMetadata>);
134 fn dispatch_tracing_event1(meta: &'static Box<RustMetadata>, f1: &FieldValue);
135 fn dispatch_tracing_event2(
136 meta: &'static Box<RustMetadata>,
137 f1: &FieldValue,
138 f2: &FieldValue,
139 );
140 fn dispatch_tracing_event3(
141 meta: &'static Box<RustMetadata>,
142 f1: &FieldValue,
143 f2: &FieldValue,
144 f3: &FieldValue,
145 );
146 fn dispatch_tracing_event4(
147 meta: &'static Box<RustMetadata>,
148 f1: &FieldValue,
149 f2: &FieldValue,
150 f3: &FieldValue,
151 f4: &FieldValue,
152 );
153 fn dispatch_tracing_event5(
154 meta: &'static Box<RustMetadata>,
155 f1: &FieldValue,
156 f2: &FieldValue,
157 f3: &FieldValue,
158 f4: &FieldValue,
159 f5: &FieldValue,
160 );
161 fn dispatch_tracing_event6(
162 meta: &'static Box<RustMetadata>,
163 f1: &FieldValue,
164 f2: &FieldValue,
165 f3: &FieldValue,
166 f4: &FieldValue,
167 f5: &FieldValue,
168 f6: &FieldValue,
169 );
170 #[allow(clippy::too_many_arguments)]
171 fn dispatch_tracing_event7(
172 meta: &'static Box<RustMetadata>,
173 f1: &FieldValue,
174 f2: &FieldValue,
175 f3: &FieldValue,
176 f4: &FieldValue,
177 f5: &FieldValue,
178 f6: &FieldValue,
179 f7: &FieldValue,
180 );
181 #[allow(clippy::too_many_arguments)]
182 fn dispatch_tracing_event8(
183 meta: &'static Box<RustMetadata>,
184 f1: &FieldValue,
185 f2: &FieldValue,
186 f3: &FieldValue,
187 f4: &FieldValue,
188 f5: &FieldValue,
189 f6: &FieldValue,
190 f7: &FieldValue,
191 f8: &FieldValue,
192 );
193 #[allow(clippy::too_many_arguments)]
194 fn dispatch_tracing_event9(
195 meta: &'static Box<RustMetadata>,
196 f1: &FieldValue,
197 f2: &FieldValue,
198 f3: &FieldValue,
199 f4: &FieldValue,
200 f5: &FieldValue,
201 f6: &FieldValue,
202 f7: &FieldValue,
203 f8: &FieldValue,
204 f9: &FieldValue,
205 );
206 #[allow(clippy::too_many_arguments)]
207 fn dispatch_tracing_event10(
208 meta: &'static Box<RustMetadata>,
209 f1: &FieldValue,
210 f2: &FieldValue,
211 f3: &FieldValue,
212 f4: &FieldValue,
213 f5: &FieldValue,
214 f6: &FieldValue,
215 f7: &FieldValue,
216 f8: &FieldValue,
217 f9: &FieldValue,
218 f10: &FieldValue,
219 );
220 }
221
222 extern "Rust" {
223
224 type Span;
225 type Entered<'a>;
226
227 unsafe fn enter<'a>(self: &'a Span) -> Box<Entered<'a>>;
229 pub fn has_field(self: &Span, field: &str) -> bool;
233 pub unsafe fn record<'a>(self: &'a Span, field: &'a str, value: &'a FieldValue)
240 -> &'a Span;
241 pub fn is_none(self: &Span) -> bool;
243 pub fn is_disabeld(self: &Span) -> bool;
245 fn in_scope(self: &Span, f: &ScopeLambda);
249
250 fn new_disabled_span(meta: &'static Box<RustMetadata>) -> Box<Span>;
251 fn current_span() -> Box<Span>;
252
253 fn new_span(meta: &'static Box<RustMetadata>) -> Box<Span>;
254 fn new_span1(meta: &'static Box<RustMetadata>, f1: &FieldValue) -> Box<Span>;
255 fn new_span2(
256 meta: &'static Box<RustMetadata>,
257 f1: &FieldValue,
258 f2: &FieldValue,
259 ) -> Box<Span>;
260 fn new_span3(
261 meta: &'static Box<RustMetadata>,
262 f1: &FieldValue,
263 f2: &FieldValue,
264 f3: &FieldValue,
265 ) -> Box<Span>;
266 fn new_span4(
267 meta: &'static Box<RustMetadata>,
268 f1: &FieldValue,
269 f2: &FieldValue,
270 f3: &FieldValue,
271 f4: &FieldValue,
272 ) -> Box<Span>;
273 fn new_span5(
274 meta: &'static Box<RustMetadata>,
275 f1: &FieldValue,
276 f2: &FieldValue,
277 f3: &FieldValue,
278 f4: &FieldValue,
279 f5: &FieldValue,
280 ) -> Box<Span>;
281 fn new_span6(
282 meta: &'static Box<RustMetadata>,
283 f1: &FieldValue,
284 f2: &FieldValue,
285 f3: &FieldValue,
286 f4: &FieldValue,
287 f5: &FieldValue,
288 f6: &FieldValue,
289 ) -> Box<Span>;
290 #[allow(clippy::too_many_arguments)]
291 fn new_span7(
292 meta: &'static Box<RustMetadata>,
293 f1: &FieldValue,
294 f2: &FieldValue,
295 f3: &FieldValue,
296 f4: &FieldValue,
297 f5: &FieldValue,
298 f6: &FieldValue,
299 f7: &FieldValue,
300 ) -> Box<Span>;
301 #[allow(clippy::too_many_arguments)]
302 fn new_span8(
303 meta: &'static Box<RustMetadata>,
304 f1: &FieldValue,
305 f2: &FieldValue,
306 f3: &FieldValue,
307 f4: &FieldValue,
308 f5: &FieldValue,
309 f6: &FieldValue,
310 f7: &FieldValue,
311 f8: &FieldValue,
312 ) -> Box<Span>;
313 #[allow(clippy::too_many_arguments)]
314 fn new_span9(
315 meta: &'static Box<RustMetadata>,
316 f1: &FieldValue,
317 f2: &FieldValue,
318 f3: &FieldValue,
319 f4: &FieldValue,
320 f5: &FieldValue,
321 f6: &FieldValue,
322 f7: &FieldValue,
323 f8: &FieldValue,
324 f9: &FieldValue,
325 ) -> Box<Span>;
326 #[allow(clippy::too_many_arguments)]
327 fn new_span10(
328 meta: &'static Box<RustMetadata>,
329 f1: &FieldValue,
330 f2: &FieldValue,
331 f3: &FieldValue,
332 f4: &FieldValue,
333 f5: &FieldValue,
334 f6: &FieldValue,
335 f7: &FieldValue,
336 f8: &FieldValue,
337 f9: &FieldValue,
338 f10: &FieldValue,
339 ) -> Box<Span>;
340 }
341}
342
343unsafe impl Sync for ffi::Callsite {}
344unsafe impl Send for ffi::Callsite {}
345
346impl ffi::Level {
347 #[allow(dead_code)]
348 const ERROR: Self = Self {
349 value: ffi::LevelValue::ERROR,
350 };
351 #[allow(dead_code)]
352 const WARN: Self = Self {
353 value: ffi::LevelValue::WARN,
354 };
355 #[allow(dead_code)]
356 const INFO: Self = Self {
357 value: ffi::LevelValue::INFO,
358 };
359 #[allow(dead_code)]
360 const DEBUG: Self = Self {
361 value: ffi::LevelValue::DEBUG,
362 };
363 #[allow(dead_code)]
364 const TRACE: Self = Self {
365 value: ffi::LevelValue::TRACE,
366 };
367
368 pub fn as_str(&self) -> &'static str {
369 match self.value {
370 ffi::LevelValue::ERROR => tracing::Level::ERROR.as_str(),
371 ffi::LevelValue::WARN => tracing::Level::WARN.as_str(),
372 ffi::LevelValue::INFO => tracing::Level::INFO.as_str(),
373 ffi::LevelValue::DEBUG => tracing::Level::DEBUG.as_str(),
374 ffi::LevelValue::TRACE => tracing::Level::TRACE.as_str(),
375 _ => "unknown",
376 }
377 }
378
379 pub fn is_enabled(&self) -> bool {
380 let tlevel: tracing::Level = self.into();
381 tlevel <= tracing::level_filters::STATIC_MAX_LEVEL
382 && tlevel <= tracing::level_filters::LevelFilter::current()
383 }
384}
385
386impl From<&ffi::Level> for tracing::Level {
387 fn from(value: &ffi::Level) -> Self {
388 match value.value {
389 ffi::LevelValue::ERROR => tracing::Level::ERROR,
390 ffi::LevelValue::WARN => tracing::Level::WARN,
391 ffi::LevelValue::INFO => tracing::Level::INFO,
392 ffi::LevelValue::DEBUG => tracing::Level::DEBUG,
393 ffi::LevelValue::TRACE => tracing::Level::TRACE,
394 _ => tracing::Level::TRACE,
395 }
396 }
397}
398
399impl ffi::Kind {
400 #[allow(dead_code)]
401 const EVENT: Self = Self {
402 value: ffi::KindValue::EVENT,
403 };
404 #[allow(dead_code)]
405 const SPAN: Self = Self {
406 value: ffi::KindValue::SPAN,
407 };
408 #[allow(dead_code)]
409 const HINT: Self = Self {
410 value: ffi::KindValue::HINT,
411 };
412
413 pub fn is_span(&self) -> bool {
414 matches!(self.value, ffi::KindValue::SPAN)
415 }
416 pub fn is_event(&self) -> bool {
417 matches!(self.value, ffi::KindValue::EVENT)
418 }
419 pub fn is_hint(&self) -> bool {
420 !matches!(self.value, ffi::KindValue::SPAN) && !matches!(self.value, ffi::KindValue::EVENT)
421 }
422}
423
424impl From<&ffi::Kind> for tracing::metadata::Kind {
425 fn from(value: &ffi::Kind) -> Self {
426 match value.value {
427 ffi::KindValue::EVENT => tracing::metadata::Kind::EVENT,
428 ffi::KindValue::SPAN => tracing::metadata::Kind::SPAN,
429 ffi::KindValue::HINT => tracing::metadata::Kind::HINT,
430 _ => tracing::metadata::Kind::HINT,
431 }
432 }
433}
434
435impl From<&ffi::Interest> for tracing_core::Interest {
436 fn from(value: &ffi::Interest) -> Self {
437 match value.value {
438 ffi::InterestKind::NEVER => tracing_core::Interest::never(),
439 ffi::InterestKind::SOMERTIMES => tracing_core::Interest::sometimes(),
440 ffi::InterestKind::ALWAYS => tracing_core::Interest::always(),
441 _ => tracing_core::Interest::sometimes(),
442 }
443 }
444}
445impl From<&tracing_core::Interest> for ffi::Interest {
446 fn from(value: &tracing_core::Interest) -> Self {
447 if value.is_never() {
448 ffi::Interest {
449 value: ffi::InterestKind::NEVER,
450 }
451 } else if value.is_always() {
452 ffi::Interest {
453 value: ffi::InterestKind::ALWAYS,
454 }
455 } else {
456 ffi::Interest {
457 value: ffi::InterestKind::SOMERTIMES,
458 }
459 }
460 }
461}
462
463impl<'a> From<&ffi::Metadata<'a>> for tracing::Metadata<'a> {
464 fn from(value: &ffi::Metadata<'a>) -> Self {
465 tracing::Metadata::new(
466 value.name,
467 value.target,
468 (&value.level).into(),
469 Some(value.file),
470 Some(value.line),
471 None,
472 tracing::field::FieldSet::new(
473 value.fields,
474 tracing::callsite::Identifier(value.callsite),
475 ),
476 (&value.kind).into(),
477 )
478 }
479}
480
481pub struct RustMetadata<'a>(pub tracing::Metadata<'a>);
482
483impl<'a> RustMetadata<'a> {
484 pub fn new(meta: &'static ffi::Metadata<'a>) -> Box<Self> {
485 Box::new(Self(meta.into()))
486 }
487}
488
489fn new_rust_metadata<'a>(meta: &'static ffi::Metadata<'a>) -> Box<RustMetadata<'a>> {
490 RustMetadata::new(meta)
491}
492
493impl ffi::Callsite {
494 #[allow(dead_code)]
495 const UNREGISTERED: u8 = 0;
496 #[allow(dead_code)]
497 const REGISTERING: u8 = 1;
498 #[allow(dead_code)]
499 const REGISTERED: u8 = 2;
500
501 #[allow(dead_code)]
502 const INTEREST_NEVER: u8 = 0;
503 #[allow(dead_code)]
504 const INTEREST_SOMETIMES: u8 = 1;
505 #[allow(dead_code)]
506 const INTEREST_ALWAYS: u8 = 2;
507 #[allow(dead_code)]
508 const INTEREST_EMPTY: u8 = 0xFF;
509}
510
511impl tracing::Callsite for ffi::Callsite {
512 #[inline(always)]
513 fn metadata(&self) -> &tracing::Metadata<'_> {
514 &self.get_meta().as_ref().0
515 }
516 fn set_interest(&self, interest: tracing_core::Interest) {
517 self.store_interest(&(&interest).into());
518 }
519}
520
521#[allow(clippy::borrowed_box)]
522fn default_enabled_for_meta(interest: &ffi::Interest, meta: &Box<RustMetadata>) -> bool {
523 let interest: tracing_core::Interest = interest.into();
524 let meta = &meta.as_ref().0;
525 interest.is_always() || tracing::dispatcher::get_default(|default| default.enabled(meta))
526}
527
528#[allow(clippy::borrowed_box)]
529fn dispatch_tracing_event(meta: &'static Box<RustMetadata>) {
530 tracing::Event::dispatch(&meta.0, &meta.0.fields().value_set(&[]));
531}
532
533macro_rules! dispatch_tracing_eventN {
534 ($name:ident, ($($fN:ident),*)) => {
535 #[allow(clippy::borrowed_box)]
536 #[allow(clippy::too_many_arguments)]
537 fn $name (meta: &'static Box<RustMetadata> $(, $fN : &ffi::FieldValue )*) {
538 let mut iter = meta.0.fields().iter();
539 let pairs = [
540 $(
541 (
542 &::core::iter::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
543 $fN.as_value(),
544 )
545 ),*
546 ];
547 let val_set = meta.0.fields().value_set(&pairs);
548 tracing::Event::dispatch(&meta.0, &val_set);
549 }
550 };
551}
552
553dispatch_tracing_eventN! {dispatch_tracing_event1, (f1)}
554dispatch_tracing_eventN! {dispatch_tracing_event2, (f1, f2)}
555dispatch_tracing_eventN! {dispatch_tracing_event3, (f1, f2, f3)}
556dispatch_tracing_eventN! {dispatch_tracing_event4, (f1, f2, f3, f4)}
557dispatch_tracing_eventN! {dispatch_tracing_event5, (f1, f2, f3, f4, f5)}
558dispatch_tracing_eventN! {dispatch_tracing_event6, (f1, f2, f3, f4, f5, f6)}
559dispatch_tracing_eventN! {dispatch_tracing_event7, (f1, f2, f3, f4, f5, f6, f7)}
560dispatch_tracing_eventN! {dispatch_tracing_event8, (f1, f2, f3, f4, f5, f6, f7, f8)}
561dispatch_tracing_eventN! {dispatch_tracing_event9, (f1, f2, f3, f4, f5, f6, f7, f8, f9)}
562dispatch_tracing_eventN! {dispatch_tracing_event10, (f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)}
563
564pub struct DisplayValue(Box<dyn tracing::Value>);
565pub fn string_to_display_value(value: String) -> Box<DisplayValue> {
566 Box::new(DisplayValue(Box::new(tracing::field::display(value))))
567}
568
569impl DisplayValue {
570 pub fn as_value(&self) -> &dyn tracing::Value {
571 &self.0
572 }
573}
574
575impl ffi::FieldValue {
576 fn as_value(&self) -> Option<&dyn tracing::field::Value> {
577 match self.get_type() {
578 ffi::FieldValueKind::U8 => Some(self.get_u8() as &dyn tracing::field::Value),
579 ffi::FieldValueKind::U16 => Some(self.get_u16() as &dyn tracing::field::Value),
580 ffi::FieldValueKind::U32 => Some(self.get_u32() as &dyn tracing::field::Value),
581 ffi::FieldValueKind::U64 => Some(self.get_u64() as &dyn tracing::field::Value),
582 ffi::FieldValueKind::I8 => Some(self.get_i8() as &dyn tracing::field::Value),
583 ffi::FieldValueKind::I16 => Some(self.get_i16() as &dyn tracing::field::Value),
584 ffi::FieldValueKind::I32 => Some(self.get_i32() as &dyn tracing::field::Value),
585 ffi::FieldValueKind::I64 => Some(self.get_i64() as &dyn tracing::field::Value),
586 ffi::FieldValueKind::F32 => Some(self.get_f32() as &dyn tracing::field::Value),
587 ffi::FieldValueKind::F64 => Some(self.get_f64() as &dyn tracing::field::Value),
588 ffi::FieldValueKind::STRING => Some(self.get_string() as &dyn tracing::field::Value),
589 ffi::FieldValueKind::STR => Some(self.get_str() as &dyn tracing::field::Value),
590 ffi::FieldValueKind::BOOL => Some(self.get_bool() as &dyn tracing::field::Value),
591 ffi::FieldValueKind::DEBUG => match self.get_debug() {
592 Ok(s) => Some(s.as_value()),
593 Err(_) => None,
594 },
595 ffi::FieldValueKind::EMPTY => None, _ => None,
597 }
598 }
599}
600
601pub struct Span(tracing::Span);
602
603#[allow(clippy::borrowed_box)]
604fn new_span(meta: &'static Box<RustMetadata>) -> Box<Span> {
605 Box::new(Span(tracing::Span::new(
606 &meta.0,
607 &meta.0.fields().value_set(&[]),
608 )))
609}
610#[allow(clippy::borrowed_box)]
611fn new_disabled_span(meta: &'static Box<RustMetadata>) -> Box<Span> {
612 Box::new(Span(tracing::Span::new_disabled(&meta.0)))
613}
614
615fn current_span() -> Box<Span> {
616 Box::new(Span(tracing::Span::current()))
617}
618
619macro_rules! new_spanN {
620 ($name:ident, ($($fN:ident),*)) => {
621 #[allow(clippy::borrowed_box)]
622 #[allow(clippy::too_many_arguments)]
623 fn $name (meta: &'static Box<RustMetadata> $(, $fN : &ffi::FieldValue )*) -> Box<Span> {
624 let mut iter = meta.0.fields().iter();
625 let pairs = [
626 $(
627 (
628 &::core::iter::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
629 $fN.as_value(),
630 )
631 ),*
632 ];
633 let val_set = meta.0.fields().value_set(&pairs);
634 Box::new(Span(tracing::Span::new(
635 &meta.0,
636 &val_set,
637 )))
638 }
639 };
640}
641
642new_spanN! {new_span1, (f1)}
643new_spanN! {new_span2, (f1, f2)}
644new_spanN! {new_span3, (f1, f2, f3)}
645new_spanN! {new_span4, (f1, f2, f3, f4)}
646new_spanN! {new_span5, (f1, f2, f3, f4, f5)}
647new_spanN! {new_span6, (f1, f2, f3, f4, f5, f6)}
648new_spanN! {new_span7, (f1, f2, f3, f4, f5, f6, f7)}
649new_spanN! {new_span8, (f1, f2, f3, f4, f5, f6, f7, f8)}
650new_spanN! {new_span9, (f1, f2, f3, f4, f5, f6, f7, f8, f9)}
651new_spanN! {new_span10, (f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)}
652
653pub struct Entered<'a>(#[allow(dead_code)] tracing::span::Entered<'a>);
654
655impl Span {
656 pub fn enter(&self) -> Box<Entered> {
657 Box::new(Entered(self.0.enter()))
658 }
659
660 pub fn has_field(&self, field: &str) -> bool {
661 self.0.has_field(field)
662 }
663
664 pub fn record(&self, field: &str, value: &ffi::FieldValue) -> &Self {
665 self.0.record(field, value.as_value());
666 self
667 }
668 pub fn is_none(&self) -> bool {
669 self.0.is_none()
670 }
671
672 pub fn is_disabeld(&self) -> bool {
673 self.0.is_disabled()
674 }
675
676 fn in_scope(&self, f: &ffi::ScopeLambda) {
677 let _guard = self.0.enter();
678 f.call();
679 }
680}
681
682mod unused {
684 #[allow(dead_code)]
685 fn test_tracing_event() {
686 tracing::event!(tracing::Level::INFO, test = 5, "messge in event");
687 }
688 #[allow(dead_code)]
689 fn test_tracing_span() {
690 let v = 5;
691 let _span = tracing::span!(tracing::Level::TRACE, "name of span", v);
692 }
693}