defmt/traits.rs
1use defmt_macros::internp;
2
3#[allow(unused_imports)]
4use crate as defmt;
5use crate::{export, Formatter, Str};
6
7/// Trait for types that can be formatted via defmt.
8///
9/// This trait is used by the `{:?}` format specifier and can format a wide range of types.
10/// User-defined types can `#[derive(Format)]` to get an auto-generated implementation of this
11/// trait.
12///
13/// **Note**: The implementation of `#[derive(Format)]` assumes that no builtin types are shadowed
14/// (for example by defining a `struct u8;`). This allows it to represent them more compactly.
15///
16/// # Example
17///
18/// Usually, an implementation of this trait can be `#[derive]`d automatically:
19///
20/// ```
21/// use defmt::Format;
22///
23/// #[derive(Format)]
24/// struct Header {
25/// source: u8,
26/// destination: u8,
27/// sequence: u16,
28/// }
29/// ```
30///
31/// Manual implementations can make use of the [`write!`] macro:
32///
33/// ```
34/// use defmt::{Format, Formatter, write};
35///
36/// struct Id(u32);
37///
38/// impl Format for Id {
39/// fn format(&self, fmt: Formatter) {
40/// // Format as hexadecimal.
41/// write!(fmt, "Id({:x})", self.0);
42/// }
43/// }
44/// ```
45/// **Note** Some implementations of standard types like `Vec<T>` are hidden behind the `alloc` feature flag.
46pub trait Format {
47 /// Writes the defmt representation of `self` to `fmt`.
48 fn format(&self, fmt: Formatter);
49
50 #[doc(hidden)]
51 fn _format_tag() -> Str {
52 internp!("{=__internal_FormatSequence}")
53 }
54
55 #[doc(hidden)]
56 fn _format_data(&self) {
57 self.format(export::make_formatter());
58 export::u16(&0); // terminator
59 }
60}
61
62/// Global logger acquire-release mechanism
63///
64/// This trait's methods will be called by the defmt logging macros to transmit the
65/// encoded log data over the wire. The call order is:
66/// - One `acquire()` call to start the log frame.
67/// - Multiple `write()` calls, with fragments of the log frame data each.
68/// - One `release()` call.
69///
70/// The data passed to `write()` is *unencoded*. Implementations MUST encode it with `Encoder`
71/// prior to sending it over the wire. The simplest way is for `acquire()` to call `Encoder::start_frame()`,
72/// `write()` to call `Encoder::write()`, and `release()` to call `Encoder::end_frame()`.
73///
74/// The global logger can be acquired once for each "execution context". The definition
75/// of execution context is up to the implementation. For example, it can be:
76///
77/// - the entire process.
78/// - one thread in std environments.
79/// - one interrupt priority level in embedded devices.
80///
81/// # Safety
82///
83/// - `acquire` logically acquires the global logger in the current execution context.
84/// The acquiring is tracked internally, no Rust object is returned representing ownership.
85/// - `acquire` is a safe function, therefore it must be thread-safe and interrupt-safe
86///
87/// And, not safety related, the methods should never be invoked from user code. The easiest way to
88/// ensure this is to implement `Logger` on a *private* `struct` and mark that `struct` as the
89/// `#[global_logger]`.
90pub unsafe trait Logger {
91 /// Acquire the global logger in the current execution context.
92 ///
93 /// This will be called by the defmt logging macros before writing each log frame.
94 ///
95 /// Panics if already acquired in the current execution context. Otherwise it must never fail.
96 fn acquire();
97
98 /// Block until host has read all pending data.
99 ///
100 /// The flush operation must not fail. This is a "best effort" operation, I/O errors should be discarded.
101 ///
102 /// # Safety
103 /// Must only be called when the global logger is acquired in the current execution context.
104 /// (i.e. between `acquire()` and `release()`).
105 unsafe fn flush();
106
107 /// Releases the global logger in the current execution context.
108 ///
109 /// This will be called by the defmt logging macros after writing each log frame.
110 ///
111 /// # Safety
112 /// Must be called exactly once for each acquire(), in the same execution context.
113 unsafe fn release();
114
115 /// Writes `bytes` to the destination.
116 ///
117 /// This will be called by the defmt logging macros to transmit frame data. One log frame may cause multiple `write` calls.
118 ///
119 /// The write operation must not fail. This is a "best effort" operation, I/O errors should be discarded.
120 ///
121 /// The `bytes` are unencoded log frame data, they MUST be encoded with `Encoder` prior to
122 /// sending over the wire.
123 ///
124 /// Note that a call to `write` does *not* correspond to a defmt logging macro invocation. A
125 /// single `defmt::info!` call can result in an arbitrary number of `write` calls.
126 ///
127 /// # Safety
128 /// Must only be called when the global logger is acquired in the current execution context.
129 /// (i.e. between `acquire()` and `release()`).
130 unsafe fn write(bytes: &[u8]);
131}