1#![forbid(unsafe_code)]
2
3use crate::*;
4
5use winapi::shared::ntdef::LPCWSTR;
6
7use std::borrow::{Borrow, Cow};
8use std::cmp::Ordering;
9use std::ffi::{OsStr, OsString};
10use std::fmt::{self, Debug, Display, Formatter};
11use std::hash::{Hash, Hasher};
12use std::os::windows::ffi::{OsStrExt, OsStringExt};
13use std::path::{Path, PathBuf};
14
15
16
17#[cfg(feature = "display")]
18impl Display for BString { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Display::fmt(&**self, fmt) } }
19impl Debug for BString { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Debug::fmt(&**self, fmt) } }
20impl AsRef<BStr> for BString { fn as_ref(&self) -> &BStr { &**self } }
21impl AsRef<[u16]> for BString { fn as_ref(&self) -> &[u16] { self.units() } }
22impl Borrow<BStr> for BString { fn borrow(&self) -> &BStr { &**self } }
23impl Borrow<[u16]> for BString { fn borrow(&self) -> &[u16] { self.units() } }
24impl Clone for BString { fn clone(&self) -> Self { Self::from_code_units(self.units().iter().cloned()).unwrap() } }
25impl From<&BStr> for BString { fn from(value: &BStr ) -> Self { Self::from_bstr(value).unwrap() } }
26impl From<&str> for BString { fn from(value: &str ) -> Self { Self::from_str(value).unwrap() } }
27impl From<&String> for BString { fn from(value: &String ) -> Self { Self::from_str(value).unwrap() } }
28impl From< String> for BString { fn from(value: String ) -> Self { Self::from_str(&value).unwrap() } }
29impl From<&OsStr> for BString { fn from(value: &OsStr ) -> Self { Self::from_osstr(value).unwrap() } }
30impl From<&OsString> for BString { fn from(value: &OsString ) -> Self { Self::from_osstr(value).unwrap() } }
31impl From< OsString> for BString { fn from(value: OsString ) -> Self { Self::from_osstr(&value).unwrap() } }
32impl Eq for BString {}
33impl Ord for BString { fn cmp(&self, other: &BString) -> Ordering { self.units().cmp(other.units()) } }
34impl Hash for BString { fn hash<H: Hasher>(&self, state: &mut H) { self.units().hash(state) } }
35
36#[cfg(feature = "display")]
37impl Display for BStr { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Display::fmt(&PathBuf::from(OsString::from_wide(self.units())).display(), fmt) } }
38impl Debug for BStr { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Debug::fmt(&OsString::from_wide(self.units()), fmt) } }
39impl AsRef<BStr> for BStr { fn as_ref(&self) -> &BStr { self } }
40impl AsRef<[u16]> for BStr { fn as_ref(&self) -> &[u16] { self.units() } }
41impl Borrow<[u16]> for BStr { fn borrow(&self) -> &[u16] { self.units() } }
42impl Eq for &BStr {}
43impl Ord for &BStr { fn cmp(&self, other: &&BStr) -> Ordering { self.units().cmp(other.units()) } }
44impl Hash for &BStr { fn hash<H: Hasher>(&self, state: &mut H) { self.units().hash(state) } }
45
46macro_rules! peo {
61 ( &? $left:ty, $($tt:tt)* ) => {
62 peo!(& $left, $($tt)*);
63 peo!( $left, $($tt)*);
64 };
65 ( $left:ty, &? $($tt:tt)* ) => {
66 peo!($left, & $($tt)*);
67 peo!($left, $($tt)*);
68 };
69 ( $left:ty, $right:ty ) => {
70 impl PartialEq<$left> for $right {
71 fn eq(&self, other: &$left) -> bool {
72 self.utf16ish().eq(other.utf16ish())
73 }
74 }
75 impl PartialOrd<$left> for $right {
76 fn partial_cmp(&self, other: &$left) -> Option<Ordering> {
77 self.utf16ish().partial_cmp(other.utf16ish())
78 }
79 }
80 };
81}
82
83peo!(&BStr, &BStr );
84peo!(BString, BString);
85
86peo!(BString, &BStr ); peo!(&BStr, BString );
87peo!(&?[u16], &BStr ); peo!(&BStr, &?[u16] ); peo!(&?str, &BStr ); peo!(&BStr, &?str );
89peo!(String, &BStr ); peo!(&BStr, String );
90peo!(&?OsStr, &BStr ); peo!(&BStr, &?OsStr );
91peo!(OsString, &BStr ); peo!(&BStr, OsString );
92peo!(&?Path, &BStr ); peo!(&BStr, &?Path );
93peo!(PathBuf, &BStr ); peo!(&BStr, PathBuf );
94peo!(Cow<'_, [u16]>, &BStr ); peo!(&BStr, Cow<'_, [u16]> );
95peo!(Cow<'_, str>, &BStr ); peo!(&BStr, Cow<'_, str> );
96peo!(Cow<'_, OsStr>, &BStr ); peo!(&BStr, Cow<'_, OsStr> );
97peo!(Cow<'_, Path>, &BStr ); peo!(&BStr, Cow<'_, Path> );
98
99peo!(&?str, BString); peo!(BString, &?str );
101peo!(&?[u16], BString); peo!(BString, &?[u16] );
102peo!(String, BString); peo!(BString, String );
103peo!(&?OsStr, BString); peo!(BString, &?OsStr );
104peo!(OsString, BString); peo!(BString, OsString );
105peo!(&?Path, BString); peo!(BString, &?Path );
106peo!(PathBuf, BString); peo!(BString, PathBuf );
107peo!(Cow<'_, [u16]>, BString); peo!(BString, Cow<'_, [u16]> );
108peo!(Cow<'_, str>, BString); peo!(BString, Cow<'_, str> );
109peo!(Cow<'_, OsStr>, BString); peo!(BString, Cow<'_, OsStr> );
110peo!(Cow<'_, Path>, BString); peo!(BString, Cow<'_, Path> );
111
112
113
114impl<'s> UTF16ish<'s> for BStr {
115 type Iter = std::iter::Copied<std::slice::Iter<'s, u16>>;
116 fn utf16ish(&'s self) -> Self::Iter { self.units().iter().copied() }
117}
118
119impl<'s> UTF16ish<'s> for BString {
120 type Iter = std::iter::Copied<std::slice::Iter<'s, u16>>;
121 fn utf16ish(&'s self) -> Self::Iter { self.units().iter().copied() }
122}
123
124
125
126impl BString {
127 pub fn from_str(s: impl AsRef<str>) -> Option<Self> { Self::from_code_units(ESI::new(s.as_ref().encode_utf16())) }
129
130 pub fn from_osstr(s: impl AsRef<OsStr>) -> Option<Self> { Self::from_code_units(ESI::new(s.as_ref().encode_wide())) }
132
133 pub fn from_bstr(s: impl AsRef<BStr>) -> Option<Self> { Self::from_code_units(s.as_ref().units().iter().copied()) }
135}
136
137
138
139impl BStr {
140 pub fn as_lpcwstr(&self) -> LPCWSTR { self.as_bstr() }
142
143 pub fn len320(&self) -> u32 { self.len32() + 1 }
147
148 #[cfg(not(target_pointer_width = "16"))]
152 pub fn len(&self) -> usize { self.len32() as usize }
153
154 #[cfg(not(target_pointer_width = "16"))]
158 pub fn len0(&self) -> usize { self.len320() as usize }
159
160 #[cfg(not(target_pointer_width = "16"))]
164 pub fn units(&self) -> &[u16] { let u = self.units0(); &u[..u.len()-1] }
165}
166
167
168
169struct ESI<I: Iterator> {
171 len: usize,
172 iter: I,
173}
174
175impl<I: Iterator + Clone> ESI<I> {
176 pub fn new(iter: I) -> Self {
177 Self {
178 len: iter.clone().count(),
179 iter,
180 }
181 }
182}
183
184impl<I: Iterator> Iterator for ESI<I> {
185 type Item = I::Item;
186 fn next(&mut self) -> Option<Self::Item> { self.iter.next() }
187}
188
189impl<I: Iterator> ExactSizeIterator for ESI<I> {
190 fn len(&self) -> usize { self.len }
191}