1 | use defmt_macros::internp; |
2 | |
3 | #[allow (unused_imports)] |
4 | use crate as defmt; |
5 | use 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. |
46 | pub 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(fmt: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]`. |
90 | pub 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 | } |
132 | |