Minor improvements.
This commit is contained in:
parent
81fdbe7151
commit
bb6437dec4
7 changed files with 54 additions and 60 deletions
|
@ -217,7 +217,7 @@ pub struct EhloResponse<T: Display> {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Response<T: Display> {
|
||||
pub code: [u8; 3],
|
||||
pub code: u16,
|
||||
pub esc: [u8; 3],
|
||||
pub message: T,
|
||||
}
|
||||
|
@ -251,15 +251,14 @@ pub enum Error {
|
|||
SyntaxError { syntax: &'static str },
|
||||
InvalidParameter { param: &'static str },
|
||||
UnsupportedParameter { param: String },
|
||||
LineTooLong,
|
||||
ResponseTooLong,
|
||||
InvalidResponse { code: [u8; 3] },
|
||||
InvalidResponse { code: u16 },
|
||||
}
|
||||
|
||||
pub(crate) const LF: u8 = b'\n';
|
||||
pub(crate) const SP: u8 = b' ';
|
||||
|
||||
pub(crate) trait IntoString: Sized {
|
||||
pub trait IntoString: Sized {
|
||||
fn into_string(self) -> String;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ pub(crate) const ETRN: u64 =
|
|||
(b'E' as u64) | (b'T' as u64) << 8 | (b'R' as u64) << 16 | (b'N' as u64) << 24;
|
||||
pub(crate) const ATRN: u64 =
|
||||
(b'A' as u64) | (b'T' as u64) << 8 | (b'R' as u64) << 16 | (b'N' as u64) << 24;
|
||||
pub(crate) const AUTH: u64 =
|
||||
pub const AUTH: u64 =
|
||||
(b'A' as u64) | (b'U' as u64) << 8 | (b'T' as u64) << 16 | (b'H' as u64) << 24;
|
||||
pub(crate) const BURL: u64 =
|
||||
(b'B' as u64) | (b'U' as u64) << 8 | (b'R' as u64) << 16 | (b'L' as u64) << 24;
|
||||
|
|
|
@ -289,9 +289,9 @@ impl Request<String> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Rfc5321Parser<'x, 'y> {
|
||||
pub struct Rfc5321Parser<'x, 'y> {
|
||||
bytes: &'x mut Iter<'y, u8>,
|
||||
pub(crate) stop_char: u8,
|
||||
pub stop_char: u8,
|
||||
pub bytes_left: usize,
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1046,7 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> {
|
|||
Ok(params)
|
||||
}
|
||||
|
||||
pub(crate) fn mechanism(&mut self) -> Result<Option<u64>, Error> {
|
||||
pub fn mechanism(&mut self) -> Result<Option<u64>, Error> {
|
||||
let mut trailing_chars = [0u8; 8];
|
||||
let mut pos = 0;
|
||||
let mechanism = self.hashed_value_long()?;
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct DummyDataReceiver {
|
|||
prev_last_ch: u8,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DummyLineReceiver {}
|
||||
|
||||
impl RequestReceiver {
|
||||
|
@ -43,7 +44,7 @@ impl RequestReceiver {
|
|||
if bytes_left < MAX_LINE_LENGTH {
|
||||
self.buf = buf[buf.len() - bytes_left..].to_vec();
|
||||
} else {
|
||||
return Err(Error::LineTooLong);
|
||||
return Err(Error::ResponseTooLong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +59,7 @@ impl RequestReceiver {
|
|||
return result;
|
||||
} else if self.buf.len() == MAX_LINE_LENGTH {
|
||||
self.buf.clear();
|
||||
return Err(Error::LineTooLong);
|
||||
return Err(Error::ResponseTooLong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ impl<T: Display> EhloResponse<T> {
|
|||
let mut capabilities = self.capabilities;
|
||||
|
||||
while capabilities != 0 {
|
||||
let capability = 63 - capabilities.leading_zeros();
|
||||
let capability = 31 - capabilities.leading_zeros();
|
||||
capabilities ^= 1 << capability;
|
||||
|
||||
writer.write_all(b"250")?;
|
||||
|
@ -109,14 +109,8 @@ impl<T: Display> Response<T> {
|
|||
pub fn write(&self, mut writer: impl Write) -> io::Result<()> {
|
||||
write!(
|
||||
writer,
|
||||
"{}{}{} {}.{}.{} {}\r\n",
|
||||
self.code[0],
|
||||
self.code[1],
|
||||
self.code[2],
|
||||
self.esc[0],
|
||||
self.esc[1],
|
||||
self.esc[2],
|
||||
self.message
|
||||
"{} {}.{}.{} {}\r\n",
|
||||
self.code, self.esc[0], self.esc[1], self.esc[2], self.message
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -176,17 +170,17 @@ impl BitToString for u64 {
|
|||
}
|
||||
|
||||
impl<T: Display> Response<T> {
|
||||
pub fn new(c0: u8, c1: u8, c2: u8, e0: u8, e1: u8, e2: u8, message: T) -> Self {
|
||||
pub fn new(code: u16, e0: u8, e1: u8, e2: u8, message: T) -> Self {
|
||||
Self {
|
||||
code: [c0, c1, c2],
|
||||
code,
|
||||
esc: [e0, e1, e2],
|
||||
message,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the reply's numeric status.
|
||||
pub fn code(&self) -> &[u8] {
|
||||
&self.code
|
||||
pub fn code(&self) -> u16 {
|
||||
self.code
|
||||
}
|
||||
|
||||
/// Returns the message included in the reply.
|
||||
|
@ -196,18 +190,18 @@ impl<T: Display> Response<T> {
|
|||
|
||||
/// Returns the status severity (first digit of the status code).
|
||||
pub fn severity(&self) -> Severity {
|
||||
match self.code[0] {
|
||||
2 => Severity::PositiveCompletion,
|
||||
3 => Severity::PositiveIntermediate,
|
||||
4 => Severity::TransientNegativeCompletion,
|
||||
5 => Severity::PermanentNegativeCompletion,
|
||||
match self.code {
|
||||
200..=299 => Severity::PositiveCompletion,
|
||||
300..=399 => Severity::PositiveIntermediate,
|
||||
400..=499 => Severity::TransientNegativeCompletion,
|
||||
500..=599 => Severity::PermanentNegativeCompletion,
|
||||
_ => Severity::Invalid,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the status category (second digit of the status code).
|
||||
pub fn category(&self) -> Category {
|
||||
match self.code[1] {
|
||||
match (self.code / 10) % 10 {
|
||||
0 => Category::Syntax,
|
||||
1 => Category::Information,
|
||||
2 => Category::Connections,
|
||||
|
@ -219,8 +213,8 @@ impl<T: Display> Response<T> {
|
|||
}
|
||||
|
||||
/// Returns the status details (third digit of the status code).
|
||||
pub fn details(&self) -> u8 {
|
||||
self.code[2]
|
||||
pub fn details(&self) -> u16 {
|
||||
self.code % 10
|
||||
}
|
||||
|
||||
/// Returns `true` if the reply is a positive completion.
|
||||
|
|
|
@ -221,14 +221,8 @@ impl<T: Display> Display for Response<T> {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Code: {}{}{}, Enhanced code: {}.{}.{}, Message: {}",
|
||||
self.code[0],
|
||||
self.code[1],
|
||||
self.code[2],
|
||||
self.esc[0],
|
||||
self.esc[1],
|
||||
self.esc[2],
|
||||
self.message,
|
||||
"Code: {}, Enhanced code: {}.{}.{}, Message: {}",
|
||||
self.code, self.esc[0], self.esc[1], self.esc[2], self.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,17 @@ pub const MAX_REPONSE_LENGTH: usize = 4096;
|
|||
#[derive(Default)]
|
||||
pub struct ResponseReceiver {
|
||||
buf: Vec<u8>,
|
||||
code: [u8; 6],
|
||||
code: u16,
|
||||
esc: [u8; 3],
|
||||
is_last: bool,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl ResponseReceiver {
|
||||
pub fn from_code(code: [u8; 3]) -> Self {
|
||||
pub fn from_code(code: u16) -> Self {
|
||||
Self {
|
||||
code: [code[0], code[1], code[2], 0, 0, 0],
|
||||
code,
|
||||
esc: [0, 0, 0],
|
||||
pos: 3,
|
||||
is_last: false,
|
||||
buf: Vec::new(),
|
||||
|
@ -30,7 +32,10 @@ impl ResponseReceiver {
|
|||
0..=2 => {
|
||||
if ch.is_ascii_digit() {
|
||||
if self.buf.is_empty() {
|
||||
self.code[self.pos] = ch - b'0';
|
||||
self.code = self
|
||||
.code
|
||||
.saturating_mul(10)
|
||||
.saturating_add((ch - b'0') as u16);
|
||||
}
|
||||
self.pos += 1;
|
||||
} else {
|
||||
|
@ -62,11 +67,11 @@ impl ResponseReceiver {
|
|||
4 | 5 | 6 => match ch {
|
||||
b'0'..=b'9' => {
|
||||
if self.buf.is_empty() {
|
||||
let code = &mut self.code[self.pos - 1];
|
||||
let code = &mut self.esc[self.pos - 4];
|
||||
*code = code.saturating_mul(10).saturating_add(ch - b'0');
|
||||
}
|
||||
}
|
||||
b'.' if self.pos < 6 && self.code[self.pos - 1] > 0 => {
|
||||
b'.' if self.pos < 6 && self.esc[self.pos - 4] > 0 => {
|
||||
self.pos += 1;
|
||||
}
|
||||
_ => {
|
||||
|
@ -91,8 +96,8 @@ impl ResponseReceiver {
|
|||
if ch == b'\n' {
|
||||
if self.is_last {
|
||||
return Ok(Response {
|
||||
code: [self.code[0], self.code[1], self.code[2]],
|
||||
esc: [self.code[3], self.code[4], self.code[5]],
|
||||
code: self.code,
|
||||
esc: self.esc,
|
||||
message: std::mem::take(&mut self.buf).into_string(),
|
||||
});
|
||||
} else {
|
||||
|
@ -107,7 +112,8 @@ impl ResponseReceiver {
|
|||
|
||||
pub fn reset(&mut self) {
|
||||
self.is_last = false;
|
||||
self.code.fill(0);
|
||||
self.code = 0;
|
||||
self.esc.fill(0);
|
||||
self.pos = 0;
|
||||
}
|
||||
}
|
||||
|
@ -116,15 +122,15 @@ impl EhloResponse<String> {
|
|||
pub fn parse(bytes: &mut Iter<'_, u8>) -> Result<Self, Error> {
|
||||
let mut parser = Rfc5321Parser::new(bytes);
|
||||
let mut response = EhloResponse::default();
|
||||
let mut code = [0u8; 3];
|
||||
let mut eol = false;
|
||||
let mut is_first_line = true;
|
||||
|
||||
while !eol {
|
||||
for code in code.iter_mut() {
|
||||
let mut code: u16 = 0;
|
||||
for _ in 0..3 {
|
||||
match parser.read_char()? {
|
||||
ch @ b'0'..=b'9' => {
|
||||
*code = ch - b'0';
|
||||
code = code.saturating_mul(10).saturating_add((ch - b'0') as u16);
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::SyntaxError {
|
||||
|
@ -134,7 +140,7 @@ impl EhloResponse<String> {
|
|||
}
|
||||
}
|
||||
|
||||
if code[0] != 2 || code[1] != 5 || code[2] != 0 {
|
||||
if code != 250 {
|
||||
return Err(Error::InvalidResponse { code });
|
||||
}
|
||||
|
||||
|
@ -143,7 +149,7 @@ impl EhloResponse<String> {
|
|||
eol = true;
|
||||
}
|
||||
b'-' => (),
|
||||
b'\n' if code[0] < 6 => {
|
||||
b'\n' if code < 600 => {
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
|
@ -416,7 +422,7 @@ mod tests {
|
|||
),
|
||||
(
|
||||
concat!("523-Massive\n", "523-Error\n", "523 Message\n"),
|
||||
Err(Error::UnknownCommand),
|
||||
Err(Error::InvalidResponse { code: 523 }),
|
||||
),
|
||||
] {
|
||||
let (response, parsed_response): (&str, Result<EhloResponse<String>, Error>) = item;
|
||||
|
@ -446,7 +452,7 @@ mod tests {
|
|||
(
|
||||
"250 2.1.1 Originator <ned@ymir.claremont.edu> ok\n",
|
||||
Response {
|
||||
code: [2, 5, 0],
|
||||
code: 250,
|
||||
esc: [2, 1, 1],
|
||||
message: "Originator <ned@ymir.claremont.edu> ok".to_string(),
|
||||
},
|
||||
|
@ -458,7 +464,7 @@ mod tests {
|
|||
"551 5.7.1 Select another host to act as your forwarder\n"
|
||||
),
|
||||
Response {
|
||||
code: [5, 5, 1],
|
||||
code: 551,
|
||||
esc: [5, 7, 1],
|
||||
message: concat!(
|
||||
"Forwarding to remote hosts disabled\n",
|
||||
|
@ -474,7 +480,7 @@ mod tests {
|
|||
"550 user has moved with no forwarding address\n"
|
||||
),
|
||||
Response {
|
||||
code: [5, 5, 0],
|
||||
code: 550,
|
||||
esc: [0, 0, 0],
|
||||
message: "mailbox unavailable\nuser has moved with no forwarding address"
|
||||
.to_string(),
|
||||
|
@ -487,7 +493,7 @@ mod tests {
|
|||
"550 user has moved with no forwarding address\n"
|
||||
),
|
||||
Response {
|
||||
code: [5, 5, 0],
|
||||
code: 550,
|
||||
esc: [0, 0, 0],
|
||||
message: "mailbox unavailable\nuser has moved with no forwarding address"
|
||||
.to_string(),
|
||||
|
@ -508,7 +514,7 @@ mod tests {
|
|||
"432 6.8.9 World!\n"
|
||||
),
|
||||
Response {
|
||||
code: [4, 3, 2],
|
||||
code: 432,
|
||||
esc: [6, 8, 9],
|
||||
message: "\nHello\n\n,\n\n\n\n\n\nWorld!".to_string(),
|
||||
},
|
||||
|
@ -517,7 +523,7 @@ mod tests {
|
|||
(
|
||||
concat!("250-Missing space\n", "250\n", "250 Ignore this"),
|
||||
Response {
|
||||
code: [2, 5, 0],
|
||||
code: 250,
|
||||
esc: [0, 0, 0],
|
||||
message: "Missing space\n".to_string(),
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue