]> git.proxmox.com Git - rustc.git/blob - src/vendor/clap/src/osstringext.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / clap / src / osstringext.rs
1 #[cfg(target_os = "windows")]
2 use INVALID_UTF8;
3 use std::ffi::OsStr;
4 #[cfg(not(target_os = "windows"))]
5 use std::os::unix::ffi::OsStrExt;
6
7 #[cfg(target_os = "windows")]
8 trait OsStrExt3 {
9 fn from_bytes(b: &[u8]) -> &Self;
10 fn as_bytes(&self) -> &[u8];
11 }
12
13 #[doc(hidden)]
14 pub trait OsStrExt2 {
15 fn starts_with(&self, s: &[u8]) -> bool;
16 fn split_at_byte(&self, b: u8) -> (&OsStr, &OsStr);
17 fn split_at(&self, i: usize) -> (&OsStr, &OsStr);
18 fn trim_left_matches(&self, b: u8) -> &OsStr;
19 fn len_(&self) -> usize;
20 fn contains_byte(&self, b: u8) -> bool;
21 fn is_empty_(&self) -> bool;
22 fn split(&self, b: u8) -> OsSplit;
23 }
24
25 #[cfg(target_os = "windows")]
26 impl OsStrExt3 for OsStr {
27 fn from_bytes(b: &[u8]) -> &Self {
28 use std::mem;
29 unsafe { mem::transmute(b) }
30 }
31 fn as_bytes(&self) -> &[u8] { self.to_str().map(|s| s.as_bytes()).expect(INVALID_UTF8) }
32 }
33
34 impl OsStrExt2 for OsStr {
35 fn starts_with(&self, s: &[u8]) -> bool { self.as_bytes().starts_with(s) }
36
37 fn is_empty_(&self) -> bool { self.as_bytes().is_empty() }
38
39 fn contains_byte(&self, byte: u8) -> bool {
40 for b in self.as_bytes() {
41 if b == &byte {
42 return true;
43 }
44 }
45 false
46 }
47
48 fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) {
49 for (i, b) in self.as_bytes().iter().enumerate() {
50 if b == &byte {
51 return (OsStr::from_bytes(&self.as_bytes()[..i]),
52 OsStr::from_bytes(&self.as_bytes()[i + 1..]));
53 }
54 }
55 (&*self, OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]))
56 }
57
58 fn trim_left_matches(&self, byte: u8) -> &OsStr {
59 for (i, b) in self.as_bytes().iter().enumerate() {
60 if b != &byte {
61 return OsStr::from_bytes(&self.as_bytes()[i..]);
62 }
63 }
64 &*self
65 }
66
67 fn split_at(&self, i: usize) -> (&OsStr, &OsStr) {
68 (OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i..]))
69 }
70
71 fn len_(&self) -> usize { self.as_bytes().len() }
72
73 fn split(&self, b: u8) -> OsSplit {
74 OsSplit {
75 sep: b,
76 val: self.as_bytes(),
77 pos: 0,
78 }
79 }
80 }
81
82 #[doc(hidden)]
83 #[derive(Clone, Debug)]
84 pub struct OsSplit<'a> {
85 sep: u8,
86 val: &'a [u8],
87 pos: usize,
88 }
89
90 impl<'a> Iterator for OsSplit<'a> {
91 type Item = &'a OsStr;
92
93 fn next(&mut self) -> Option<&'a OsStr> {
94 debugln!("fn=OsSplit::next;");
95 debugln!("OsSplit: {:?}", self);
96 if self.pos == self.val.len() {
97 return None;
98 }
99 let start = self.pos;
100 for b in &self.val[start..] {
101 self.pos += 1;
102 if *b == self.sep {
103 return Some(OsStr::from_bytes(&self.val[start..self.pos - 1]));
104 }
105 }
106 Some(OsStr::from_bytes(&self.val[start..]))
107 }
108 fn size_hint(&self) -> (usize, Option<usize>) {
109 let mut count = 0;
110 for b in &self.val[self.pos..] {
111 if *b == self.sep {
112 count += 1;
113 }
114 }
115 if count > 0 {
116 return (count, Some(count));
117 }
118 (0, None)
119 }
120 }
121
122 impl<'a> DoubleEndedIterator for OsSplit<'a> {
123 fn next_back(&mut self) -> Option<&'a OsStr> {
124 if self.pos == 0 {
125 return None;
126 }
127 let start = self.pos;
128 for b in self.val[..self.pos].iter().rev() {
129 self.pos -= 1;
130 if *b == self.sep {
131 return Some(OsStr::from_bytes(&self.val[self.pos + 1..start]));
132 }
133 }
134 Some(OsStr::from_bytes(&self.val[..start]))
135 }
136 }