1 | use super::*; |
2 | |
3 | /// A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters. |
4 | #[repr (transparent)] |
5 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
6 | pub struct PCSTR(pub *const u8); |
7 | |
8 | impl PCSTR { |
9 | /// Construct a new `PCSTR` from a raw pointer |
10 | pub const fn from_raw(ptr: *const u8) -> Self { |
11 | Self(ptr) |
12 | } |
13 | |
14 | /// Construct a null `PCSTR` |
15 | pub fn null() -> Self { |
16 | Self(std::ptr::null()) |
17 | } |
18 | |
19 | /// Returns a raw pointer to the `PCSTR` |
20 | pub fn as_ptr(&self) -> *const u8 { |
21 | self.0 |
22 | } |
23 | |
24 | /// Checks whether the `PCSTR` is null |
25 | pub fn is_null(&self) -> bool { |
26 | self.0.is_null() |
27 | } |
28 | |
29 | /// String data without the trailing 0 |
30 | /// |
31 | /// # Safety |
32 | /// |
33 | /// The `PCSTR`'s pointer needs to be valid for reads up until and including the next `\0`. |
34 | pub unsafe fn as_bytes(&self) -> &[u8] { |
35 | let len = super::strlen(*self); |
36 | std::slice::from_raw_parts(self.0, len) |
37 | } |
38 | |
39 | /// Copy the `PCSTR` into a Rust `String`. |
40 | /// |
41 | /// # Safety |
42 | /// |
43 | /// See the safety information for `PCSTR::as_bytes`. |
44 | pub unsafe fn to_string(&self) -> std::result::Result<String, std::string::FromUtf8Error> { |
45 | String::from_utf8(self.as_bytes().into()) |
46 | } |
47 | |
48 | /// Allow this string to be displayed. |
49 | /// |
50 | /// # Safety |
51 | /// |
52 | /// See the safety information for `PCSTR::as_bytes`. |
53 | pub unsafe fn display(&self) -> impl std::fmt::Display + '_ { |
54 | Decode(move || decode_utf8(self.as_bytes())) |
55 | } |
56 | } |
57 | |
58 | impl TypeKind for PCSTR { |
59 | type TypeKind = CopyType; |
60 | } |
61 | |
62 | #[cfg (test)] |
63 | mod tests { |
64 | use super::*; |
65 | |
66 | #[test ] |
67 | fn can_display() { |
68 | // 💖 followed by an invalid byte sequence and then an incomplete one |
69 | let s = [240, 159, 146, 150, 255, 240, 159, 0]; |
70 | let s = PCSTR::from_raw(s.as_ptr()); |
71 | assert_eq!("💖�" , format!(" {}" , unsafe { s.display() })); |
72 | } |
73 | } |
74 | |