#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
use core::{ffi::CStr, ops::RangeFrom, slice, slice::SliceIndex};
#[cfg(feature = "std")]
use std::{
borrow::Borrow,
collections::{BTreeMap, HashMap, VecDeque},
ffi::{CStr, CString, OsStr, OsString},
hash::Hash,
ops::{RangeFrom, RangeFull},
slice,
slice::SliceIndex,
};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{
borrow::Borrow,
collections::{btree_map::BTreeMap, vec_deque::VecDeque},
ffi::CString,
string::String,
vec::Vec,
};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use core::ops::RangeFull;
pub trait TryIndex<Idx>
where
Idx: ?Sized,
{
type Output: ?Sized;
fn try_index(&self, index: Idx) -> Option<&Self::Output>;
}
pub trait TryIndexMut<Idx>
where
Idx: ?Sized,
{
type Output: ?Sized;
fn try_index_mut(&mut self, index: Idx) -> Option<&mut Self::Output>;
}
impl<T, I> TryIndex<I> for [T]
where
I: SliceIndex<[T]>,
{
type Output = <I as SliceIndex<[T]>>::Output;
fn try_index(&self, index: I) -> Option<&Self::Output> {
self.get(index)
}
}
impl<T, I> TryIndexMut<I> for [T]
where
I: SliceIndex<[T]>,
{
type Output = <I as SliceIndex<[T]>>::Output;
fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
impl<T, I, const N: usize> TryIndex<I> for [T; N]
where
[T]: TryIndex<I, Output = T>,
{
type Output = T;
fn try_index(&self, index: I) -> Option<&Self::Output> {
self.as_slice().try_index(index)
}
}
impl<T, I, const N: usize> TryIndexMut<I> for [T; N]
where
[T]: TryIndexMut<I, Output = T>,
{
type Output = T;
fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
self.as_mut_slice().try_index_mut(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T, I> TryIndex<I> for Vec<T>
where
I: SliceIndex<[T]>,
{
type Output = <I as SliceIndex<[T]>>::Output;
fn try_index(&self, index: I) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T, I> TryIndexMut<I> for Vec<T>
where
I: SliceIndex<[T]>,
{
type Output = <I as SliceIndex<[T]>>::Output;
fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> TryIndex<usize> for VecDeque<T> {
type Output = T;
fn try_index(&self, index: usize) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> TryIndexMut<usize> for VecDeque<T> {
type Output = T;
fn try_index_mut(&mut self, index: usize) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
#[cfg(feature = "std")]
impl<K, Q, V> TryIndex<&Q> for HashMap<K, V>
where
K: Eq + Hash + Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
type Output = V;
fn try_index(&self, index: &Q) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(feature = "std")]
impl<K, Q, V> TryIndexMut<&Q> for HashMap<K, V>
where
K: Eq + Hash + Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
type Output = V;
fn try_index_mut(&mut self, index: &Q) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<K, Q, V> TryIndex<&Q> for BTreeMap<K, V>
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
type Output = V;
fn try_index(&self, index: &Q) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<K, Q, V> TryIndexMut<&Q> for BTreeMap<K, V>
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
type Output = V;
fn try_index_mut(&mut self, index: &Q) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<I> TryIndex<I> for str
where
I: SliceIndex<str>,
{
type Output = <I as SliceIndex<str>>::Output;
fn try_index(&self, index: I) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<I> TryIndexMut<I> for str
where
I: SliceIndex<str>,
{
type Output = <I as SliceIndex<str>>::Output;
fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<I> TryIndex<I> for String
where
I: SliceIndex<str>,
{
type Output = <I as SliceIndex<str>>::Output;
fn try_index(&self, index: I) -> Option<&Self::Output> {
self.get(index)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<I> TryIndexMut<I> for String
where
I: SliceIndex<str>,
{
type Output = <I as SliceIndex<str>>::Output;
fn try_index_mut(&mut self, index: I) -> Option<&mut Self::Output> {
self.get_mut(index)
}
}
impl TryIndex<RangeFrom<usize>> for CStr {
type Output = CStr;
fn try_index(&self, index: RangeFrom<usize>) -> Option<&Self::Output> {
let l = self.count_bytes();
match index.start <= l {
true => Some(unsafe {
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
&*(self.as_ptr() as *const u8).add(index.start),
l - index.start + 1,
))
}),
false => None,
}
}
}
#[test]
fn cstr_test() {
let string = c"Test";
assert_eq!(string.try_index(2..), Some(c"st"));
assert_eq!(string.try_index(4..), Some(c""));
assert_eq!(string.try_index(5..), None);
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl TryIndex<RangeFull> for CString {
type Output = CStr;
fn try_index(&self, index: RangeFull) -> Option<&Self::Output> {
Some(&self[index])
}
}
#[cfg(feature = "std")]
impl TryIndex<RangeFull> for OsString {
type Output = OsStr;
fn try_index(&self, index: RangeFull) -> Option<&Self::Output> {
Some(&self[index])
}
}