capsules_core/low_level_debug/fmt.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
/// fmt contains formatting routines for LowLevelDebug's console messages as
/// well as the buffer size necessary for the messages.
use super::DebugEntry;
// Messages that may be emitted:
// 1. LowLevelDebug: Dropped ## entries for app ##\n
// 2. LowLevelDebug: App ## alert code ##\n
// 3. LowLevelDebug: App ## prints ##\n
// 4. LowLevelDebug: App ## prints ## ##\n
//
// Each ## above is a usize printed in hexadecimal, with a leading 0x.
// The longest message is either 1 or 4, depending on the size of a usize.
pub const BUF_LEN: usize = max(45 + 2 * USIZE_DIGITS, 35 + 3 * USIZE_DIGITS);
// Formats the given DebugEntry using the provided buffer. Returns the length of
// the message.
pub(crate) fn format_entry(app_num: usize, entry: DebugEntry, buffer: &mut [u8]) -> usize {
use core::fmt::write;
use DebugEntry::{AlertCode, Dropped, Print1, Print2};
let mut adapter = WriteAdapter::new(buffer);
let _ = match entry {
Dropped(count) => write(
&mut adapter,
format_args!(
"LowLevelDebug: Dropped 0x{:x} entries for app 0x{:x}\n",
count, app_num
),
),
AlertCode(code) => write(
&mut adapter,
format_args!(
"LowLevelDebug: App 0x{:x} alert code 0x{:x}\n",
app_num, code
),
),
Print1(num) => write(
&mut adapter,
format_args!("LowLevelDebug: App 0x{:x} prints 0x{:x}\n", app_num, num),
),
Print2(num1, num2) => write(
&mut adapter,
format_args!(
"LowLevelDebug: App 0x{:x} prints 0x{:x} 0x{:x}\n",
app_num, num1, num2
),
),
};
adapter.finish()
}
// The length of a hex-formatted usize, excluding the leading 0x.
const USIZE_DIGITS: usize = 2 * core::mem::size_of::<usize>();
// const implementation of max
const fn max(a: usize, b: usize) -> usize {
[a, b][(b > a) as usize]
}
// Adapter to allow core::fmt::write to write into a u8 slice.
struct WriteAdapter<'b> {
buffer: &'b mut [u8],
used: usize,
}
impl<'b> WriteAdapter<'b> {
pub fn new(buffer: &'b mut [u8]) -> WriteAdapter<'b> {
WriteAdapter { buffer, used: 0 }
}
pub fn finish(self) -> usize {
self.used
}
}
impl core::fmt::Write for WriteAdapter<'_> {
fn write_str(&mut self, msg: &str) -> core::fmt::Result {
if let Some(slice) = self.buffer.get_mut(self.used..(self.used + msg.len())) {
slice.copy_from_slice(msg.as_bytes());
self.used += msg.len();
};
Ok(())
}
}