mail_parser/parsers/
mime.rsuse crate::decoders::DecodeResult;
use super::message::MessageStream;
pub(crate) fn seek_next_part(stream: &mut MessageStream, boundary: &[u8]) -> bool {
if !boundary.is_empty() {
let mut pos = stream.pos;
let mut match_count = 0;
for ch in &stream.data[pos..] {
pos += 1;
if ch == &boundary[match_count] {
match_count += 1;
if match_count == boundary.len() {
stream.pos = pos;
return true;
} else {
continue;
}
} else if match_count > 0 {
if ch == &boundary[0] {
match_count = 1;
continue;
} else {
match_count = 0;
}
}
}
}
false
}
pub(crate) fn get_bytes_to_boundary<'x>(
stream: &MessageStream<'x>,
start_pos: usize,
boundary: &[u8],
_is_word: bool,
) -> (usize, DecodeResult) {
let mut read_pos = start_pos;
if !boundary.is_empty() {
let mut match_count = 0;
let mut cr_pos = 0;
let mut lf_pos = 0;
for ch in &stream.data[read_pos..] {
read_pos += 1;
if ch == &boundary[match_count] {
match_count += 1;
if match_count == boundary.len() {
if is_boundary_end(stream, read_pos) {
let mut match_pos = read_pos - match_count;
if match_pos > 0 && match_pos == lf_pos {
if lf_pos == cr_pos + 1 {
match_pos -= 2;
} else {
match_pos -= 1;
}
}
return (
read_pos - start_pos,
if start_pos < match_pos {
DecodeResult::Borrowed((start_pos, match_pos))
} else {
DecodeResult::Empty
},
);
} else {
match_count = 0;
}
}
continue;
} else if match_count > 0 {
if ch == &boundary[0] {
match_count = 1;
continue;
} else {
match_count = 0;
}
}
if ch == &b'\r' {
cr_pos = read_pos;
} else if ch == &b'\n' {
lf_pos = read_pos;
}
}
(0, DecodeResult::Empty)
} else if start_pos < stream.data.len() {
(
stream.data.len() - start_pos,
DecodeResult::Borrowed((start_pos, stream.data.len())),
)
} else {
(0, DecodeResult::Empty)
}
}
#[inline(always)]
pub(crate) fn is_boundary_end(stream: &MessageStream, pos: usize) -> bool {
matches!(
stream.data.get(pos..),
Some([b'\n' | b'\r' | b' ' | b'\t', ..]) | Some([b'-', b'-', ..]) | Some([]) | None
)
}
pub(crate) fn skip_multipart_end(stream: &mut MessageStream) -> bool {
match stream.data.get(stream.pos..stream.pos + 2) {
Some(b"--") => {
if let Some(byte) = stream.data.get(stream.pos + 2) {
if !(*byte).is_ascii_whitespace() {
return false;
}
}
stream.pos += 2;
true
}
_ => false,
}
}
#[inline(always)]
pub(crate) fn skip_crlf(stream: &mut MessageStream) {
for ch in &stream.data[stream.pos..] {
match ch {
b'\r' | b' ' | b'\t' => stream.pos += 1,
b'\n' => {
stream.pos += 1;
break;
}
_ => break,
}
}
}
#[inline(always)]
pub(crate) fn seek_crlf(stream: &MessageStream, mut start_pos: usize) -> usize {
for ch in &stream.data[start_pos..] {
match ch {
b'\r' | b' ' | b'\t' => start_pos += 1,
b'\n' => {
start_pos += 1;
break;
}
_ => break,
}
}
start_pos
}