Skip to content

Commit 58e8735

Browse files
committedApr 19, 2019
Implement slicing operators on OsStr and OsString.
1 parent 3be85df commit 58e8735

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed
 

‎src/libstd/ffi/os_str.rs

+120
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,36 @@ impl ops::Index<ops::RangeFull> for OsString {
373373
}
374374
}
375375

376+
#[stable(feature = "os_str_slice", since = "1.33.0")]
377+
impl ops::Index<ops::Range<usize>> for OsString {
378+
type Output = OsStr;
379+
380+
#[inline]
381+
fn index(&self, index: ops::Range<usize>) -> &OsStr {
382+
OsStr::from_inner(&self.inner.as_slice()[index])
383+
}
384+
}
385+
386+
#[stable(feature = "os_str_slice", since = "1.33.0")]
387+
impl ops::Index<ops::RangeFrom<usize>> for OsString {
388+
type Output = OsStr;
389+
390+
#[inline]
391+
fn index(&self, index: ops::RangeFrom<usize>) -> &OsStr {
392+
OsStr::from_inner(&self.inner.as_slice()[index])
393+
}
394+
}
395+
396+
#[stable(feature = "os_str_slice", since = "1.33.0")]
397+
impl ops::Index<ops::RangeTo<usize>> for OsString {
398+
type Output = OsStr;
399+
400+
#[inline]
401+
fn index(&self, index: ops::RangeTo<usize>) -> &OsStr {
402+
OsStr::from_inner(&self.inner.as_slice()[index])
403+
}
404+
}
405+
376406
#[stable(feature = "rust1", since = "1.0.0")]
377407
impl ops::Deref for OsString {
378408
type Target = OsStr;
@@ -966,6 +996,46 @@ impl AsInner<Slice> for OsStr {
966996
}
967997
}
968998

999+
#[stable(feature = "os_str_slice", since = "1.33.0")]
1000+
impl ops::Index<ops::RangeFull> for OsStr {
1001+
type Output = OsStr;
1002+
1003+
#[inline]
1004+
fn index(&self, _: ops::RangeFull) -> &OsStr {
1005+
self
1006+
}
1007+
}
1008+
1009+
#[stable(feature = "os_str_slice", since = "1.33.0")]
1010+
impl ops::Index<ops::Range<usize>> for OsStr {
1011+
type Output = OsStr;
1012+
1013+
#[inline]
1014+
fn index(&self, index: ops::Range<usize>) -> &OsStr {
1015+
OsStr::from_inner(&self.inner[index])
1016+
}
1017+
}
1018+
1019+
#[stable(feature = "os_str_slice", since = "1.33.0")]
1020+
impl ops::Index<ops::RangeFrom<usize>> for OsStr {
1021+
type Output = OsStr;
1022+
1023+
#[inline]
1024+
fn index(&self, index: ops::RangeFrom<usize>) -> &OsStr {
1025+
OsStr::from_inner(&self.inner[index])
1026+
}
1027+
}
1028+
1029+
#[stable(feature = "os_str_slice", since = "1.33.0")]
1030+
impl ops::Index<ops::RangeTo<usize>> for OsStr {
1031+
type Output = OsStr;
1032+
1033+
#[inline]
1034+
fn index(&self, index: ops::RangeTo<usize>) -> &OsStr {
1035+
OsStr::from_inner(&self.inner[index])
1036+
}
1037+
}
1038+
9691039
#[cfg(test)]
9701040
mod tests {
9711041
use super::*;
@@ -1133,4 +1203,54 @@ mod tests {
11331203
assert_eq!(&*rc2, os_str);
11341204
assert_eq!(&*arc2, os_str);
11351205
}
1206+
1207+
#[test]
1208+
fn slice_with_utf8_boundary() {
1209+
let os_str = OsStr::new("Hello🌍🌎🌏");
1210+
assert_eq!(os_str.len(), 17);
1211+
1212+
assert_eq!(os_str, &os_str[..]);
1213+
assert_eq!(os_str, &os_str[..17]);
1214+
assert_eq!(os_str, &os_str[0..]);
1215+
assert_eq!(os_str, &os_str[0..17]);
1216+
1217+
assert_eq!(OsStr::new("Hello"), &os_str[..5]);
1218+
assert_eq!(OsStr::new("🌎🌏"), &os_str[9..]);
1219+
assert_eq!(OsStr::new("lo🌍"), &os_str[3..9]);
1220+
1221+
let os_string = os_str.to_owned();
1222+
assert_eq!(os_str, &os_string[..]);
1223+
assert_eq!(os_str, &os_string[..17]);
1224+
assert_eq!(os_str, &os_string[0..]);
1225+
assert_eq!(os_str, &os_string[0..17]);
1226+
1227+
assert_eq!(OsStr::new("Hello"), &os_string[..5]);
1228+
assert_eq!(OsStr::new("🌎🌏"), &os_string[9..]);
1229+
assert_eq!(OsStr::new("lo🌍"), &os_string[3..9]);
1230+
}
1231+
1232+
#[test]
1233+
#[cfg(any(unix, target_os = "redox", target_arch = "wasm32"))]
1234+
fn slice_with_non_utf8_boundary_unix() {
1235+
#[cfg(unix)]
1236+
use os::unix::ffi::OsStrExt;
1237+
#[cfg(target_os = "redox")]
1238+
use os::redox::ffi::OsStrExt;
1239+
1240+
let os_str = OsStr::new("Hello🌍🌎🌏");
1241+
assert_eq!(OsStr::from_bytes(b"Hello\xf0"), &os_str[..6]);
1242+
assert_eq!(OsStr::from_bytes(b"\x9f\x8c\x8e\xf0\x9f\x8c\x8f"), &os_str[10..]);
1243+
assert_eq!(OsStr::from_bytes(b"\x8d\xf0\x9f\x8c\x8e"), &os_str[8..13]);
1244+
}
1245+
1246+
#[test]
1247+
#[cfg(windows)]
1248+
fn slice_with_non_utf8_boundary_windows() {
1249+
use os::windows::ffi::OsStringExt;
1250+
1251+
let os_str = OsStr::new("Hello🌍🌎🌏");
1252+
assert_eq!(OsString::from_wide(&[0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xD83C]), &os_str[..7]);
1253+
assert_eq!(OsString::from_wide(&[0xDF0E, 0xD83C, 0xDF0F]), &os_str[11..]);
1254+
assert_eq!(OsString::from_wide(&[0xDF0D, 0xD83C]), &os_str[7..11]);
1255+
}
11361256
}

‎src/libstd/sys/windows/os_str.rs

+25
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::sys_common::wtf8::{Wtf8, Wtf8Buf};
77
use crate::mem;
88
use crate::rc::Rc;
99
use crate::sync::Arc;
10+
use crate::ops::{Index, Range, RangeFrom, RangeTo};
1011
use crate::sys_common::{AsInner, IntoInner, FromInner};
1112

1213
#[derive(Clone, Hash)]
@@ -60,6 +61,30 @@ impl fmt::Display for Slice {
6061
}
6162
}
6263

64+
impl Index<Range<usize>> for Slice {
65+
type Output = Slice;
66+
67+
fn index(&self, range: Range<usize>) -> &Slice {
68+
unsafe { mem::transmute(&self.inner[range]) }
69+
}
70+
}
71+
72+
impl Index<RangeFrom<usize>> for Slice {
73+
type Output = Slice;
74+
75+
fn index(&self, range: RangeFrom<usize>) -> &Slice {
76+
unsafe { mem::transmute(&self.inner[range]) }
77+
}
78+
}
79+
80+
impl Index<RangeTo<usize>> for Slice {
81+
type Output = Slice;
82+
83+
fn index(&self, range: RangeTo<usize>) -> &Slice {
84+
unsafe { mem::transmute(&self.inner[range]) }
85+
}
86+
}
87+
6388
impl Buf {
6489
pub fn with_capacity(capacity: usize) -> Buf {
6590
Buf {

‎src/libstd/sys_common/os_str_bytes.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use crate::ffi::{OsStr, OsString};
66
use crate::fmt;
77
use crate::str;
88
use crate::mem;
9+
use crate::ops::{Index, Range, RangeFrom, RangeTo};
910
use crate::rc::Rc;
1011
use crate::sync::Arc;
1112
use crate::sys_common::{FromInner, IntoInner, AsInner};
1213
use crate::sys_common::bytestring::debug_fmt_bytestring;
13-
1414
use core::str::lossy::Utf8Lossy;
1515

1616
#[derive(Clone, Hash)]
@@ -34,6 +34,30 @@ impl fmt::Display for Slice {
3434
}
3535
}
3636

37+
impl Index<Range<usize>> for Slice {
38+
type Output = Slice;
39+
40+
fn index(&self, range: Range<usize>) -> &Slice {
41+
Slice::from_u8_slice(&self.inner[range])
42+
}
43+
}
44+
45+
impl Index<RangeFrom<usize>> for Slice {
46+
type Output = Slice;
47+
48+
fn index(&self, range: RangeFrom<usize>) -> &Slice {
49+
Slice::from_u8_slice(&self.inner[range])
50+
}
51+
}
52+
53+
impl Index<RangeTo<usize>> for Slice {
54+
type Output = Slice;
55+
56+
fn index(&self, range: RangeTo<usize>) -> &Slice {
57+
Slice::from_u8_slice(&self.inner[range])
58+
}
59+
}
60+
3761
impl fmt::Debug for Buf {
3862
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
3963
fmt::Debug::fmt(self.as_slice(), formatter)

0 commit comments

Comments
 (0)