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 pub trait OsStrExt3 { from_bytes(b: &[u8]) -> &Self9 fn from_bytes(b: &[u8]) -> &Self; as_bytes(&self) -> &[u8]10 fn as_bytes(&self) -> &[u8]; 11 } 12 13 #[doc(hidden)] 14 pub trait OsStrExt2 { starts_with(&self, s: &[u8]) -> bool15 fn starts_with(&self, s: &[u8]) -> bool; split_at_byte(&self, b: u8) -> (&OsStr, &OsStr)16 fn split_at_byte(&self, b: u8) -> (&OsStr, &OsStr); split_at(&self, i: usize) -> (&OsStr, &OsStr)17 fn split_at(&self, i: usize) -> (&OsStr, &OsStr); trim_left_matches(&self, b: u8) -> &OsStr18 fn trim_left_matches(&self, b: u8) -> &OsStr; len_(&self) -> usize19 fn len_(&self) -> usize; contains_byte(&self, b: u8) -> bool20 fn contains_byte(&self, b: u8) -> bool; is_empty_(&self) -> bool21 fn is_empty_(&self) -> bool; split(&self, b: u8) -> OsSplit22 fn split(&self, b: u8) -> OsSplit; 23 } 24 25 #[cfg(target_os = "windows")] 26 impl OsStrExt3 for OsStr { from_bytes(b: &[u8]) -> &Self27 fn from_bytes(b: &[u8]) -> &Self { 28 use std::mem; 29 unsafe { mem::transmute(b) } 30 } as_bytes(&self) -> &[u8]31 fn as_bytes(&self) -> &[u8] { self.to_str().map(|s| s.as_bytes()).expect(INVALID_UTF8) } 32 } 33 34 impl OsStrExt2 for OsStr { starts_with(&self, s: &[u8]) -> bool35 fn starts_with(&self, s: &[u8]) -> bool { self.as_bytes().starts_with(s) } 36 is_empty_(&self) -> bool37 fn is_empty_(&self) -> bool { self.as_bytes().is_empty() } 38 contains_byte(&self, byte: u8) -> bool39 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 split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr)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 ( 52 OsStr::from_bytes(&self.as_bytes()[..i]), 53 OsStr::from_bytes(&self.as_bytes()[i + 1..]), 54 ); 55 } 56 } 57 ( 58 &*self, 59 OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]), 60 ) 61 } 62 trim_left_matches(&self, byte: u8) -> &OsStr63 fn trim_left_matches(&self, byte: u8) -> &OsStr { 64 let mut found = false; 65 for (i, b) in self.as_bytes().iter().enumerate() { 66 if b != &byte { 67 return OsStr::from_bytes(&self.as_bytes()[i..]); 68 } else { 69 found = true; 70 } 71 } 72 if found { 73 return OsStr::from_bytes(&self.as_bytes()[self.len_()..]); 74 } 75 &*self 76 } 77 split_at(&self, i: usize) -> (&OsStr, &OsStr)78 fn split_at(&self, i: usize) -> (&OsStr, &OsStr) { 79 ( 80 OsStr::from_bytes(&self.as_bytes()[..i]), 81 OsStr::from_bytes(&self.as_bytes()[i..]), 82 ) 83 } 84 len_(&self) -> usize85 fn len_(&self) -> usize { self.as_bytes().len() } 86 split(&self, b: u8) -> OsSplit87 fn split(&self, b: u8) -> OsSplit { 88 OsSplit { 89 sep: b, 90 val: self.as_bytes(), 91 pos: 0, 92 } 93 } 94 } 95 96 #[doc(hidden)] 97 #[derive(Clone, Debug)] 98 pub struct OsSplit<'a> { 99 sep: u8, 100 val: &'a [u8], 101 pos: usize, 102 } 103 104 impl<'a> Iterator for OsSplit<'a> { 105 type Item = &'a OsStr; 106 next(&mut self) -> Option<&'a OsStr>107 fn next(&mut self) -> Option<&'a OsStr> { 108 debugln!("OsSplit::next: self={:?}", self); 109 if self.pos == self.val.len() { 110 return None; 111 } 112 let start = self.pos; 113 for b in &self.val[start..] { 114 self.pos += 1; 115 if *b == self.sep { 116 return Some(OsStr::from_bytes(&self.val[start..self.pos - 1])); 117 } 118 } 119 Some(OsStr::from_bytes(&self.val[start..])) 120 } size_hint(&self) -> (usize, Option<usize>)121 fn size_hint(&self) -> (usize, Option<usize>) { 122 let mut count = 0; 123 for b in &self.val[self.pos..] { 124 if *b == self.sep { 125 count += 1; 126 } 127 } 128 if count > 0 { 129 return (count, Some(count)); 130 } 131 (0, None) 132 } 133 } 134 135 impl<'a> DoubleEndedIterator for OsSplit<'a> { next_back(&mut self) -> Option<&'a OsStr>136 fn next_back(&mut self) -> Option<&'a OsStr> { 137 if self.pos == 0 { 138 return None; 139 } 140 let start = self.pos; 141 for b in self.val[..self.pos].iter().rev() { 142 self.pos -= 1; 143 if *b == self.sep { 144 return Some(OsStr::from_bytes(&self.val[self.pos + 1..start])); 145 } 146 } 147 Some(OsStr::from_bytes(&self.val[..start])) 148 } 149 } 150