In the current, the trait Index
has the following behavior
pub trait Index<Idx: ?Sized> {
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}
This means, the return type is at least a reference type. This make it hard to implement Index
for a type A
that the operation A[x]
would have some exception. In other words, if we want the Output
to be Resut<T>
or Option<T>
, in this cases, the return type would be the reference to Output
, which does invovle the lifetime
issue. It is no way to implement such a behavior if A
does not have a inner field of type Resut<T>
or Option<T>
. Consider we want to implement Index
for a file
which might have io
error, and we want the operation [x]
on file
can emit that error out.
For example:
use std::io::prelude::*;
struct FileReader<'a> {
file: std::fs::File,
buff: Vec<u8>,
_marker: PhantomData<&'a u8>,
}
impl<'a> Index<std::ops::Range<usize>> for FileReader<'a> {
type Output = std::io::Result<&'a [u8]>;
fn index<'b>(&'b self, index: std::ops::Range<usize>) -> &'b Self::Output {
unimplemented!()
}
}
impl<'a> IndexMut<std::ops::Range<usize>> for FileReader<'a> {
fn index_mut<'b>(&'b mut self, index: std::ops::Range<usize>) -> &'b mut Self::Output {
let begin = index.start;
let size = index.end - index.start - 1;
self.buff.resize(size, b'\0');
self.file.seek(std::io::SeekFrom::Start(begin as u64));
match self.file.read(&self.buff[0..]) {
Ok(_) => & mut Ok(&self.buff[0..]) // error
Err(e) => & mut Err(e) // error
}
}
}
In this case, we do not have a way to construct a Result<&[u8]>
that outlives b
if we do not have a field of type Result<&[u8]>
in Self
.
Is any possible to let user designate what is the return type of the index
method through just specify the return type is Self::Output
rather than &Self::Output
?