From 4d78e11a4339f9ef42455306fc8a79f4c5b57ce4 Mon Sep 17 00:00:00 2001 From: Niklas Dusenlund Date: Fri, 29 Nov 2024 11:58:03 +0100 Subject: [PATCH] Add rust_dbg_hex --- src/rust/bitbox02-rust-c/src/lib.rs | 35 +++++++++++++++++++++ src/rust/bitbox02-rust-c/src/util.rs | 46 ++++++++++++++++------------ 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/rust/bitbox02-rust-c/src/lib.rs b/src/rust/bitbox02-rust-c/src/lib.rs index 2106252f6..12d099ed4 100644 --- a/src/rust/bitbox02-rust-c/src/lib.rs +++ b/src/rust/bitbox02-rust-c/src/lib.rs @@ -68,3 +68,38 @@ pub extern "C" fn rust_log(ptr: *const ::util::c_types::c_char) { ::util::log::rtt_target::rprintln!("{}", s); } } + +/// This function is for debug purposes only! +/// +/// Don't use this in production, the returned pointer is only valid until this function is called +/// again. This function is not thread safe. +/// +/// Returns a null terminated string, suitable for printing with printf in C. +/// +/// Max `len` is 64. This function panics if `len` is to large. +/// +/// Usage: +/// uint8_t arr[2] = {1,2}; +/// util_log("%s", rust_dbg_hex(arr, sizeof(arr))); +/// +#[no_mangle] +#[cfg(feature = "rtt")] +pub extern "C" fn rust_dbg_hex( + buf: *mut ::util::c_types::c_uchar, + len: usize, +) -> *const ::util::c_types::c_char { + #![allow(static_mut_refs)] + + const MAX_BYTES_LEN: usize = 64; + if len > MAX_BYTES_LEN { + panic!("Cannot convert more than {} bytes", MAX_BYTES_LEN); + } + + let bytes = util::Bytes::new(buf, len); + + static mut BUF: [u8; MAX_BYTES_LEN * 2 + 1] = [0; MAX_BYTES_LEN * 2 + 1]; + let buf = unsafe { &mut BUF }; + bytes.to_slice_hex(buf); + buf[len] = 0; // Null terminator. + buf as _ +} diff --git a/src/rust/bitbox02-rust-c/src/util.rs b/src/rust/bitbox02-rust-c/src/util.rs index 5bdb77aa3..29f9f836f 100644 --- a/src/rust/bitbox02-rust-c/src/util.rs +++ b/src/rust/bitbox02-rust-c/src/util.rs @@ -25,22 +25,9 @@ pub extern "C" fn rust_util_zero(mut dst: BytesMut) { util::zero(dst.as_mut()) } -/// Convert bytes to hex representation -/// -/// * `buf` - bytes to convert to hex. -/// * `out` - hex will be written here. out len must be at least 2*buf.len+1. #[no_mangle] -pub extern "C" fn rust_util_uint8_to_hex(buf: Bytes, mut out: BytesMut) { - let bytes = buf.as_ref(); - let hexlen = bytes.len() * 2; - // Avoid .unwrap() here until the following compiler regression is fixed: - // https://github.com/rust-lang/rust/issues/83925 - match hex::encode_to_slice(bytes, &mut out.as_mut()[..hexlen]) { - Ok(()) => {} - Err(err) => panic!("{:?}", err), - } - // Null terminator. - out.as_mut()[hexlen] = 0; +pub extern "C" fn rust_util_uint8_to_hex(src: Bytes, mut dst: BytesMut) { + src.to_slice_hex(dst.as_mut()); } #[repr(C)] @@ -97,13 +84,32 @@ impl AsMut<[u8]> for BytesMut { } } +impl Bytes { + pub fn new(buf: *const c_uchar, len: usize) -> Bytes { + Bytes { buf, len } + } + + /// Convert bytes to hex representation + /// + /// * `out` - hex will be written here. out len must be at least 2*len. + pub fn to_slice_hex(&self, out: &mut [u8]) { + let bytes = self.as_ref(); + let hexlen = bytes.len() * 2; + // Avoid .unwrap() here until the following compiler regression is fixed: + // https://github.com/rust-lang/rust/issues/83925 + if let Err(err) = hex::encode_to_slice(bytes, &mut out.as_mut()[..hexlen]) { + panic!("{:?}", err); + } + } +} + /// Convert buffer to slice /// /// * `buf` - Must be a valid pointer to an array of bytes /// * `len` - Length of buffer, `buf[len-1]` must be a valid dereference #[no_mangle] pub extern "C" fn rust_util_bytes(buf: *const c_uchar, len: usize) -> Bytes { - Bytes { buf, len } + Bytes::new(buf, len) } /// Convert buffer to mutable slice @@ -175,15 +181,15 @@ mod tests { fn test_uint8_to_hex() { let buf = [1u8, 2, 3, 14, 15, 255]; let mut string = String::from("xxxxxxxxxxxxx"); - rust_util_uint8_to_hex(rust_util_bytes(buf.as_ptr(), buf.len()), unsafe { - rust_util_bytes_mut(string.as_mut_ptr(), string.len()) + rust_util_bytes(buf.as_ptr(), buf.len()).to_slice_hex(unsafe { + rust_util_bytes_mut(string.as_mut_ptr(), string.len()).as_mut() }); assert_eq!(string, "0102030e0fff\0"); // Bigger buffer also works. let mut string = String::from("\0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - rust_util_uint8_to_hex(rust_util_bytes(buf.as_ptr(), buf.len()), unsafe { - rust_util_bytes_mut(string.as_mut_ptr(), string.len()) + rust_util_bytes(buf.as_ptr(), buf.len()).to_slice_hex(unsafe { + rust_util_bytes_mut(string.as_mut_ptr(), string.len()).as_mut() }); assert_eq!(string, "0102030e0fff\0xxxxxxxxxxxxxxxxxxxxxxx"); }