diff options
| author | Martin Fischer <martin@push-f.com> | 2023-08-16 12:00:29 +0200 | 
|---|---|---|
| committer | Martin Fischer <martin@push-f.com> | 2023-08-19 13:41:55 +0200 | 
| commit | 180f6d6111b966627aa00a4017b6fb9751f7386c (patch) | |
| tree | 4a0b638eebf352761da3425370ba3ac8dbad73c5 /src | |
| parent | 78c2066021deda483a4f0a1bb575543d98d27dca (diff) | |
perf: only store start offsets for attribute spans
This spares us two usizes per AttrInternal<Range<usize>>.
So on a 64 bit target where a usize is 8 bytes this spares
us 16 bytes of memory per attribute (if spans are enabled,
... for Token<()> this obviously doesn't change anything).
And the DefaultEmitter now also no longer has to update the
spans on each Emitter::push_attribute_(name|value) call.
The spans are now calculated on demand by the Attribute methods,
which is fine since the assumption is that API users are only
interested in a few specific spans (rather than all spans).
Diffstat (limited to 'src')
| -rw-r--r-- | src/attr.rs | 24 | ||||
| -rw-r--r-- | src/emitter.rs | 20 | 
2 files changed, 26 insertions, 18 deletions
| diff --git a/src/attr.rs b/src/attr.rs index a56eb95..4c7e330 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -30,8 +30,10 @@ pub struct AttributeMap<O> {  #[derive(Debug, Eq, PartialEq)]  pub(crate) struct AttrInternal<O> {      pub value: String, -    pub name_span: Range<O>, -    pub value_span: Range<O>, +    /// The start offset of the attribute name. +    pub name_offset: O, +    /// The start offset of the attribute value. +    pub value_offset: O,  }  /// An HTML attribute borrowed from an [`AttributeMap`]. @@ -74,14 +76,14 @@ impl<'a, O: Offset> Attribute<'a, O> {          &self.map_val.value      } -    /// Returns the span of the attribute name. +    /// Calculates the span of the attribute name and returns it.      pub fn name_span(&self) -> Range<O> { -        self.map_val.name_span.clone() +        self.map_val.name_offset..self.map_val.name_offset + self.name.len()      } -    /// Returns the span of the attribute value. +    /// Calculates the span of the attribute value and returns it.      pub fn value_span(&self) -> Range<O> { -        self.map_val.value_span.clone() +        self.map_val.value_offset..self.map_val.value_offset + self.map_val.value.len()      }  } @@ -154,8 +156,8 @@ impl<O: Default> FromIterator<(String, String)> for AttributeMap<O> {                          name,                          AttrInternal {                              value, -                            name_span: O::default()..O::default(), -                            value_span: O::default()..O::default(), +                            name_offset: O::default(), +                            value_offset: O::default(),                          },                      )                  }) @@ -163,3 +165,9 @@ impl<O: Default> FromIterator<(String, String)> for AttributeMap<O> {          }      }  } + +impl<O: Offset> AttrInternal<O> { +    pub(crate) fn name_span(&self, name_len: usize) -> Range<O> { +        self.name_offset..self.name_offset + name_len +    } +} diff --git a/src/emitter.rs b/src/emitter.rs index 9dfb363..17a4882 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -205,7 +205,7 @@ impl<O> DefaultEmitter<O> {      fn flush_current_attribute(&mut self)      where -        O: Clone, +        O: Offset,      {          if let Some((name, map_val)) = self.current_attribute.take() {              match self.current_token { @@ -213,14 +213,16 @@ impl<O> DefaultEmitter<O> {                      Entry::Vacant(vacant) => {                          vacant.insert(map_val);                      } -                    Entry::Occupied(_) => { -                        self.push_error(Error::DuplicateAttribute, map_val.name_span); +                    Entry::Occupied(entry) => { +                        let name_len = entry.key().len(); +                        self.push_error(Error::DuplicateAttribute, map_val.name_span(name_len));                      }                  },                  Some(Token::EndTag(_)) => { -                    self.attr_in_end_tag_span = Some(map_val.name_span.clone()); +                    let name_span = map_val.name_span(name.len()); +                    self.attr_in_end_tag_span = Some(name_span.clone());                      if !self.seen_attributes.insert(name) { -                        self.push_error(Error::DuplicateAttribute, map_val.name_span); +                        self.push_error(Error::DuplicateAttribute, name_span);                      }                  }                  _ => { @@ -380,25 +382,23 @@ impl<O: Offset> Emitter<O> for DefaultEmitter<O> {          self.current_attribute = Some((              String::new(),              crate::attr::AttrInternal { -                name_span: offset..offset, +                name_offset: offset,                  value: String::new(), -                value_span: Range::default(), +                value_offset: O::default(),              },          ));      }      fn init_attribute_value(&mut self, offset: O, _quoted: bool) { -        self.current_attribute.as_mut().unwrap().1.value_span = offset..offset; +        self.current_attribute.as_mut().unwrap().1.value_offset = offset;      }      fn push_attribute_name(&mut self, s: &str) {          let current_attr = self.current_attribute.as_mut().unwrap();          current_attr.0.push_str(s); -        current_attr.1.name_span.end += s.len();      }      fn push_attribute_value(&mut self, s: &str) {          let current_attr = self.current_attribute.as_mut().unwrap();          current_attr.1.value.push_str(s); -        current_attr.1.value_span.end += s.len();      }      fn set_doctype_public_identifier(&mut self, value: &str) {          if let Some(Token::Doctype(Doctype { | 
