diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 23ce42626d948..65433c528bc52 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -397,20 +397,43 @@ pub mod reader { } } - pub fn docs(d: Doc, mut it: F) -> bool where - F: FnMut(usize, Doc) -> bool, - { - let mut pos = d.start; - while pos < d.end { - let elt_tag = try_or!(tag_at(d.data, pos), false); - let elt_size = try_or!(tag_len_at(d.data, elt_tag), false); - pos = elt_size.next + elt_size.val; - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(elt_tag.val, doc) { - return false; + pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> { + DocsIterator { + d: d + } + } + + pub struct DocsIterator<'a> { + d: Doc<'a>, + } + + impl<'a> Iterator for DocsIterator<'a> { + type Item = (usize, Doc<'a>); + + fn next(&mut self) -> Option<(usize, Doc<'a>)> { + if self.d.start >= self.d.end { + return None; } + + let elt_tag = try_or!(tag_at(self.d.data, self.d.start), { + self.d.start = self.d.end; + None + }); + let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), { + self.d.start = self.d.end; + None + }); + + let end = elt_size.next + elt_size.val; + let doc = Doc { + data: self.d.data, + start: elt_size.next, + end: end, + }; + + self.d.start = end; + return Some((elt_tag.val, doc)); } - return true; } pub fn tagged_docs(d: Doc, tg: usize, mut it: F) -> bool where diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 2f2a5d31c9f77..2c11ee8baa9d6 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -275,25 +275,18 @@ fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec { fn item_path(item_doc: rbml::Doc) -> Vec { let path_doc = reader::get_doc(item_doc, tag_path); - - let len_doc = reader::get_doc(path_doc, tag_path_len); - let len = reader::doc_as_u32(len_doc) as usize; - - let mut result = Vec::with_capacity(len); - reader::docs(path_doc, |tag, elt_doc| { + reader::docs(path_doc).filter_map(|(tag, elt_doc)| { if tag == tag_path_elem_mod { let s = elt_doc.as_str_slice(); - result.push(ast_map::PathMod(token::intern(s))); + Some(ast_map::PathMod(token::intern(s))) } else if tag == tag_path_elem_name { let s = elt_doc.as_str_slice(); - result.push(ast_map::PathName(token::intern(s))); + Some(ast_map::PathName(token::intern(s))) } else { // ignore tag_path_len element + None } - true - }); - - result + }).collect() } fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 328972c54e377..894a7db21be1d 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1706,7 +1706,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn decode_side_tables(dcx: &DecodeContext, ast_doc: rbml::Doc) { let tbl_doc = ast_doc.get(c::tag_table as usize); - reader::docs(tbl_doc, |tag, entry_doc| { + for (tag, entry_doc) in reader::docs(tbl_doc) { let mut entry_dsr = reader::Decoder::new(entry_doc); let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap(); let id = dcx.tr_id(id0); @@ -1815,8 +1815,7 @@ fn decode_side_tables(dcx: &DecodeContext, } debug!(">< Side table doc loaded"); - true - }); + } } // ______________________________________________________________________