Skip to content

Commit

Permalink
Removes Display implementation on EfiStr and EfiString
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon committed Dec 30, 2024
1 parent 06c90d1 commit cfd6f2f
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ Keep in mind that you need to put everything your test needed in the same functi
- `SystemTable::current()` was replaced with `zfi::system_table()`.
- `Image::current()` was replaced with `zfi::current_image()`.
- All getters on `SystemTable` no longer return a static lifetime.
- `EfiStr` and `EfiString` to longer implement `Display`. Use `EfiStr::display()` instead.

## License

Expand Down
39 changes: 27 additions & 12 deletions src/string.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use alloc::borrow::ToOwned;
use alloc::string::String;
use alloc::vec::Vec;
use core::borrow::Borrow;
use core::fmt::{Display, Formatter};
use core::fmt::{Formatter, Write};
use core::mem::transmute;
use core::slice::{from_raw_parts, IterMut};
use core::str::FromStr;
Expand All @@ -15,6 +14,7 @@ use core::str::FromStr;
pub struct EfiStr([u16]);

impl EfiStr {
/// An empty string with only NUL character.
pub const EMPTY: &'static Self = unsafe { Self::new_unchecked(&[0]) };

/// # Safety
Expand All @@ -40,17 +40,26 @@ impl EfiStr {
Self::new_unchecked(from_raw_parts(ptr, len + 1))
}

/// Returnes a pointer to the first character.
pub const fn as_ptr(&self) -> *const u16 {
self.0.as_ptr()
}

/// Returnes length of this string without NUL, in character.
pub const fn len(&self) -> usize {
self.0.len() - 1
}

/// Returns `true` if this string contains only NUL character.
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

/// Returns object that implement [`core::fmt::Display`] for safely printing string that may
/// contain non-Unicode data.
pub const fn display(&self) -> impl core::fmt::Display + '_ {
Display(self)
}
}

impl AsRef<EfiStr> for EfiStr {
Expand Down Expand Up @@ -83,12 +92,24 @@ impl ToOwned for EfiStr {
}
}

impl Display for EfiStr {
/// Provides [`core::fmt::Display`] to display [`EfiStr`] lossy.
struct Display<'a>(&'a EfiStr);

impl<'a> core::fmt::Display for Display<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let d = &self.0[..(self.0.len() - 1)]; // Exclude NUL.
let s = String::from_utf16(d).unwrap();
// SAFETY: EfiStr guarantee to have NUL at the end.
let mut ptr = self.0.as_ptr();

while unsafe { *ptr != 0 } {
let c = unsafe { *ptr };
let c = char::from_u32(c.into()).unwrap_or(char::REPLACEMENT_CHARACTER);

f.write_char(c)?;

unsafe { ptr = ptr.add(1) };
}

f.write_str(&s)
Ok(())
}
}

Expand Down Expand Up @@ -166,12 +187,6 @@ impl Borrow<EfiStr> for EfiString {
}
}

impl Display for EfiString {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.as_ref().fmt(f)
}
}

/// A non-NUL character in the EFI string.
#[repr(transparent)]
pub struct EfiChar(u16);
Expand Down

0 comments on commit cfd6f2f

Please sign in to comment.