v0.1.0
This commit is contained in:
parent
1dbb2ab8fc
commit
cf9640069d
11 changed files with 323 additions and 37 deletions
13
.github/FUNDING.yml
vendored
Normal file
13
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: stalwartlabs
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
22
.github/workflows/rust.yml
vendored
Normal file
22
.github/workflows/rust.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
name: "CI"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
|
@ -1,5 +1,13 @@
|
|||
[package]
|
||||
name = "smtp-proto"
|
||||
description = "SMTP protocol parser"
|
||||
authors = [ "Stalwart Labs <hello@stalw.art>"]
|
||||
repository = "https://github.com/stalwartlabs/smtp-proto"
|
||||
homepage = "https://github.com/stalwartlabs/smtp-proto"
|
||||
license = "AGPL-3.0-only"
|
||||
keywords = ["smtp", "lmtp", "protocol", "parser"]
|
||||
categories = ["email", "parser-implementations"]
|
||||
readme = "README.md"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
|
37
README.md
37
README.md
|
@ -1,2 +1,37 @@
|
|||
# smtp-proto
|
||||
SMTP Protocol
|
||||
|
||||
[![crates.io](https://img.shields.io/crates/v/smtp-proto)](https://crates.io/crates/smtp-proto)
|
||||
[![build](https://github.com/stalwartlabs/sieve/actions/workflows/rust.yml/badge.svg)](https://github.com/stalwartlabs/sieve/actions/workflows/rust.yml)
|
||||
[![docs.rs](https://img.shields.io/docsrs/smtp-proto)](https://docs.rs/smtp-proto)
|
||||
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
|
||||
|
||||
_smtp-proto_ is a fast SMTP/LMTP parser for Rust that supports all [registered SMTP service extensions](https://www.iana.org/assignments/mail-parameters/mail-parameters.xhtml).
|
||||
The library is part of Stalwart SMTP and LMTP servers. It is not yet documented so if you need help using the library please start a discussion.
|
||||
|
||||
|
||||
## Testing & Fuzzing
|
||||
|
||||
To run the testsuite:
|
||||
|
||||
```bash
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
To fuzz the library with `cargo-fuzz`:
|
||||
|
||||
```bash
|
||||
$ cargo +nightly fuzz run smtp_proto
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the terms of the [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.en.html) as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
See [LICENSE](LICENSE) for more details.
|
||||
|
||||
You can be released from the requirements of the AGPLv3 license by purchasing
|
||||
a commercial license. Please contact licensing@stalw.art for more details.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright (C) 2020-2023, Stalwart Labs Ltd.
|
||||
|
|
61
src/lib.rs
61
src/lib.rs
|
@ -1,3 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
//! # smtp-proto
|
||||
//!
|
||||
//! [![crates.io](https://img.shields.io/crates/v/smtp-proto)](https://crates.io/crates/smtp-proto)
|
||||
//! [![build](https://github.com/stalwartlabs/sieve/actions/workflows/rust.yml/badge.svg)](https://github.com/stalwartlabs/sieve/actions/workflows/rust.yml)
|
||||
//! [![docs.rs](https://img.shields.io/docsrs/smtp-proto)](https://docs.rs/smtp-proto)
|
||||
//! [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
|
||||
//!
|
||||
//! _smtp-proto_ is a fast SMTP/LMTP parser for Rust that supports all [registered SMTP service extensions](https://www.iana.org/assignments/mail-parameters/mail-parameters.xhtml).
|
||||
//! The library is part of Stalwart SMTP and LMTP servers. It is not yet documented so if you need help using the library please start a discussion.
|
||||
//!
|
||||
//!
|
||||
//! ## Testing & Fuzzing
|
||||
//!
|
||||
//! To run the testsuite:
|
||||
//!
|
||||
//! ```bash
|
||||
//! $ cargo test
|
||||
//! ```
|
||||
//!
|
||||
//! To fuzz the library with `cargo-fuzz`:
|
||||
//!
|
||||
//! ```bash
|
||||
//! $ cargo +nightly fuzz run smtp_proto
|
||||
//! ```
|
||||
//!
|
||||
//! ## License
|
||||
//!
|
||||
//! Licensed under the terms of the [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.en.html) as published by
|
||||
//! the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
//! See [LICENSE](LICENSE) for more details.
|
||||
//!
|
||||
//! You can be released from the requirements of the AGPLv3 license by purchasing
|
||||
//! a commercial license. Please contact licensing@stalw.art for more details.
|
||||
//!
|
||||
//! ## Copyright
|
||||
//!
|
||||
//! Copyright (C) 2020-2023, Stalwart Labs Ltd.
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
pub mod request;
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
pub mod parser;
|
||||
pub mod receiver;
|
||||
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
use std::slice::Iter;
|
||||
|
||||
use crate::*;
|
||||
|
@ -7,6 +30,9 @@ use super::*;
|
|||
#[derive(Default)]
|
||||
pub struct RequestParser {}
|
||||
|
||||
const MAX_ADDRESS_LEN: usize = 256;
|
||||
const MAX_DOMAIN_LEN: usize = 255;
|
||||
|
||||
impl Request<String> {
|
||||
pub fn parse(bytes: &mut Iter<'_, u8>) -> Result<Request<String>, Error> {
|
||||
let mut parser = Rfc5321Parser::new(bytes);
|
||||
|
@ -70,7 +96,7 @@ impl Request<String> {
|
|||
if parser.stop_char != LF {
|
||||
let host = parser.text()?;
|
||||
parser.seek_lf()?;
|
||||
if !host.is_empty() {
|
||||
if (1..=MAX_DOMAIN_LEN).contains(&host.len()) {
|
||||
return Ok(Request::Ehlo { host });
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +162,7 @@ impl Request<String> {
|
|||
if parser.stop_char != LF {
|
||||
let value = parser.string()?;
|
||||
parser.seek_lf()?;
|
||||
if !value.is_empty() {
|
||||
if (1..=MAX_ADDRESS_LEN).contains(&value.len()) {
|
||||
return Ok(Request::Expn { value });
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +189,7 @@ impl Request<String> {
|
|||
if parser.stop_char != LF {
|
||||
let host = parser.text()?;
|
||||
parser.seek_lf()?;
|
||||
if !host.is_empty() {
|
||||
if (1..=MAX_DOMAIN_LEN).contains(&host.len()) {
|
||||
return Ok(Request::Lhlo { host });
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +205,7 @@ impl Request<String> {
|
|||
if parser.stop_char != LF {
|
||||
let value = parser.string()?;
|
||||
parser.seek_lf()?;
|
||||
if !value.is_empty() {
|
||||
if (1..=MAX_ADDRESS_LEN).contains(&value.len()) {
|
||||
return Ok(Request::Vrfy { value });
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +298,7 @@ impl Request<String> {
|
|||
if parser.stop_char != LF {
|
||||
let host = parser.text()?;
|
||||
parser.seek_lf()?;
|
||||
if !host.is_empty() {
|
||||
if (1..=MAX_DOMAIN_LEN).contains(&host.len()) {
|
||||
return Ok(Request::Helo { host });
|
||||
}
|
||||
}
|
||||
|
@ -423,11 +449,13 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> {
|
|||
self.stop_char = ch;
|
||||
let value = value.into_string();
|
||||
let len = value.chars().count();
|
||||
return Ok(if len == 0 || len < 255 && at_count == 1 && lp_len > 0 {
|
||||
return Ok(
|
||||
if len == 0 || len <= MAX_ADDRESS_LEN && at_count == 1 && lp_len > 0 {
|
||||
value.into()
|
||||
} else {
|
||||
None
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
b'\r' => (),
|
||||
b':' if !in_quote && matches!(value.first(), Some(b'@')) => {
|
||||
|
@ -442,22 +470,26 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> {
|
|||
self.stop_char = b' ';
|
||||
let value = value.into_string();
|
||||
let len = value.chars().count();
|
||||
return Ok(if len == 0 || len < 255 && at_count == 1 && lp_len > 0 {
|
||||
return Ok(
|
||||
if len == 0 || len <= MAX_ADDRESS_LEN && at_count == 1 && lp_len > 0 {
|
||||
value.into()
|
||||
} else {
|
||||
None
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
b'\n' => {
|
||||
self.stop_char = b'\n';
|
||||
let value = value.into_string();
|
||||
let len = value.chars().count();
|
||||
return Ok(if len == 0 || len < 255 && at_count == 1 && lp_len > 0 {
|
||||
return Ok(
|
||||
if len == 0 || len <= MAX_ADDRESS_LEN && at_count == 1 && lp_len > 0 {
|
||||
value.into()
|
||||
} else {
|
||||
None
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
b'\"' if !in_quote || last_ch != b'\\' => {
|
||||
in_quote = !in_quote;
|
||||
|
@ -937,7 +969,9 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> {
|
|||
}
|
||||
AUTH_ if self.stop_char == b'=' => {
|
||||
let mailbox = self.xtext()?;
|
||||
if !mailbox.is_empty() && self.stop_char.is_ascii_whitespace() {
|
||||
if (1..=MAX_ADDRESS_LEN).contains(&mailbox.len())
|
||||
&& self.stop_char.is_ascii_whitespace()
|
||||
{
|
||||
params.auth = mailbox.into();
|
||||
} else {
|
||||
self.seek_lf()?;
|
||||
|
@ -1039,7 +1073,9 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> {
|
|||
return Err(Error::InvalidParameter { param: "ORCPT" });
|
||||
}
|
||||
let addr = self.xtext()?;
|
||||
if self.stop_char.is_ascii_whitespace() && (1..=500).contains(&addr.len()) {
|
||||
if self.stop_char.is_ascii_whitespace()
|
||||
&& (1..=MAX_ADDRESS_LEN).contains(&addr.len())
|
||||
{
|
||||
params.orcpt = addr.into();
|
||||
} else {
|
||||
self.seek_lf()?;
|
||||
|
@ -2081,12 +2117,11 @@ mod tests {
|
|||
let (request, parsed_request): (&str, Result<Request<String>, Error>) = item;
|
||||
|
||||
for extra in ["\n", "\r\n", " \n", " \r\n"] {
|
||||
let request = format!("{}{}", request, extra);
|
||||
let request = format!("{request}{extra}");
|
||||
assert_eq!(
|
||||
parsed_request,
|
||||
Request::parse(&mut request.as_bytes().iter()),
|
||||
"failed for {:?}",
|
||||
request
|
||||
"failed for {request:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
use std::slice::Iter;
|
||||
|
||||
use crate::{Error, Request};
|
||||
|
@ -247,7 +270,7 @@ mod tests {
|
|||
continue 'outer;
|
||||
}
|
||||
}
|
||||
panic!("Failed for {:?}", data);
|
||||
panic!("Failed for {data:?}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,7 +318,7 @@ mod tests {
|
|||
Err(Error::NeedsMoreData { .. }) => {
|
||||
break;
|
||||
}
|
||||
err => panic!("Unexpected error {:?}", err),
|
||||
err => panic!("Unexpected error {err:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
fmt::Display,
|
||||
io::{self, Write},
|
||||
|
@ -39,7 +62,7 @@ impl<T: Display> EhloResponse<T> {
|
|||
while mechanisms != 0 {
|
||||
let item = 1 << (63 - mechanisms.leading_zeros());
|
||||
mechanisms ^= item;
|
||||
write!(writer, " {}", (item as u64).to_mechanism())?;
|
||||
write!(writer, " {}", item.to_mechanism())?;
|
||||
}
|
||||
writer.write_all(b"\r\n")
|
||||
}
|
||||
|
@ -79,7 +102,7 @@ impl<T: Display> EhloResponse<T> {
|
|||
EXT_MTRK => write!(writer, "MTRK\r\n"),
|
||||
EXT_NO_SOLICITING => {
|
||||
if let Some(keywords) = &self.no_soliciting {
|
||||
write!(writer, "NO-SOLICITING {}\r\n", keywords)
|
||||
write!(writer, "NO-SOLICITING {keywords}\r\n")
|
||||
} else {
|
||||
write!(writer, "NO-SOLICITING\r\n")
|
||||
}
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{EhloResponse, Response};
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart SMTP protocol parser.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
use std::slice::Iter;
|
||||
|
||||
use crate::{request::parser::Rfc5321Parser, *};
|
||||
|
@ -480,8 +503,7 @@ mod tests {
|
|||
assert_eq!(
|
||||
parsed_response,
|
||||
EhloResponse::parse(&mut response.as_bytes().iter()),
|
||||
"failed for {:?}",
|
||||
response
|
||||
"failed for {response:?}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -624,8 +646,7 @@ mod tests {
|
|||
ResponseReceiver::default()
|
||||
.parse(&mut response.as_bytes().iter())
|
||||
.unwrap(),
|
||||
"failed for {:?}",
|
||||
response
|
||||
"failed for {response:?}",
|
||||
);
|
||||
all_responses.extend_from_slice(response.as_bytes());
|
||||
all_parsed_responses.push(parsed_response);
|
||||
|
@ -643,15 +664,14 @@ mod tests {
|
|||
assert_eq!(
|
||||
parsed_response.next(),
|
||||
Some(response),
|
||||
"chunk size {}",
|
||||
chunk_size
|
||||
"chunk size {chunk_size}",
|
||||
);
|
||||
receiver.reset();
|
||||
}
|
||||
Err(Error::NeedsMoreData { .. }) => {
|
||||
break;
|
||||
}
|
||||
err => panic!("Unexpected error {:?} for chunk size {}", err, chunk_size),
|
||||
err => panic!("Unexpected error {err:?} for chunk size {chunk_size}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue