Skip to content

Commit c4ab6ae

Browse files
authored
Better CStr16 to String and str (#249)
1 parent 8101a63 commit c4ab6ae

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/data_types/strs.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::chars::{Char16, Char8, NUL_16, NUL_8};
2+
#[cfg(feature = "exts")]
3+
use crate::alloc_api::string::String;
24
use core::convert::TryInto;
35
use core::fmt;
46
use core::iter::Iterator;
@@ -162,6 +164,40 @@ impl CStr16 {
162164
pos: 0,
163165
}
164166
}
167+
168+
/// Writes each [`Char16`] as a [´char´] (4 bytes long in Rust language) into the buffer.
169+
/// It is up the the implementer of [`core::fmt::Write`] to convert the char to a string
170+
/// with proper encoding/charset. For example, in the case of [`core::alloc::string::String`]
171+
/// all Rust chars (UTF-32) get converted to UTF-8.
172+
///
173+
/// ## Example
174+
///
175+
/// ```ignore
176+
/// let firmware_vendor_c16_str: CStr16 = ...;
177+
/// // crate "arrayvec" uses stack-allocated arrays for Strings => no heap allocations
178+
/// let mut buf = arrayvec::ArrayString::<128>::new();
179+
/// firmware_vendor_c16_str.as_str_in_buf(&mut buf);
180+
/// log::info!("as rust str: {}", buf.as_str());
181+
/// ```
182+
pub fn as_str_in_buf(&self, buf: &mut dyn core::fmt::Write) -> core::fmt::Result {
183+
for c16 in self.iter() {
184+
buf.write_char(char::from(*c16))?;
185+
}
186+
Ok(())
187+
}
188+
189+
/// Transforms the C16Str to a regular Rust String.
190+
/// **WARNING** This will require **heap allocation**, i.e. you need an global allocator.
191+
/// If the UEFI boot services are exited, your OS/Kernel needs to provide another allocation
192+
/// mechanism!
193+
#[cfg(feature = "exts")]
194+
pub fn as_string(&self) -> String {
195+
let mut buf = String::with_capacity(self.0.len() * 2);
196+
for c16 in self.iter() {
197+
buf.push(char::from(*c16));
198+
}
199+
buf
200+
}
165201
}
166202

167203
/// An iterator over `CStr16`.

uefi-test-runner/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern crate alloc;
1111
// Keep this line to ensure the `mem*` functions are linked in.
1212
extern crate rlibc;
1313

14+
use alloc::string::String;
1415
use core::mem;
1516
use uefi::prelude::*;
1617
use uefi::proto::console::serial::Serial;
@@ -25,6 +26,13 @@ fn efi_main(image: Handle, mut st: SystemTable<Boot>) -> Status {
2526
// Initialize utilities (logging, memory allocation...)
2627
uefi_services::init(&mut st).expect_success("Failed to initialize utilities");
2728

29+
// unit tests here
30+
31+
// output firmware-vendor (CStr16 to Rust string)
32+
let mut buf = String::new();
33+
st.firmware_vendor().as_str_in_buf(&mut buf).unwrap();
34+
info!("Firmware Vendor: {}", buf.as_str());
35+
2836
// Reset the console before running all the other tests.
2937
st.stdout()
3038
.reset(false)

0 commit comments

Comments
 (0)