1mod bstr;
2mod hstring;
3mod literals;
4mod pcstr;
5mod pcwstr;
6mod pstr;
7mod pwstr;
8
9pub use bstr::*;
10pub use hstring::*;
11#[doc(hidden)]
12pub use literals::*;
13pub use pcstr::*;
14pub use pcwstr::*;
15pub use pstr::*;
16pub use pwstr::*;
17
18use super::*;
19
20extern "C" {
21 #[doc(hidden)]
22 pub fn strlen(s: PCSTR) -> usize;
23 #[doc(hidden)]
24 pub fn wcslen(s: PCWSTR) -> usize;
25}
26
27/// An internal helper for decoding an iterator of chars and displaying them
28#[doc(hidden)]
29pub struct Decode<F>(pub F);
30
31impl<F, R, E> std::fmt::Display for Decode<F>
32where
33 F: Clone + FnOnce() -> R,
34 R: IntoIterator<Item = std::result::Result<char, E>>,
35{
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 use std::fmt::Write;
38 let iter: F = self.0.clone();
39 for c: Result in iter().into_iter() {
40 f.write_char(c.unwrap_or(default:std::char::REPLACEMENT_CHARACTER))?
41 }
42 Ok(())
43 }
44}
45
46/// Mirror of `std::char::decode_utf16` for utf-8.
47fn decode_utf8(mut buffer: &[u8]) -> impl Iterator<Item = std::result::Result<char, std::str::Utf8Error>> + '_ {
48 let mut current = "".chars();
49 let mut previous_error = None;
50 std::iter::from_fn(move || {
51 loop {
52 match (current.next(), previous_error) {
53 (Some(c), _) => return Some(Ok(c)),
54 // Return the previous error
55 (None, Some(e)) => {
56 previous_error = None;
57 return Some(Err(e));
58 }
59 // We're completely done
60 (None, None) if buffer.is_empty() => return None,
61 (None, None) => {
62 match std::str::from_utf8(buffer) {
63 Ok(s) => {
64 current = s.chars();
65 buffer = &[];
66 }
67 Err(e) => {
68 let (valid, rest) = buffer.split_at(e.valid_up_to());
69 // Skip the invalid sequence and stop completely if we ended early
70 let invalid_sequence_length = e.error_len()?;
71 buffer = &rest[invalid_sequence_length..];
72
73 // Set the current iterator to the valid section and indicate previous error
74 // SAFETY: `valid` is known to be valid utf-8 from error
75 current = unsafe { std::str::from_utf8_unchecked(valid) }.chars();
76 previous_error = Some(e);
77 }
78 }
79 }
80 }
81 }
82 })
83}
84