summaryrefslogtreecommitdiffstats
path: root/vendor/mime/src/parse.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/mime/src/parse.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/mime/src/parse.rs')
-rw-r--r--vendor/mime/src/parse.rs93
1 files changed, 92 insertions, 1 deletions
diff --git a/vendor/mime/src/parse.rs b/vendor/mime/src/parse.rs
index d55e5494c..20022b775 100644
--- a/vendor/mime/src/parse.rs
+++ b/vendor/mime/src/parse.rs
@@ -5,7 +5,7 @@ use std::fmt;
use std::iter::Enumerate;
use std::str::Bytes;
-use super::{Mime, Source, ParamSource, Indexed, CHARSET, UTF_8};
+use super::{Mime, MimeIter, Source, ParamSource, Indexed, CHARSET, UTF_8};
#[derive(Debug)]
pub enum ParseError {
@@ -49,6 +49,65 @@ impl Error for ParseError {
}
}
+impl<'a> MimeIter<'a> {
+ /// A new iterator over mimes or media types
+ pub fn new(s: &'a str) -> Self {
+ Self {
+ pos: 0,
+ source: s,
+ }
+ }
+}
+
+impl<'a> Iterator for MimeIter<'a> {
+ type Item = Result<Mime, &'a str>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let start = self.pos;
+ let len = self.source.bytes().len();
+
+ if start >= len {
+ return None
+ }
+
+ // Try parsing the whole remaining slice, until the end
+ match parse(&self.source[start ..len]) {
+ Ok(value) => {
+ self.pos = len;
+ Some(Ok(value))
+ }
+ Err(ParseError::InvalidToken { pos, .. }) => {
+ // The first token is immediately found to be wrong by `parse`. Skip it
+ if pos == 0 {
+ self.pos += 1;
+ return self.next()
+ }
+ let slice = &self.source[start .. start + pos];
+ // Try parsing the longest slice (until the first invalid token)
+ return match parse(slice) {
+ Ok(mime) => {
+ self.pos = start + pos + 1;
+ Some(Ok(mime))
+ }
+ Err(_) => {
+ if start + pos < len {
+ // Skip this invalid slice,
+ // try parsing the remaining slice in the next iteration
+ self.pos = start + pos;
+ Some(Err(slice))
+ } else {
+ None
+ }
+ }
+ }
+ }
+ // Do not process any other error condition: the slice is malformed and
+ // no character is found to be invalid: a character is missing
+ Err(_) => None,
+ }
+ }
+}
+
pub fn parse(s: &str) -> Result<Mime, ParseError> {
if s == "*/*" {
return Ok(::STAR_STAR);
@@ -361,3 +420,35 @@ fn test_lookup_tables() {
assert_eq!(valid, should, "{:?} ({}) should be {}", i as char, i, should);
}
}
+
+#[test]
+fn test_parse_iterator() {
+ let mut iter = MimeIter::new("application/json, application/json");
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next(), None);
+
+ let mut iter = MimeIter::new("application/json");
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next(), None);
+
+ let mut iter = MimeIter::new("application/json; ");
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_parse_iterator_invalid() {
+ let mut iter = MimeIter::new("application/json, invalid, application/json");
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next().unwrap().unwrap_err(), "invalid");
+ assert_eq!(iter.next().unwrap().unwrap(), parse("application/json").unwrap());
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_parse_iterator_all_invalid() {
+ let mut iter = MimeIter::new("application/json, text/html");
+ assert_eq!(iter.next().unwrap().unwrap_err(), "application/json");
+ assert_eq!(iter.next(), None);
+}