Skip to content

better CStr16 to String and str #249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/data_types/strs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use super::chars::{Char16, Char8, NUL_16, NUL_8};
#[cfg(feature = "exts")]
use crate::alloc_api::string::String;
use core::convert::TryInto;
use core::fmt;
use core::iter::Iterator;
Expand Down Expand Up @@ -162,6 +164,40 @@ impl CStr16 {
pos: 0,
}
}

/// Writes each [`Char16`] as a [´char´] (4 bytes long in Rust language) into the buffer.
/// It is up the the implementer of [`core::fmt::Write`] to convert the char to a string
/// with proper encoding/charset. For example, in the case of [`core::alloc::string::String`]
/// all Rust chars (UTF-32) get converted to UTF-8.
///
/// ## Example
///
/// ```ignore
/// let firmware_vendor_c16_str: CStr16 = ...;
/// // crate "arrayvec" uses stack-allocated arrays for Strings => no heap allocations
/// let mut buf = arrayvec::ArrayString::<128>::new();
/// firmware_vendor_c16_str.as_str_in_buf(&mut buf);
/// log::info!("as rust str: {}", buf.as_str());
/// ```
pub fn as_str_in_buf(&self, buf: &mut dyn core::fmt::Write) -> core::fmt::Result {
for c16 in self.iter() {
buf.write_char(char::from(*c16))?;
}
Ok(())
}

/// Transforms the C16Str to a regular Rust String.
/// **WARNING** This will require **heap allocation**, i.e. you need an global allocator.
/// If the UEFI boot services are exited, your OS/Kernel needs to provide another allocation
/// mechanism!
#[cfg(feature = "exts")]
pub fn as_string(&self) -> String {
let mut buf = String::with_capacity(self.0.len() * 2);
for c16 in self.iter() {
buf.push(char::from(*c16));
}
buf
}
}

/// An iterator over `CStr16`.
Expand Down
8 changes: 8 additions & 0 deletions uefi-test-runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern crate alloc;
// Keep this line to ensure the `mem*` functions are linked in.
extern crate rlibc;

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

// unit tests here

// output firmware-vendor (CStr16 to Rust string)
let mut buf = String::new();
st.firmware_vendor().as_str_in_buf(&mut buf).unwrap();
info!("Firmware Vendor: {}", buf.as_str());

// Reset the console before running all the other tests.
st.stdout()
.reset(false)
Expand Down