This commit is contained in:
Michael Zhang 2021-08-08 14:31:18 -05:00
parent c1e770e050
commit a22a2ee35c
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
9 changed files with 45 additions and 13 deletions

View file

@ -1,2 +1,5 @@
fmt: fmt:
cargo +nightly fmt --all cargo +nightly fmt --all
greenmail-test:
cargo run -p imap --bin greenmail-test

View file

@ -1,4 +1,2 @@
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {}
}

View file

@ -1,7 +1,7 @@
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use crate::proto::command::{Command, CommandLogin};
use crate::client::inner::Inner; use crate::client::inner::Inner;
use crate::proto::command::{Command, CommandLogin};
pub trait Client: AsyncRead + AsyncWrite + Unpin + Sync + Send + 'static {} pub trait Client: AsyncRead + AsyncWrite + Unpin + Sync + Send + 'static {}

View file

@ -1,5 +1,5 @@
use anyhow::Result; use anyhow::Result;
use futures::future::FutureExt; use futures::{future::FutureExt, stream::StreamExt};
use tokio::{ use tokio::{
io::{split, AsyncRead, AsyncWrite, ReadHalf, WriteHalf}, io::{split, AsyncRead, AsyncWrite, ReadHalf, WriteHalf},
sync::oneshot, sync::oneshot,
@ -71,12 +71,18 @@ where
{ {
// set up framed communication // set up framed communication
let codec = ImapCodec::default(); let codec = ImapCodec::default();
let framed = FramedRead::new(stream, codec); let mut framed = FramedRead::new(stream, codec);
let exit = exit.fuse(); let exit = exit.fuse();
pin_mut!(exit); pin_mut!(exit);
loop { loop {
let next = framed.next().fuse();
pin_mut!(next);
select! { select! {
msg = next => {
println!("hellosu {:?}", msg);
}
_ = exit => break, _ = exit => break,
} }
} }

View file

@ -1,3 +1,19 @@
pub mod auth; pub mod auth;
pub mod inner; pub mod inner;
pub mod upgrade; pub mod upgrade;
use anyhow::Result;
#[derive(Debug, Builder)]
#[builder(build_fn(skip))]
pub struct Config {
// (required for TLS)
hostname: String,
tls: bool,
}
impl ConfigBuilder {
pub async fn build() -> Result<Client> { todo!() }
}
pub struct Client;

View file

@ -1,6 +1,6 @@
use std::io; use std::io;
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use tokio_util::codec::{Decoder, Encoder}; use tokio_util::codec::{Decoder, Encoder};
@ -15,7 +15,7 @@ pub struct ImapCodec {
} }
impl<'a> Decoder for ImapCodec { impl<'a> Decoder for ImapCodec {
type Item = ResponseData; type Item = OwnedResponse;
type Error = io::Error; type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> { fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
if self.decode_need_message_bytes > buf.len() { if self.decode_need_message_bytes > buf.len() {
@ -55,7 +55,7 @@ impl<'a> Decoder for ImapCodec {
impl<'a> Encoder<&'a Command<'a>> for ImapCodec { impl<'a> Encoder<&'a Command<'a>> for ImapCodec {
type Error = io::Error; type Error = io::Error;
fn encode(&mut self, msg: &Command, dst: &mut BytesMut) -> Result<(), io::Error> { fn encode(&mut self, _msg: &Command, _dst: &mut BytesMut) -> Result<(), io::Error> {
todo!() todo!()
// dst.put(&*msg.0); // dst.put(&*msg.0);
// dst.put_u8(b' '); // dst.put_u8(b' ');
@ -66,7 +66,7 @@ impl<'a> Encoder<&'a Command<'a>> for ImapCodec {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ResponseData { pub struct OwnedResponse {
raw: Bytes, raw: Bytes,
// This reference is really scoped to the lifetime of the `raw` // This reference is really scoped to the lifetime of the `raw`
// member, but unfortunately Rust does not allow that yet. It // member, but unfortunately Rust does not allow that yet. It
@ -79,7 +79,7 @@ pub struct ResponseData {
response: Response<'static>, response: Response<'static>,
} }
impl ResponseData { impl OwnedResponse {
pub fn request_id(&self) -> Option<&Tag> { pub fn request_id(&self) -> Option<&Tag> {
match self.response { match self.response {
Response::Done(ResponseDone { ref tag, .. }) => Some(tag), Response::Done(ResponseDone { ref tag, .. }) => Some(tag),

View file

@ -40,4 +40,4 @@ pub enum Command<'a> {
pub struct CommandLogin<'a> { pub struct CommandLogin<'a> {
pub username: &'a str, pub username: &'a str,
pub password: &'a str, pub password: &'a str,
} }

View file

@ -13,4 +13,4 @@ pub mod rfc2234;
pub mod rfc3501; pub mod rfc3501;
#[cfg(feature = "rfc2177-idle")] #[cfg(feature = "rfc2177-idle")]
pub mod rfc2177; pub mod rfc2177;

View file

@ -4,6 +4,7 @@ use std::borrow::Cow;
pub struct Tag(pub String); pub struct Tag(pub String);
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive]
pub enum Response<'a> { pub enum Response<'a> {
Done(ResponseDone<'a>), Done(ResponseDone<'a>),
} }
@ -16,6 +17,13 @@ pub struct ResponseDone<'a> {
pub info: Option<Cow<'a, str>>, pub info: Option<Cow<'a, str>>,
} }
#[derive(Debug)]
pub struct Condition<'a> {
pub status: Status,
pub code: Option<ResponseCode<'a>>,
pub text: String,
}
#[derive(Debug)] #[derive(Debug)]
pub enum Status { pub enum Status {
Ok, Ok,
@ -26,6 +34,7 @@ pub enum Status {
} }
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive]
pub enum ResponseCode<'a> { pub enum ResponseCode<'a> {
Alert, Alert,
Capabilities(Vec<Capability<'a>>), Capabilities(Vec<Capability<'a>>),