| 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 | |