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}