From e2c9944f1b86df2a9a6f8e4bfe350dcf154df1a9 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 4 Oct 2021 16:30:34 -0400 Subject: [PATCH] tamer: Move Sections map from unique from writer into Sections We're implementing an new XIR-based writer and don't want to have to duplicate this; it didn't really belong there to begin with. --- tamer/src/ir/asg/section.rs | 67 ++++++++++++++++++++++++++++++- tamer/src/obj/xmle/writer/xmle.rs | 10 +---- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/tamer/src/ir/asg/section.rs b/tamer/src/ir/asg/section.rs index 10dd571d..7ad355f2 100644 --- a/tamer/src/ir/asg/section.rs +++ b/tamer/src/ir/asg/section.rs @@ -24,6 +24,9 @@ //! //! [`SortableAsg::sort`]: super::SortableAsg::sort +use super::IdentObjectData; +use crate::sym::SymbolId; +use fxhash::FxHashSet; use std::iter::Chain; use std::slice::Iter; @@ -121,7 +124,7 @@ pub struct Sections<'a, T> { pub rater: Section<'a, T>, } -impl<'a, T> Sections<'a, T> { +impl<'a, T: IdentObjectData> Sections<'a, T> { /// New collection of empty sections. pub fn new() -> Self { Self { @@ -189,6 +192,19 @@ impl<'a, T> Sections<'a, T> { SectionsIter(SectionsIterType::Single(self.map.iter())) } + /// Iterate over each unique map `from` entry. + /// + /// Multiple mappings may reference the same source field, + /// which would produce duplicate values if they are not filtered. + pub fn iter_map_froms_uniq(&self) -> impl Iterator { + self.iter_map() + .filter_map(|ident| { + ident.src().expect("internal error: missing map src").from + }) + .collect::>() + .into_iter() + } + /// Construct an iterator over the return map section. pub fn iter_retmap(&self) -> SectionsIter { SectionsIter(SectionsIterType::Single(self.retmap.iter())) @@ -236,12 +252,20 @@ impl<'a, T> Iterator for SectionsIter<'a, T> { SectionsIterType::Single(inner) => inner.next(), } } + + fn size_hint(&self) -> (usize, Option) { + match &self.0 { + SectionsIterType::All(inner) => inner.size_hint(), + SectionsIterType::Static(inner) => inner.size_hint(), + SectionsIterType::Single(inner) => inner.size_hint(), + } + } } #[cfg(test)] mod test { use super::*; - use crate::ir::asg::IdentObject; + use crate::ir::asg::{IdentKind, IdentObject, Source}; use crate::sym::GlobalSymbolIntern; type Sut<'a, 'i> = Section<'a, IdentObject>; @@ -376,4 +400,43 @@ mod test { objs.iter().collect::>() ); } + + #[test] + fn sections_iter_map_froms_uniq() { + let mut sut_a = Sections::new(); + let mut sut_b = Sections::new(); + + let a = IdentObject::Ident( + "a".intern(), + IdentKind::Map, + Source { + from: Some("froma".intern()), + ..Default::default() + }, + ); + + let b = IdentObject::Ident( + "a".intern(), + IdentKind::Map, + Source { + from: Some("fromb".intern()), + ..Default::default() + }, + ); + + // A contains duplicates. + sut_a.map.body.push(&a); + sut_a.map.body.push(&a); + sut_a.map.body.push(&b); + + // B does not. + sut_b.map.body.push(&a); + sut_b.map.body.push(&b); + + // They should compare the same. + assert_eq!( + sut_a.iter_map_froms_uniq().collect::>(), + sut_b.iter_map_froms_uniq().collect::>(), + ); + } } diff --git a/tamer/src/obj/xmle/writer/xmle.rs b/tamer/src/obj/xmle/writer/xmle.rs index ed40b367..8f38da1c 100644 --- a/tamer/src/obj/xmle/writer/xmle.rs +++ b/tamer/src/obj/xmle/writer/xmle.rs @@ -22,7 +22,6 @@ use crate::ir::asg::{ IdentKind, IdentObject, IdentObjectData, Sections, SectionsIter, }; use crate::sym::{GlobalSymbolResolve, SymbolId}; -use fxhash::FxHashSet; #[cfg(test)] use mock::MockXmlWriter as XmlWriter; use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; @@ -302,14 +301,7 @@ impl XmleWriter { &mut self, sections: &Sections, ) -> Result<&mut XmleWriter> { - let map_froms: FxHashSet = sections - .iter_map() - .filter_map(|ident| { - ident.src().expect("internal error: missing map src").from - }) - .collect(); - - for from in map_froms { + for from in sections.iter_map_froms_uniq() { let name: &str = &from.lookup_str(); self.writer.write_event(Event::Empty(