Недавно я делаю аналог iostream C++ для ржавчины, но меня смущает система времени жизни. Я хочу сохранить ссылку на читатель или голый читатель в IStream
, поэтому я сохраняю Q
в структуре. И затем я использую фантомный тип D
для преобразования Q
в R
.
Вот объяснение:
R
— этоReader
, где мне действительно нужно.Q
— это тип хранилищаR
, поэтомуQ
может быть голымR
или ссылкой&mut R
.- Я использую
D
для преобразованияQ
вR
. Потому чтоborrow_from_mut(&mut R)
дает мне&mut R
, аborrow_from_mut(R)
также дает мне&mut R
. Таким образом, это может бытьD: BorrowFromMut<Q>
. - и
D
можно преобразовать вR
путем разыменования. Итак,&mut D: DerefMut<R>
- потому что
&mut D
можно разыменовать наD
, но мне нужно&mut D
разыменовать наR
, здесь нужно использоватьtrait object
для динамической отправки методаderef_mut
из-за отсутствияUFCS
. (трюк:let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
)
Такой трюк позволяет IStream
хранить как &mut R
, так и R
.
Но код не может скомпилироваться из-за пожизненной проблемы:
let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
//the Q borrowed from the RefCell only valid in the block, doesn't out live 'c.
как я могу это решить?
вот пример кода:
pub struct IStream<'a,'b,R:'a+'b,Q:'a+'b,Sized? D:'b> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
istream: Rc<RefCell<Q>>
}
impl<'a,'b,R,Q,D> Clone for IStream<'a,'b,R,Q,D> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
fn clone(&self) -> IStream<'a,'b,R,Q,D> {
IStream {
istream: self.istream.clone()
}
}
}
impl<'a,'b,'c,F,R,Q,D> Shr<&'b mut F,IStream<'a,'c,R,Q,D>> for IStream<'a,'c,R,Q,D> where R: Reader, F: FromStr + Default, D: BorrowFromMut<Q>, &'c mut D: DerefMut<R> {
fn shr(mut self, output: &mut F) -> IStream<'a,'c,R,Q,D> {
let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
let mut reader: &mut D = BorrowFromMut::borrow_from_mut(tmp);
let mut real_reader: &DerefMut<R> = &reader;
let mut buf = String::new(); // a string buffer
loop {
if let Ok(byte) = (*real_reader.deref_mut()).read_byte() {
if byte == '\u{A}' as u8 || byte == '\u{20}' as u8 {
break
} else {
buf.push(byte as char);
}
} else {
break
}
}
*output = FromStr::from_str(buf[]).unwrap_or_default();
IStream {
istream: self.istream.clone()
}
}
}