Skip to content

Commit cfd6f2f

Browse files
committed
Removes Display implementation on EfiStr and EfiString
1 parent 06c90d1 commit cfd6f2f

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ Keep in mind that you need to put everything your test needed in the same functi
204204
- `SystemTable::current()` was replaced with `zfi::system_table()`.
205205
- `Image::current()` was replaced with `zfi::current_image()`.
206206
- All getters on `SystemTable` no longer return a static lifetime.
207+
- `EfiStr` and `EfiString` to longer implement `Display`. Use `EfiStr::display()` instead.
207208

208209
## License
209210

src/string.rs

+27-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use alloc::borrow::ToOwned;
2-
use alloc::string::String;
32
use alloc::vec::Vec;
43
use core::borrow::Borrow;
5-
use core::fmt::{Display, Formatter};
4+
use core::fmt::{Formatter, Write};
65
use core::mem::transmute;
76
use core::slice::{from_raw_parts, IterMut};
87
use core::str::FromStr;
@@ -15,6 +14,7 @@ use core::str::FromStr;
1514
pub struct EfiStr([u16]);
1615

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

2020
/// # Safety
@@ -40,17 +40,26 @@ impl EfiStr {
4040
Self::new_unchecked(from_raw_parts(ptr, len + 1))
4141
}
4242

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

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

53+
/// Returns `true` if this string contains only NUL character.
5154
pub const fn is_empty(&self) -> bool {
5255
self.len() == 0
5356
}
57+
58+
/// Returns object that implement [`core::fmt::Display`] for safely printing string that may
59+
/// contain non-Unicode data.
60+
pub const fn display(&self) -> impl core::fmt::Display + '_ {
61+
Display(self)
62+
}
5463
}
5564

5665
impl AsRef<EfiStr> for EfiStr {
@@ -83,12 +92,24 @@ impl ToOwned for EfiStr {
8392
}
8493
}
8594

86-
impl Display for EfiStr {
95+
/// Provides [`core::fmt::Display`] to display [`EfiStr`] lossy.
96+
struct Display<'a>(&'a EfiStr);
97+
98+
impl<'a> core::fmt::Display for Display<'a> {
8799
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
88-
let d = &self.0[..(self.0.len() - 1)]; // Exclude NUL.
89-
let s = String::from_utf16(d).unwrap();
100+
// SAFETY: EfiStr guarantee to have NUL at the end.
101+
let mut ptr = self.0.as_ptr();
102+
103+
while unsafe { *ptr != 0 } {
104+
let c = unsafe { *ptr };
105+
let c = char::from_u32(c.into()).unwrap_or(char::REPLACEMENT_CHARACTER);
106+
107+
f.write_char(c)?;
108+
109+
unsafe { ptr = ptr.add(1) };
110+
}
90111

91-
f.write_str(&s)
112+
Ok(())
92113
}
93114
}
94115

@@ -166,12 +187,6 @@ impl Borrow<EfiStr> for EfiString {
166187
}
167188
}
168189

169-
impl Display for EfiString {
170-
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
171-
self.as_ref().fmt(f)
172-
}
173-
}
174-
175190
/// A non-NUL character in the EFI string.
176191
#[repr(transparent)]
177192
pub struct EfiChar(u16);

0 commit comments

Comments
 (0)