Skip to content

Commit 8f17d23

Browse files
committed
os_str: Create UTF-8 platform encoding
1 parent c7a635f commit 8f17d23

File tree

2 files changed

+333
-0
lines changed

2 files changed

+333
-0
lines changed

library/std/src/sys/os_str/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ cfg_select! {
55
mod wtf8;
66
pub use wtf8::{Buf, Slice};
77
}
8+
any(target_os = "motor") => {
9+
mod utf8;
10+
pub use utf8::{Buf, Slice};
11+
}
812
_ => {
913
mod bytes;
1014
pub use bytes::{Buf, Slice};

library/std/src/sys/os_str/utf8.rs

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
//! The underlying OsString/OsStr implementation on Motor OS is UTF-8.
2+
3+
use core::clone::CloneToUninit;
4+
5+
use crate::borrow::Cow;
6+
use crate::collections::TryReserveError;
7+
use crate::rc::Rc;
8+
use crate::sync::Arc;
9+
use crate::sys_common::{AsInner, FromInner, IntoInner};
10+
use crate::{fmt, mem};
11+
12+
#[derive(Hash)]
13+
#[repr(transparent)]
14+
pub struct Buf {
15+
pub inner: String,
16+
}
17+
18+
#[repr(transparent)]
19+
pub struct Slice {
20+
pub inner: str,
21+
}
22+
23+
impl IntoInner<String> for Buf {
24+
fn into_inner(self) -> String {
25+
self.inner
26+
}
27+
}
28+
29+
impl FromInner<String> for Buf {
30+
fn from_inner(inner: String) -> Self {
31+
Buf { inner }
32+
}
33+
}
34+
35+
impl AsInner<str> for Buf {
36+
#[inline]
37+
fn as_inner(&self) -> &str {
38+
&self.inner
39+
}
40+
}
41+
42+
impl fmt::Debug for Buf {
43+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44+
fmt::Debug::fmt(&self.inner, f)
45+
}
46+
}
47+
48+
impl fmt::Display for Buf {
49+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50+
fmt::Display::fmt(&self.inner, f)
51+
}
52+
}
53+
54+
impl fmt::Debug for Slice {
55+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56+
fmt::Debug::fmt(&self.inner, f)
57+
}
58+
}
59+
60+
impl fmt::Display for Slice {
61+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62+
fmt::Display::fmt(&self.inner, f)
63+
}
64+
}
65+
66+
impl Clone for Buf {
67+
#[inline]
68+
fn clone(&self) -> Self {
69+
Buf { inner: self.inner.clone() }
70+
}
71+
72+
#[inline]
73+
fn clone_from(&mut self, source: &Self) {
74+
self.inner.clone_from(&source.inner)
75+
}
76+
}
77+
78+
impl Buf {
79+
#[inline]
80+
pub fn into_encoded_bytes(self) -> Vec<u8> {
81+
self.inner.into_bytes()
82+
}
83+
84+
#[inline]
85+
pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self {
86+
unsafe { Self { inner: String::from_utf8_unchecked(s) } }
87+
}
88+
89+
#[inline]
90+
pub fn into_string(self) -> Result<String, Buf> {
91+
Ok(self.inner)
92+
}
93+
94+
#[inline]
95+
pub const fn from_string(s: String) -> Buf {
96+
Buf { inner: s }
97+
}
98+
99+
#[inline]
100+
pub fn with_capacity(capacity: usize) -> Buf {
101+
Buf { inner: String::with_capacity(capacity) }
102+
}
103+
104+
#[inline]
105+
pub fn clear(&mut self) {
106+
self.inner.clear()
107+
}
108+
109+
#[inline]
110+
pub fn capacity(&self) -> usize {
111+
self.inner.capacity()
112+
}
113+
114+
#[inline]
115+
pub fn push_slice(&mut self, s: &Slice) {
116+
self.inner.push_str(&s.inner)
117+
}
118+
119+
#[inline]
120+
pub fn push_str(&mut self, s: &str) {
121+
self.inner.push_str(s);
122+
}
123+
124+
#[inline]
125+
pub fn reserve(&mut self, additional: usize) {
126+
self.inner.reserve(additional)
127+
}
128+
129+
#[inline]
130+
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
131+
self.inner.try_reserve(additional)
132+
}
133+
134+
#[inline]
135+
pub fn reserve_exact(&mut self, additional: usize) {
136+
self.inner.reserve_exact(additional)
137+
}
138+
139+
#[inline]
140+
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
141+
self.inner.try_reserve_exact(additional)
142+
}
143+
144+
#[inline]
145+
pub fn shrink_to_fit(&mut self) {
146+
self.inner.shrink_to_fit()
147+
}
148+
149+
#[inline]
150+
pub fn shrink_to(&mut self, min_capacity: usize) {
151+
self.inner.shrink_to(min_capacity)
152+
}
153+
154+
#[inline]
155+
pub fn as_slice(&self) -> &Slice {
156+
// SAFETY: Slice is just a wrapper for str,
157+
// and self.inner.as_str() returns &str.
158+
// Therefore, transmuting &str to &Slice is safe.
159+
unsafe { mem::transmute(self.inner.as_str()) }
160+
}
161+
162+
#[inline]
163+
pub fn as_mut_slice(&mut self) -> &mut Slice {
164+
// SAFETY: Slice is just a wrapper for str,
165+
// and self.inner.as_mut_str() returns &mut str.
166+
// Therefore, transmuting &mut str to &mut Slice is safe.
167+
unsafe { mem::transmute(self.inner.as_mut_str()) }
168+
}
169+
170+
#[inline]
171+
pub fn leak<'a>(self) -> &'a mut Slice {
172+
unsafe { mem::transmute(self.inner.leak()) }
173+
}
174+
175+
#[inline]
176+
pub fn into_box(self) -> Box<Slice> {
177+
unsafe { mem::transmute(self.inner.into_boxed_str()) }
178+
}
179+
180+
#[inline]
181+
pub fn from_box(boxed: Box<Slice>) -> Buf {
182+
let inner: Box<str> = unsafe { mem::transmute(boxed) };
183+
Buf { inner: inner.into_string() }
184+
}
185+
186+
#[inline]
187+
pub fn into_arc(&self) -> Arc<Slice> {
188+
self.as_slice().into_arc()
189+
}
190+
191+
#[inline]
192+
pub fn into_rc(&self) -> Rc<Slice> {
193+
self.as_slice().into_rc()
194+
}
195+
196+
/// Provides plumbing to `Vec::truncate` without giving full mutable access
197+
/// to the `Vec`.
198+
///
199+
/// # Safety
200+
///
201+
/// The length must be at an `OsStr` boundary, according to
202+
/// `Slice::check_public_boundary`.
203+
#[inline]
204+
pub unsafe fn truncate_unchecked(&mut self, len: usize) {
205+
self.inner.truncate(len);
206+
}
207+
208+
/// Provides plumbing to `Vec::extend_from_slice` without giving full
209+
/// mutable access to the `Vec`.
210+
///
211+
/// # Safety
212+
///
213+
/// The slice must be valid for the platform encoding (as described in
214+
/// `OsStr::from_encoded_bytes_unchecked`). For this encoding, that means
215+
/// `other` must be valid UTF-8.
216+
#[inline]
217+
pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
218+
self.inner.push_str(unsafe { str::from_utf8_unchecked(other) });
219+
}
220+
}
221+
222+
impl Slice {
223+
#[inline]
224+
pub fn as_encoded_bytes(&self) -> &[u8] {
225+
self.inner.as_bytes()
226+
}
227+
228+
#[inline]
229+
pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
230+
unsafe { mem::transmute(str::from_utf8_unchecked(s)) }
231+
}
232+
233+
#[track_caller]
234+
#[inline]
235+
pub fn check_public_boundary(&self, index: usize) {
236+
if !self.inner.is_char_boundary(index) {
237+
panic!("byte index {index} is not an OsStr boundary");
238+
}
239+
}
240+
241+
#[inline]
242+
pub fn from_str(s: &str) -> &Slice {
243+
unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) }
244+
}
245+
246+
#[inline]
247+
pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
248+
Ok(&self.inner)
249+
}
250+
251+
#[inline]
252+
pub fn to_string_lossy(&self) -> Cow<'_, str> {
253+
Cow::Borrowed(&self.inner)
254+
}
255+
256+
#[inline]
257+
pub fn to_owned(&self) -> Buf {
258+
Buf { inner: self.inner.to_owned() }
259+
}
260+
261+
#[inline]
262+
pub fn clone_into(&self, buf: &mut Buf) {
263+
self.inner.clone_into(&mut buf.inner)
264+
}
265+
266+
#[inline]
267+
pub fn into_box(&self) -> Box<Slice> {
268+
let boxed: Box<str> = self.inner.into();
269+
unsafe { mem::transmute(boxed) }
270+
}
271+
272+
#[inline]
273+
pub fn empty_box() -> Box<Slice> {
274+
let boxed: Box<str> = Default::default();
275+
unsafe { mem::transmute(boxed) }
276+
}
277+
278+
#[inline]
279+
pub fn into_arc(&self) -> Arc<Slice> {
280+
let arc: Arc<str> = Arc::from(&self.inner);
281+
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
282+
}
283+
284+
#[inline]
285+
pub fn into_rc(&self) -> Rc<Slice> {
286+
let rc: Rc<str> = Rc::from(&self.inner);
287+
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
288+
}
289+
290+
#[inline]
291+
pub fn make_ascii_lowercase(&mut self) {
292+
self.inner.make_ascii_lowercase()
293+
}
294+
295+
#[inline]
296+
pub fn make_ascii_uppercase(&mut self) {
297+
self.inner.make_ascii_uppercase()
298+
}
299+
300+
#[inline]
301+
pub fn to_ascii_lowercase(&self) -> Buf {
302+
Buf { inner: self.inner.to_ascii_lowercase() }
303+
}
304+
305+
#[inline]
306+
pub fn to_ascii_uppercase(&self) -> Buf {
307+
Buf { inner: self.inner.to_ascii_uppercase() }
308+
}
309+
310+
#[inline]
311+
pub fn is_ascii(&self) -> bool {
312+
self.inner.is_ascii()
313+
}
314+
315+
#[inline]
316+
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
317+
self.inner.eq_ignore_ascii_case(&other.inner)
318+
}
319+
}
320+
321+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
322+
unsafe impl CloneToUninit for Slice {
323+
#[inline]
324+
#[cfg_attr(debug_assertions, track_caller)]
325+
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
326+
// SAFETY: we're just a transparent wrapper around [u8]
327+
unsafe { self.inner.clone_to_uninit(dst) }
328+
}
329+
}

0 commit comments

Comments
 (0)