Skip to content

Commit

Permalink
Merge pull request #759 from Mingun/const
Browse files Browse the repository at this point in the history
Make `const` as many functions as possible
  • Loading branch information
Mingun committed Jun 16, 2024
2 parents d66df32 + 4543ba6 commit 5629ac7
Show file tree
Hide file tree
Showing 16 changed files with 175 additions and 97 deletions.
27 changes: 27 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,37 @@
### Misc Changes

- [#650]: Change the type of `Event::PI` to a new dedicated `BytesPI` type.
- [#759]: Make `const` as much functions as possible:
- `resolve_html5_entity()`
- `resolve_predefined_entity()`
- `resolve_xml_entity()`
- `Attr::key()`
- `Attr::value()`
- `Attributes::html()`
- `Attributes::new()`
- `BytesDecl::from_start()`
- `Decoder::encoding()`
- `Deserializer::get_ref()`
- `IoReader::get_ref()`
- `LocalName::into_inner()`
- `Namespace::into_inner()`
- `NsReader::config()`
- `NsReader::prefixes()`
- `Prefix::into_inner()`
- `QName::into_inner()`
- `Reader::buffer_position()`
- `Reader::config()`
- `Reader::decoder()`
- `Reader::error_position()`
- `Reader::get_ref()`
- `SliceReader::get_ref()`
- `Writer::get_ref()`
- `Writer::new()`

[#650]: https://github.com/tafia/quick-xml/issues/650
[#755]: https://github.com/tafia/quick-xml/pull/755
[#758]: https://github.com/tafia/quick-xml/pull/758
[#759]: https://github.com/tafia/quick-xml/pull/759


## 0.32.0 -- 2024-06-10
Expand Down
10 changes: 5 additions & 5 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2155,7 +2155,7 @@ impl<'i, R: XmlRead<'i>, E: EntityResolver> XmlReader<'i, R, E> {
}

/// Returns `true` if all events was consumed
fn is_empty(&self) -> bool {
const fn is_empty(&self) -> bool {
matches!(self.lookahead, Ok(PayloadEvent::Eof))
}

Expand All @@ -2166,7 +2166,7 @@ impl<'i, R: XmlRead<'i>, E: EntityResolver> XmlReader<'i, R, E> {
}

#[inline(always)]
fn need_trim_end(&self) -> bool {
const fn need_trim_end(&self) -> bool {
// If next event is a text or CDATA, we should not trim trailing spaces
!matches!(
self.lookahead,
Expand Down Expand Up @@ -2464,7 +2464,7 @@ where
/// assert_eq!(reader.error_position(), 28);
/// assert_eq!(reader.buffer_position(), 41);
/// ```
pub fn get_ref(&self) -> &R {
pub const fn get_ref(&self) -> &R {
&self.reader.reader
}

Expand Down Expand Up @@ -3127,7 +3127,7 @@ impl<R: BufRead> IoReader<R> {
/// assert_eq!(reader.error_position(), 28);
/// assert_eq!(reader.buffer_position(), 41);
/// ```
pub fn get_ref(&self) -> &Reader<R> {
pub const fn get_ref(&self) -> &Reader<R> {
&self.reader
}
}
Expand Down Expand Up @@ -3194,7 +3194,7 @@ impl<'de> SliceReader<'de> {
/// assert_eq!(reader.error_position(), 28);
/// assert_eq!(reader.buffer_position(), 41);
/// ```
pub fn get_ref(&self) -> &Reader<&'de [u8]> {
pub const fn get_ref(&self) -> &Reader<&'de [u8]> {
&self.reader
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/de/simple_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ impl<'de, 'a> SimpleTypeDeserializer<'de, 'a> {

/// Constructor for tests
#[inline]
fn new(content: CowRef<'de, 'a, [u8]>, escaped: bool, decoder: Decoder) -> Self {
const fn new(content: CowRef<'de, 'a, [u8]>, escaped: bool, decoder: Decoder) -> Self {
Self {
content,
escaped,
Expand Down
2 changes: 1 addition & 1 deletion src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Decoder {
///
/// [`decode`]: Self::decode
#[cfg(feature = "encoding")]
pub fn encoding(&self) -> &'static Encoding {
pub const fn encoding(&self) -> &'static Encoding {
self.encoding
}

Expand Down
6 changes: 3 additions & 3 deletions src/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ where
/// Behaves like [`resolve_xml_entity`] if feature is not enabled and as
/// [`resolve_html5_entity`] if enabled.
#[inline]
pub fn resolve_predefined_entity(entity: &str) -> Option<&'static str> {
pub const fn resolve_predefined_entity(entity: &str) -> Option<&'static str> {
#[cfg(not(feature = "escape-html"))]
{
resolve_xml_entity(entity)
Expand Down Expand Up @@ -314,7 +314,7 @@ pub fn resolve_predefined_entity(entity: &str) -> Option<&'static str> {
/// ```
///
/// [specification]: https://www.w3.org/TR/xml11/#sec-predefined-ent
pub fn resolve_xml_entity(entity: &str) -> Option<&'static str> {
pub const fn resolve_xml_entity(entity: &str) -> Option<&'static str> {
// match over strings are not allowed in const functions
let s = match entity.as_bytes() {
b"lt" => "<",
Expand All @@ -328,7 +328,7 @@ pub fn resolve_xml_entity(entity: &str) -> Option<&'static str> {
}

/// Resolves all HTML5 entities. For complete list see <https://dev.w3.org/html5/html-author/charref>.
pub fn resolve_html5_entity(entity: &str) -> Option<&'static str> {
pub const fn resolve_html5_entity(entity: &str) -> Option<&'static str> {
// imported from https://dev.w3.org/html5/html-author/charref
// match over strings are not allowed in const functions
//TODO: automate up-to-dating using https://html.spec.whatwg.org/entities.json
Expand Down
16 changes: 8 additions & 8 deletions src/events/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use crate::errors::Result as XmlResult;
use crate::escape::{escape, resolve_predefined_entity, unescape_with};
use crate::name::QName;
use crate::reader::{is_whitespace, Reader};
use crate::utils::{write_byte_string, write_cow_string, Bytes};
use crate::reader::Reader;
use crate::utils::{is_whitespace, write_byte_string, write_cow_string, Bytes};
use std::fmt::{self, Debug, Display, Formatter};
use std::iter::FusedIterator;
use std::{borrow::Cow, ops::Range};
Expand Down Expand Up @@ -195,20 +195,20 @@ pub struct Attributes<'a> {
impl<'a> Attributes<'a> {
/// Internal constructor, used by `BytesStart`. Supplies data in reader's encoding
#[inline]
pub(crate) fn wrap(buf: &'a [u8], pos: usize, html: bool) -> Self {
pub(crate) const fn wrap(buf: &'a [u8], pos: usize, html: bool) -> Self {
Self {
bytes: buf,
state: IterState::new(pos, html),
}
}

/// Creates a new attribute iterator from a buffer.
pub fn new(buf: &'a str, pos: usize) -> Self {
pub const fn new(buf: &'a str, pos: usize) -> Self {
Self::wrap(buf.as_bytes(), pos, false)
}

/// Creates a new attribute iterator from a buffer, allowing HTML attribute syntax.
pub fn html(buf: &'a str, pos: usize) -> Self {
pub const fn html(buf: &'a str, pos: usize) -> Self {
Self::wrap(buf.as_bytes(), pos, true)
}

Expand Down Expand Up @@ -416,7 +416,7 @@ impl<T> Attr<T> {
impl<'a> Attr<&'a [u8]> {
/// Returns the key value
#[inline]
pub fn key(&self) -> QName<'a> {
pub const fn key(&self) -> QName<'a> {
QName(match self {
Attr::DoubleQ(key, _) => key,
Attr::SingleQ(key, _) => key,
Expand All @@ -429,7 +429,7 @@ impl<'a> Attr<&'a [u8]> {
///
/// [HTML specification]: https://www.w3.org/TR/2012/WD-html-markup-20120329/syntax.html#syntax-attr-empty
#[inline]
pub fn value(&self) -> &'a [u8] {
pub const fn value(&self) -> &'a [u8] {
match self {
Attr::DoubleQ(_, value) => value,
Attr::SingleQ(_, value) => value,
Expand Down Expand Up @@ -518,7 +518,7 @@ pub(crate) struct IterState {
}

impl IterState {
pub fn new(offset: usize, html: bool) -> Self {
pub const fn new(offset: usize, html: bool) -> Self {
Self {
state: State::Next(offset),
html,
Expand Down
45 changes: 6 additions & 39 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub mod attributes;
use encoding_rs::Encoding;
use std::borrow::Cow;
use std::fmt::{self, Debug, Formatter};
use std::mem::replace;
use std::ops::Deref;
use std::str::from_utf8;

Expand All @@ -50,12 +51,10 @@ use crate::escape::{
escape, minimal_escape, partial_escape, resolve_predefined_entity, unescape_with,
};
use crate::name::{LocalName, QName};
use crate::reader::{is_whitespace, name_len};
use crate::utils::write_cow_string;
#[cfg(feature = "serialize")]
use crate::utils::CowRef;
use crate::utils::{name_len, trim_xml_end, trim_xml_start, write_cow_string};
use attributes::{Attribute, Attributes};
use std::mem::replace;

/// Opening tag data (`Event::Start`), with optional attributes.
///
Expand All @@ -78,7 +77,7 @@ pub struct BytesStart<'a> {
impl<'a> BytesStart<'a> {
/// Internal constructor, used by `Reader`. Supplies data in reader's encoding
#[inline]
pub(crate) fn wrap(content: &'a [u8], name_len: usize) -> Self {
pub(crate) const fn wrap(content: &'a [u8], name_len: usize) -> Self {
BytesStart {
buf: Cow::Borrowed(content),
name_len,
Expand Down Expand Up @@ -406,7 +405,7 @@ impl<'a> BytesDecl<'a> {
}

/// Creates a `BytesDecl` from a `BytesStart`
pub fn from_start(start: BytesStart<'a>) -> Self {
pub const fn from_start(start: BytesStart<'a>) -> Self {
Self { content: start }
}

Expand Down Expand Up @@ -621,7 +620,7 @@ pub struct BytesEnd<'a> {
impl<'a> BytesEnd<'a> {
/// Internal constructor, used by `Reader`. Supplies data in reader's encoding
#[inline]
pub(crate) fn wrap(name: Cow<'a, [u8]>) -> Self {
pub(crate) const fn wrap(name: Cow<'a, [u8]>) -> Self {
BytesEnd { name }
}

Expand Down Expand Up @@ -1019,7 +1018,7 @@ pub struct BytesPI<'a> {
impl<'a> BytesPI<'a> {
/// Creates a new `BytesPI` from a byte sequence in the specified encoding.
#[inline]
pub(crate) fn wrap(content: &'a [u8], target_len: usize) -> Self {
pub(crate) const fn wrap(content: &'a [u8], target_len: usize) -> Self {
Self {
content: BytesStart::wrap(content, target_len),
}
Expand Down Expand Up @@ -1257,38 +1256,6 @@ fn str_cow_to_bytes<'a, C: Into<Cow<'a, str>>>(content: C) -> Cow<'a, [u8]> {
}
}

/// Returns a byte slice with leading XML whitespace bytes removed.
///
/// 'Whitespace' refers to the definition used by [`is_whitespace`].
const fn trim_xml_start(mut bytes: &[u8]) -> &[u8] {
// Note: A pattern matching based approach (instead of indexing) allows
// making the function const.
while let [first, rest @ ..] = bytes {
if is_whitespace(*first) {
bytes = rest;
} else {
break;
}
}
bytes
}

/// Returns a byte slice with trailing XML whitespace bytes removed.
///
/// 'Whitespace' refers to the definition used by [`is_whitespace`].
const fn trim_xml_end(mut bytes: &[u8]) -> &[u8] {
// Note: A pattern matching based approach (instead of indexing) allows
// making the function const.
while let [rest @ .., last] = bytes {
if is_whitespace(*last) {
bytes = rest;
} else {
break;
}
}
bytes
}

fn trim_cow<'a, F>(value: Cow<'a, [u8]>, trim: F) -> Cow<'a, [u8]>
where
F: FnOnce(&[u8]) -> &[u8],
Expand Down
10 changes: 5 additions & 5 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct QName<'a>(pub &'a [u8]);
impl<'a> QName<'a> {
/// Converts this name to an internal slice representation.
#[inline(always)]
pub fn into_inner(self) -> &'a [u8] {
pub const fn into_inner(self) -> &'a [u8] {
self.0
}

Expand Down Expand Up @@ -137,7 +137,7 @@ pub struct LocalName<'a>(&'a [u8]);
impl<'a> LocalName<'a> {
/// Converts this name to an internal slice representation.
#[inline(always)]
pub fn into_inner(self) -> &'a [u8] {
pub const fn into_inner(self) -> &'a [u8] {
self.0
}
}
Expand Down Expand Up @@ -187,7 +187,7 @@ pub struct Prefix<'a>(&'a [u8]);
impl<'a> Prefix<'a> {
/// Extracts internal slice
#[inline(always)]
pub fn into_inner(self) -> &'a [u8] {
pub const fn into_inner(self) -> &'a [u8] {
self.0
}
}
Expand Down Expand Up @@ -252,7 +252,7 @@ impl<'a> Namespace<'a> {
/// [non-normalized]: https://www.w3.org/TR/xml11/#AVNormalize
/// [IRI reference]: https://datatracker.ietf.org/doc/html/rfc3987
#[inline(always)]
pub fn into_inner(self) -> &'a [u8] {
pub const fn into_inner(self) -> &'a [u8] {
self.0
}
//TODO: implement value normalization and use it when comparing namespaces
Expand Down Expand Up @@ -618,7 +618,7 @@ impl NamespaceResolver {
}

#[inline]
pub fn iter(&self) -> PrefixIter {
pub const fn iter(&self) -> PrefixIter {
PrefixIter {
resolver: self,
// We initialize the cursor to 2 to skip the two default namespaces xml: and xmlns:
Expand Down
4 changes: 2 additions & 2 deletions src/reader/async_tokio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::events::Event;
use crate::name::{QName, ResolveResult};
use crate::reader::buffered_reader::impl_buffered_source;
use crate::reader::{
is_whitespace, BangType, ElementParser, NsReader, ParseState, Parser, PiParser, ReadTextResult,
Reader, Span,
BangType, ElementParser, NsReader, ParseState, Parser, PiParser, ReadTextResult, Reader, Span,
};
use crate::utils::is_whitespace;

/// A struct for read XML asynchronously from an [`AsyncBufRead`].
///
Expand Down
3 changes: 2 additions & 1 deletion src/reader/buffered_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::path::Path;
use crate::errors::{Error, Result};
use crate::events::Event;
use crate::name::QName;
use crate::reader::{is_whitespace, BangType, Parser, ReadTextResult, Reader, Span, XmlSource};
use crate::reader::{BangType, Parser, ReadTextResult, Reader, Span, XmlSource};
use crate::utils::is_whitespace;

macro_rules! impl_buffered_source {
($($lf:lifetime, $reader:tt, $async:ident, $await:ident)?) => {
Expand Down
Loading

0 comments on commit 5629ac7

Please sign in to comment.