1use std::error::Error;
4use std::fmt::Arguments;
5use std::fmt::Debug;
6use std::fmt::Result;
7
8use tracing::field::Field;
9use tracing::field::Visit;
10use tracing::Event;
11use tracing::Subscriber;
12use tracing_subscriber::fmt::format::FormatFields;
13use tracing_subscriber::fmt::format::Writer;
14use tracing_subscriber::fmt::FmtContext;
15use tracing_subscriber::fmt::FormatEvent;
16use tracing_subscriber::registry::LookupSpan;
17
18
19#[derive(Debug)]
22struct Visitor<'w> {
23 writer: Writer<'w>,
24}
25
26impl<'w> Visitor<'w> {
27 fn new(writer: Writer<'w>) -> Self {
28 Self { writer }
29 }
30
31 fn record_value(&mut self, field: &Field, value: Arguments<'_>) {
32 let name = field.name();
33 if name == "message" {
36 let _result = writeln!(self.writer, "cargo:warning={value}");
37 } else {
38 let _result = writeln!(self.writer, "cargo:warning={name}={value}");
39 }
40 }
41}
42
43impl Visit for Visitor<'_> {
44 fn record_debug(&mut self, field: &Field, value: &dyn Debug) {
45 self.record_value(field, format_args!("{value:?}"))
46 }
47
48 fn record_f64(&mut self, field: &Field, value: f64) {
49 self.record_value(field, format_args!("{value}"))
50 }
51
52 fn record_i64(&mut self, field: &Field, value: i64) {
53 self.record_value(field, format_args!("{value}"))
54 }
55
56 fn record_u64(&mut self, field: &Field, value: u64) {
57 self.record_value(field, format_args!("{value}"))
58 }
59
60 fn record_i128(&mut self, field: &Field, value: i128) {
61 self.record_value(field, format_args!("{value}"))
62 }
63
64 fn record_u128(&mut self, field: &Field, value: u128) {
65 self.record_value(field, format_args!("{value}"))
66 }
67
68 fn record_bool(&mut self, field: &Field, value: bool) {
69 self.record_value(field, format_args!("{value}"))
70 }
71
72 fn record_str(&mut self, field: &Field, value: &str) {
73 self.record_value(field, format_args!("{value}"))
74 }
75
76 fn record_error(&mut self, field: &Field, value: &(dyn Error + 'static)) {
77 self.record_value(field, format_args!("{value}"))
78 }
79}
80
81
82#[derive(Debug)]
100pub struct CargoWarningFormatter;
101
102impl<S, N> FormatEvent<S, N> for CargoWarningFormatter
103where
104 S: Subscriber + for<'a> LookupSpan<'a>,
105 N: for<'a> FormatFields<'a> + 'static,
106{
107 fn format_event(
108 &self,
109 _ctx: &FmtContext<'_, S, N>,
110 writer: Writer<'_>,
111 event: &Event<'_>,
112 ) -> Result {
113 let mut visitor = Visitor::new(writer);
114 let () = event.record(&mut visitor);
115 Ok(())
116 }
117}