Timp de mulți ani, trait-ul standard Iterator din biblioteca standard Rust a avut o limitare conceptuală majoră: metoda next(&mut self) -> Option cere ca fiecare element returnat să aibă o durată de viață independentă de durata împrumutului iteratorului. Cu alte cuvinte, un iterator clasic nu poate împrumuta date direct din buffer-ul său intern fără a le clona!
Stabilizarea Generic Associated Types (GATs) a deblocat una dintre cele mai puternice facilități ale sistemului de tipuri: tipurile asociate pot accepta acum parametri generici de tip sau de durată de viață (lifetimes), permițând implementarea pattern-ului de Lending Iterator (Streaming Iterator).
// Trait-ul folosește un tip asociat generic parametrizat pe lifetime-ul împrumutului ('a):
pub trait LendingIterator {
type Item<'a> where Self: 'a;
fn next(&mut self) -> Option>;
}
// O structură de citire care refolosește un singur buffer intern de memorie:
pub struct ChunkReader {
date_totale: Vec,
cursor: usize,
buffer_temporar: Vec,
}
impl ChunkReader {
pub fn new(date: Vec) -> Self {
ChunkReader {
date_totale: date,
cursor: 0,
buffer_temporar: Vec::with_capacity(4),
}
}
}
impl LendingIterator for ChunkReader {
// Tipul asociat este un slice împrumutat din buffer_temporar:
type Item<'a> = &'a [u8] where Self: 'a;
fn next(&mut self) -> Option> {
if self.cursor >= self.date_totale.len() {
return None;
}
self.buffer_temporar.clear();
let sfarsit = (self.cursor + 4).min(self.date_totale.len());
self.buffer_temporar.extend_from_slice(&self.date_totale[self.cursor..sfarsit]);
self.cursor = sfarsit;
Some(&self.buffer_temporar[..])
}
}
fn main() {
let mut reader = ChunkReader::new(vec![10, 20, 30, 40, 50, 60, 70]);
// Consumăm segmentele succesive fără nicio alocare nouă de memorie pe iterație!
while let Some(chunk) = reader.next() {
println!("Segment citit: {:?}", chunk);
}
}
De Ce GATs Sunt Revoluționare pentru Arhitecturile Enterprise?
- Sisteme de Baze de Date și Parsere de Rețea: Un parser HTTP sau un cititor de linii de loguri poate citi datele direct într-un buffer reutilizabil, expunând câmpurile deserializate fără clonare de șiruri.
- Monade Asincrone și Pointeri Inteligenți: Permite crearea de abstracțiuni generice complexe peste structuri precum pointeri de referință sau containere de date tranzacționale.