1#![cfg_attr(not(feature = "std"), no_std)]
78#[cfg(not(feature = "std"))]
79use core::{ffi::CStr, ops::RangeFrom, slice, slice::SliceIndex};
80#[cfg(feature = "std")]
81use std::{
82 borrow::Borrow,
83 collections::{BTreeMap, HashMap, VecDeque},
84 ffi::{CStr, CString, OsStr, OsString},
85 hash::Hash,
86 ops::{RangeFrom, RangeFull},
87 slice,
88 slice::SliceIndex,
89};
90#[cfg(all(not(feature = "std"), feature = "alloc"))]
91extern crate alloc;
92#[cfg(all(not(feature = "std"), feature = "alloc"))]
93use alloc::{
94 borrow::Borrow,
95 collections::{btree_map::BTreeMap, vec_deque::VecDeque},
96 ffi::CString,
97 string::String,
98 vec::Vec,
99};
100#[cfg(all(not(feature = "std"), feature = "alloc"))]
101use core::ops::RangeFull;
102
103pub trait TryIndex<Idx>
109where
110 Idx: ?Sized,
111{
112 type Output: ?Sized;
113
114 fn try_index(&self, index: Idx) -> Option<&Self::Output>;
115}
116
117pub trait TryIndexMut<Idx>
120where
121 Idx: ?Sized,
122{
123 type Output: ?Sized;
124
125 fn try_index_mut(&mut self, index: Idx) -> Option<&mut Self::Output>;
126}
127
128impl<T, I> TryIndex<I> for [T]
132where
133 I: SliceIndex<[T]>,
134{
135 type Output = <I as SliceIndex<[T]>>::Output;
136
137 fn try_index(&self, index: I) -> Option<&Self::Output> {
138 self.get(index)
139 }
140}
141
142impl<T, I> TryIndexMut<I> for [T]
143where
144 I: SliceIndex<[T]>,
145{
146 type Output = <I as SliceIndex<[T]>>::Output;
147
148 fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
149 self.get_mut(index)
150 }
151}
152
153impl<T, I, const N: usize> TryIndex<I> for [T; N]
157where
158 [T]: TryIndex<I, Output = T>,
159{
160 type Output = T;
161
162 fn try_index(&self, index: I) -> Option<&Self::Output> {
163 self.as_slice().try_index(index)
164 }
165}
166
167impl<T, I, const N: usize> TryIndexMut<I> for [T; N]
168where
169 [T]: TryIndexMut<I, Output = T>,
170{
171 type Output = T;
172
173 fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
174 self.as_mut_slice().try_index_mut(index)
175 }
176}
177
178#[cfg(any(feature = "std", feature = "alloc"))]
182impl<T, I> TryIndex<I> for Vec<T>
183where
184 I: SliceIndex<[T]>,
185{
186 type Output = <I as SliceIndex<[T]>>::Output;
187
188 fn try_index(&self, index: I) -> Option<&Self::Output> {
189 self.get(index)
190 }
191}
192
193#[cfg(any(feature = "std", feature = "alloc"))]
194impl<T, I> TryIndexMut<I> for Vec<T>
195where
196 I: SliceIndex<[T]>,
197{
198 type Output = <I as SliceIndex<[T]>>::Output;
199
200 fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
201 self.get_mut(index)
202 }
203}
204
205#[cfg(any(feature = "std", feature = "alloc"))]
209impl<T> TryIndex<usize> for VecDeque<T> {
210 type Output = T;
211
212 fn try_index(&self, index: usize) -> Option<&Self::Output> {
213 self.get(index)
214 }
215}
216
217#[cfg(any(feature = "std", feature = "alloc"))]
218impl<T> TryIndexMut<usize> for VecDeque<T> {
219 type Output = T;
220
221 fn try_index_mut(&mut self, index: usize) -> Option<&mut Self::Output> {
222 self.get_mut(index)
223 }
224}
225
226#[cfg(feature = "std")]
230impl<K, Q, V> TryIndex<&Q> for HashMap<K, V>
231where
232 K: Eq + Hash + Borrow<Q>,
233 Q: Eq + Hash + ?Sized,
234{
235 type Output = V;
236
237 fn try_index(&self, index: &Q) -> Option<&Self::Output> {
238 self.get(index)
239 }
240}
241
242#[cfg(feature = "std")]
243impl<K, Q, V> TryIndexMut<&Q> for HashMap<K, V>
244where
245 K: Eq + Hash + Borrow<Q>,
246 Q: Eq + Hash + ?Sized,
247{
248 type Output = V;
249
250 fn try_index_mut(&mut self, index: &Q) -> Option<&mut Self::Output> {
251 self.get_mut(index)
252 }
253}
254
255#[cfg(any(feature = "std", feature = "alloc"))]
259impl<K, Q, V> TryIndex<&Q> for BTreeMap<K, V>
260where
261 K: Borrow<Q> + Ord,
262 Q: Ord + ?Sized,
263{
264 type Output = V;
265
266 fn try_index(&self, index: &Q) -> Option<&Self::Output> {
267 self.get(index)
268 }
269}
270
271#[cfg(any(feature = "std", feature = "alloc"))]
272impl<K, Q, V> TryIndexMut<&Q> for BTreeMap<K, V>
273where
274 K: Borrow<Q> + Ord,
275 Q: Ord + ?Sized,
276{
277 type Output = V;
278
279 fn try_index_mut(&mut self, index: &Q) -> Option<&mut Self::Output> {
280 self.get_mut(index)
281 }
282}
283
284#[cfg(any(feature = "std", feature = "alloc"))]
288impl<I> TryIndex<I> for str
289where
290 I: SliceIndex<str>,
291{
292 type Output = <I as SliceIndex<str>>::Output;
293
294 fn try_index(&self, index: I) -> Option<&Self::Output> {
295 self.get(index)
296 }
297}
298
299#[cfg(any(feature = "std", feature = "alloc"))]
300impl<I> TryIndexMut<I> for str
301where
302 I: SliceIndex<str>,
303{
304 type Output = <I as SliceIndex<str>>::Output;
305
306 fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
307 self.get_mut(index)
308 }
309}
310
311#[cfg(any(feature = "std", feature = "alloc"))]
315impl<I> TryIndex<I> for String
316where
317 I: SliceIndex<str>,
318{
319 type Output = <I as SliceIndex<str>>::Output;
320
321 fn try_index(&self, index: I) -> Option<&Self::Output> {
322 self.get(index)
323 }
324}
325
326#[cfg(any(feature = "std", feature = "alloc"))]
327impl<I> TryIndexMut<I> for String
328where
329 I: SliceIndex<str>,
330{
331 type Output = <I as SliceIndex<str>>::Output;
332
333 fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
334 self.get_mut(index)
335 }
336}
337
338impl TryIndex<RangeFrom<usize>> for CStr {
342 type Output = CStr;
343
344 fn try_index(&self, index: RangeFrom<usize>) -> Option<&Self::Output> {
345 let l = self.count_bytes();
346 match index.start <= l {
347 true => Some(unsafe {
348 CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
349 &*(self.as_ptr() as *const u8).add(index.start),
350 l - index.start + 1,
351 ))
352 }),
353 false => None,
354 }
355 }
356}
357
358#[test]
359fn cstr_test() {
360 let string = c"Test";
361 assert_eq!(string.try_index(2..), Some(c"st"));
362 assert_eq!(string.try_index(4..), Some(c""));
363 assert_eq!(string.try_index(5..), None);
364}
365
366#[cfg(any(feature = "std", feature = "alloc"))]
370impl TryIndex<RangeFull> for CString {
371 type Output = CStr;
372
373 fn try_index(&self, index: RangeFull) -> Option<&Self::Output> {
374 Some(&self[index])
375 }
376}
377
378#[cfg(feature = "std")]
382impl TryIndex<RangeFull> for OsString {
383 type Output = OsStr;
384
385 fn try_index(&self, index: RangeFull) -> Option<&Self::Output> {
386 Some(&self[index])
387 }
388}