Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern crate bytes;
- extern crate tokio;
- extern crate tokio_codec;
- use bytes::{BufMut, BytesMut};
- use std::io::{Error, ErrorKind};
- use std::str;
- use tokio::prelude::*;
- use tokio_codec::{Decoder, Encoder};
- pub enum MailItem {
- SingleLine(String),
- MultiLine(Vec<u8>)
- }
- pub struct MailSocketCodec {
- uses_dot_stuff: bool,
- /// The index of where we should search for CRLF in the input stream.
- next_index: usize,
- multiline_size: usize
- }
- /// To implement:
- /// receiveLine
- /// receiveNBytes
- /// receiveUntilDot
- /// startTLS
- /// connect
- /// close
- impl Encoder for MailSocketCodec {
- type Item = MailItem;
- type Error = Error;
- fn encode(&mut self, item: MailItem,
- buf: &mut BytesMut) -> Result<(), Error> {
- match item {
- MailItem::SingleLine(line) => {
- assert!(!line.contains("\r") && !line.contains("\n"),
- "Cannot send CR or LF values across a single line");
- buf.reserve(line.len() + 2);
- buf.put(line);
- buf.put("\r\n");
- Ok(())
- },
- MailItem::MultiLine(bytes) => {
- match self.uses_dot_stuff {
- true => {
- panic!("Dot stuff not yet implemented");
- },
- false => {
- buf.put(bytes);
- Ok(())
- }
- }
- }
- }
- }
- }
- fn make_str(s: &[u8]) -> Result<String, Error> {
- str::from_utf8(s)
- .map(|s| s.to_string())
- .map_err(|_| Error::new(ErrorKind::InvalidData, "Not UTF-8"))
- }
- impl Decoder for MailSocketCodec {
- type Item = MailItem;
- type Error = Error;
- fn decode(&mut self,
- buf: &mut BytesMut) -> Result<Option<MailItem>, Error> {
- match (self.multiline_size, self.uses_dot_stuff) {
- (0, _) => {
- // We're parsing in single-line mode.
- let offset = buf[self.next_index..].windows(2).position(|t| t == b"\r\n");
- if let Some(count) = offset {
- let count = self.next_index + count;
- // Take the full string, sans CRLF, into the line
- let line = buf.split_to(count);
- // Drop off the CRLF from the buffer.
- buf.split_to(2);
- // Reset our search point for the next CRLF.
- self.next_index = 0;
- // Finally, return the line we saved.
- make_str(&line).map(|val| Some(MailItem::SingleLine(val)))
- } else {
- // Note that we don't need to scan this portion of the array
- // anymore...
- self.next_index = buf.len();
- // ... unless the very last byte was a CR.
- if buf.len() >= 1 && buf[buf.len() - 1] == b'\r' {
- self.next_index -= 1;
- }
- Ok(None)
- }
- },
- (_, true) => {
- panic!("Dot stuffing not implemented");
- },
- (count, false) => {
- panic!("Exact count not implemented");
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement