Move chartype into a separate module
authorRichard Whitehouse <github@richardwhiuk.com>
Mon, 22 Oct 2018 13:00:37 +0000 (09:00 -0400)
committerRichard Whitehouse <github@richardwhiuk.com>
Mon, 22 Oct 2018 13:00:37 +0000 (09:00 -0400)
src/codec.rs [deleted file]
src/codec/chartype.rs [new file with mode: 0644]
src/codec/mod.rs [new file with mode: 0644]

diff --git a/src/codec.rs b/src/codec.rs
deleted file mode 100644 (file)
index b1d298c..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-use bytes::BytesMut;
-use nom;
-use std;
-use std::io;
-use tokio_io::codec::{Decoder, Encoder};
-
-use parser::header;
-use parser::top_line;
-use types::{Header, Method, RequestLine, StatusLine, TopLine};
-
-const SPACE: u8 = b' ';
-const TAB: u8 = b'\t';
-const LF: u8 = b'\n';
-const CR: u8 = b'\r';
-
-impl Header {
-    fn parse(line: UnparsedLine) -> Option<(Header, UnparsedLine)> {
-        match header(line.as_bytes()) {
-            nom::IResult::Done(_, h) => Some((h, line.clone())),
-            result => {
-                warn!("Failed to parse header: {:?} - {:?}", line, result);
-                None
-            }
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-struct UnparsedLine {
-    value: BytesMut,
-}
-
-impl UnparsedLine {
-    fn new(value: BytesMut) -> UnparsedLine {
-        UnparsedLine { value: value }
-    }
-
-    fn add(&mut self, value: &BytesMut) {
-        self.value.extend_from_slice(value);
-    }
-
-    fn as_bytes(&self) -> &[u8] {
-        &self.value
-    }
-}
-
-pub struct SipCodec {
-    message: Option<PartialMessage>,
-    headers: Vec<UnparsedLine>,
-    top_line: Option<UnparsedLine>,
-    latest_header: Option<UnparsedLine>,
-}
-
-impl SipCodec {
-    pub fn new() -> SipCodec {
-        SipCodec {
-            message: None,
-            headers: Vec::new(),
-            top_line: None,
-            latest_header: None,
-        }
-    }
-
-    fn parse_message(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
-        loop {
-            trace!("Gathering headers from {:?}", std::str::from_utf8(&buf));
-
-            let mut done = false;
-            let mut total = 0;
-
-            {
-                let mut search: Box<Iterator<Item = &u8>> = Box::new(buf.iter());
-
-                while !done {
-                    trace!("Gathering CRLF");
-
-                    if let Some(cr) = search.position(|&b| b == CR) {
-                        trace!("Found CR at {}", cr);
-
-                        total += cr;
-
-                        let next = search.next();
-
-                        trace!("Got {:?} after CR", next);
-
-                        if let Some(&LF) = next {
-                            done = true;
-                        }
-                    } else {
-                        return Ok(None);
-                    }
-                }
-            }
-
-            // We've got a line terminating in \r\n.
-            let line = buf.split_to(total + 2);
-
-            trace!("Using line: {:?}", std::str::from_utf8(&line));
-
-            match (
-                &mut self.top_line,
-                chartype(line.first()),
-                &mut self.latest_header,
-            ) {
-                // Ignore empty top lines
-                (&mut None, CharType::Line, _) => {
-                    trace!("Ignoring empty top line");
-                }
-
-                // Top line beginnning with whitespace - ignore
-                (&mut None, CharType::Whitespace, _) => {
-                    trace!(
-                        "Got top line beginning with whitespace - ignore: {:?}",
-                        line
-                    );
-                }
-
-                // Top line with no headers! Discard.
-                (top_line @ &mut None, CharType::Other, _) => {
-                    trace!("Got new top line of request: {:?}", line);
-
-                    top_line.get_or_insert(UnparsedLine::new(line));
-                }
-
-                // Top line with no headers! Discard.
-                (top_line @ &mut Some(_), CharType::Line, &mut None) => {
-                    warn!("Got request with no headers - discarding");
-                    top_line.take();
-                }
-
-                // Whitespace wrapped req line
-                (&mut Some(ref mut top_line), CharType::Whitespace, &mut None) => {
-                    top_line.add(&line)
-                }
-
-                // Whitespace wrapped header
-                (&mut Some(_), CharType::Whitespace, &mut Some(ref mut latest_header)) => {
-                    latest_header.add(&line)
-                }
-
-                // First header
-                (&mut Some(_), CharType::Other, latest_header @ &mut None) => {
-                    latest_header.get_or_insert(UnparsedLine::new(line));
-                }
-
-                // New header
-                (&mut Some(_), CharType::Other, latest_header @ &mut Some(_)) => {
-                    self.headers.push(latest_header.take().unwrap());
-                    latest_header.get_or_insert(UnparsedLine::new(line));
-                }
-
-                // End of headers
-                (top_line @ &mut Some(_), CharType::Line, old_header @ &mut Some(_)) => {
-                    self.headers.push(old_header.take().unwrap());
-
-                    trace!("Got end of headers");
-
-                    if let Ok(new_message) =
-                        PartialMessage::new(top_line.take().unwrap(), &mut self.headers)
-                    {
-                        debug!("Got partial message: {:?}", new_message);
-
-                        self.headers.clear();
-
-                        let length = new_message.body_length();
-
-                        if length == 0 {
-                            if let Some(message) = Message::new(new_message) {
-                                debug!("Got message without body: {:?}", message);
-
-                                return Ok(Some(message));
-                            } else {
-                                debug!("Failed to parse message with no body!");
-                            }
-                        } else if length > buf.len() {
-                            self.message.get_or_insert(new_message);
-                            return Ok(None);
-                        } else {
-                            let body = buf.split_to(length);
-                            if let Some(message) = Message::new_with_body(new_message, body) {
-                                debug!("Got message with body: {:?}", message);
-
-                                return Ok(Some(message));
-                            } else {
-                                warn!("Failed to parse message with body!");
-                            }
-                        }
-                    } else {
-                        warn!("Failed to parse partial message!");
-
-                        // Message failed to parse
-                        top_line.take();
-                        self.headers.clear();
-                    }
-                }
-            }
-        }
-    }
-}
-
-#[derive(Debug)]
-struct PartialMessage {
-    headers: Vec<(Header, UnparsedLine)>,
-    top_line: UnparsedLine,
-}
-
-impl PartialMessage {
-    fn new(
-        top_line: UnparsedLine,
-        headers: &mut Vec<UnparsedLine>,
-    ) -> Result<PartialMessage, std::str::Utf8Error> {
-        Ok(PartialMessage {
-            top_line: top_line,
-            headers: headers
-                .drain(..)
-                .filter_map(|line| Header::parse(line))
-                .collect(),
-        })
-    }
-
-    fn body_length(&self) -> usize {
-        let body_length = 0;
-
-        body_length
-    }
-}
-
-#[derive(Debug)]
-pub enum Message {
-    Request(Request),
-    Response(Response),
-}
-
-#[derive(Debug)]
-pub struct Response {
-    status_line: (StatusLine, UnparsedLine),
-    headers: Vec<(Header, UnparsedLine)>,
-    body: Option<BytesMut>,
-}
-
-impl Response {
-    fn as_bytes(&self) -> &[u8] {
-        return self.status_line.1.as_bytes();
-    }
-}
-
-#[derive(Debug)]
-pub struct Request {
-    request_line: (RequestLine, UnparsedLine),
-    headers: Vec<(Header, UnparsedLine)>,
-    body: Option<BytesMut>,
-}
-
-impl Request {
-    fn as_bytes(&self) -> &[u8] {
-        return self.request_line.1.as_bytes();
-    }
-
-    pub fn method(&self) -> &Method {
-        &self.request_line.0.method
-    }
-}
-
-impl Message {
-    fn new(message: PartialMessage) -> Option<Message> {
-        Message::parse(message, None)
-    }
-
-    fn parse(message: PartialMessage, body: Option<BytesMut>) -> Option<Message> {
-        match top_line(message.top_line.as_bytes()) {
-            nom::IResult::Done(_, TopLine::RequestLine(r)) => Some(Message::Request(Request {
-                headers: message.headers,
-                request_line: (r, message.top_line.clone()),
-                body: body,
-            })),
-            nom::IResult::Done(_, TopLine::StatusLine(s)) => Some(Message::Response(Response {
-                headers: message.headers,
-                status_line: (s, message.top_line.clone()),
-                body: body,
-            })),
-            result => {
-                warn!("Failed to parse top line: {:?}", result);
-                None
-            }
-        }
-    }
-
-    fn new_with_body(message: PartialMessage, body: BytesMut) -> Option<Message> {
-        Message::parse(message, Some(body))
-    }
-
-    fn as_bytes<'a>(&'a self) -> &'a [u8] {
-        match self {
-            &Message::Request(ref r) => r.as_bytes(),
-            &Message::Response(ref r) => r.as_bytes(),
-        }
-    }
-}
-
-impl Decoder for SipCodec {
-    type Item = Message;
-    type Error = io::Error;
-
-    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
-        if let Some(_) = self.message {
-            trace!("Gathering body");
-
-            let length = self.message.iter().map(|m| m.body_length()).next().unwrap();
-
-            if length > buf.len() {
-                return Ok(None);
-            } else if let Some(message) =
-                Message::new_with_body(self.message.take().unwrap(), buf.split_to(length))
-            {
-                return Ok(Some(message));
-            } else {
-                warn!("Failed to parse message with no body!");
-            }
-        }
-
-        self.parse_message(buf)
-    }
-}
-
-impl Encoder for SipCodec {
-    type Item = Message;
-    type Error = io::Error;
-
-    fn encode(&mut self, msg: Message, buf: &mut BytesMut) -> io::Result<()> {
-        buf.extend(msg.as_bytes());
-        Ok(())
-    }
-}
-
-#[derive(PartialEq, Debug)]
-enum CharType {
-    Line,
-    Whitespace,
-    Other,
-}
-
-fn chartype(char: Option<&u8>) -> CharType {
-    match char {
-        None | Some(&LF) | Some(&CR) => CharType::Line,
-        Some(&SPACE) | Some(&TAB) => CharType::Whitespace,
-        Some(_) => CharType::Other,
-    }
-}
-
-#[cfg(test)]
-mod tests {
-
-    use super::*;
-
-    #[test]
-    fn test_chartype_none() {
-        assert_eq!(chartype(None), CharType::Line);
-    }
-
-    #[test]
-    fn test_chartype_cr() {
-        assert_eq!(chartype(Some(&LF)), CharType::Line);
-    }
-
-    #[test]
-    fn test_chartype_lf() {
-        assert_eq!(chartype(Some(&CR)), CharType::Line);
-    }
-
-    #[test]
-    fn test_chartype_space() {
-        assert_eq!(chartype(Some(&SPACE)), CharType::Whitespace);
-    }
-
-    #[test]
-    fn test_chartype_tab() {
-        assert_eq!(chartype(Some(&TAB)), CharType::Whitespace);
-    }
-
-    #[test]
-    fn test_chartype_alpha() {
-        const A: u8 = b'a';
-        assert_eq!(chartype(Some(&A)), CharType::Other);
-    }
-
-    #[test]
-    fn test_chartype_number() {
-        const ONE: u8 = b'1';
-        assert_eq!(chartype(Some(&ONE)), CharType::Other);
-    }
-}
diff --git a/src/codec/chartype.rs b/src/codec/chartype.rs
new file mode 100644 (file)
index 0000000..61953f8
--- /dev/null
@@ -0,0 +1,61 @@
+const SPACE: u8 = b' ';
+const TAB: u8 = b'\t';
+pub const LF: u8 = b'\n';
+pub const CR: u8 = b'\r';
+
+#[derive(PartialEq, Debug)]
+pub enum CharType {
+    Line,
+    Whitespace,
+    Other,
+}
+
+pub fn chartype(char: Option<&u8>) -> CharType {
+    match char {
+        None | Some(&LF) | Some(&CR) => CharType::Line,
+        Some(&SPACE) | Some(&TAB) => CharType::Whitespace,
+        Some(_) => CharType::Other,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_chartype_none() {
+        assert_eq!(chartype(None), CharType::Line);
+    }
+
+    #[test]
+    fn test_chartype_cr() {
+        assert_eq!(chartype(Some(&LF)), CharType::Line);
+    }
+
+    #[test]
+    fn test_chartype_lf() {
+        assert_eq!(chartype(Some(&CR)), CharType::Line);
+    }
+
+    #[test]
+    fn test_chartype_space() {
+        assert_eq!(chartype(Some(&SPACE)), CharType::Whitespace);
+    }
+
+    #[test]
+    fn test_chartype_tab() {
+        assert_eq!(chartype(Some(&TAB)), CharType::Whitespace);
+    }
+
+    #[test]
+    fn test_chartype_alpha() {
+        const A: u8 = b'a';
+        assert_eq!(chartype(Some(&A)), CharType::Other);
+    }
+
+    #[test]
+    fn test_chartype_number() {
+        const ONE: u8 = b'1';
+        assert_eq!(chartype(Some(&ONE)), CharType::Other);
+    }
+}
diff --git a/src/codec/mod.rs b/src/codec/mod.rs
new file mode 100644 (file)
index 0000000..63804bb
--- /dev/null
@@ -0,0 +1,331 @@
+use bytes::BytesMut;
+use nom;
+use std;
+use std::io;
+use tokio_io::codec::{Decoder, Encoder};
+
+mod chartype;
+
+use self::chartype::{chartype, CharType, CR, LF};
+use parser::header;
+use parser::top_line;
+use types::{Header, Method, RequestLine, StatusLine, TopLine};
+
+impl Header {
+    fn parse(line: UnparsedLine) -> Option<(Header, UnparsedLine)> {
+        match header(line.as_bytes()) {
+            nom::IResult::Done(_, h) => Some((h, line.clone())),
+            result => {
+                warn!("Failed to parse header: {:?} - {:?}", line, result);
+                None
+            }
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+struct UnparsedLine {
+    value: BytesMut,
+}
+
+impl UnparsedLine {
+    fn new(value: BytesMut) -> UnparsedLine {
+        UnparsedLine { value: value }
+    }
+
+    fn add(&mut self, value: &BytesMut) {
+        self.value.extend_from_slice(value);
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        &self.value
+    }
+}
+
+pub struct SipCodec {
+    message: Option<PartialMessage>,
+    headers: Vec<UnparsedLine>,
+    top_line: Option<UnparsedLine>,
+    latest_header: Option<UnparsedLine>,
+}
+
+impl SipCodec {
+    pub fn new() -> SipCodec {
+        SipCodec {
+            message: None,
+            headers: Vec::new(),
+            top_line: None,
+            latest_header: None,
+        }
+    }
+
+    fn parse_message(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
+        loop {
+            trace!("Gathering headers from {:?}", std::str::from_utf8(&buf));
+
+            let mut done = false;
+            let mut total = 0;
+
+            {
+                let mut search: Box<Iterator<Item = &u8>> = Box::new(buf.iter());
+
+                while !done {
+                    trace!("Gathering CRLF");
+
+                    if let Some(cr) = search.position(|&b| b == CR) {
+                        trace!("Found CR at {}", cr);
+
+                        total += cr;
+
+                        let next = search.next();
+
+                        trace!("Got {:?} after CR", next);
+
+                        if let Some(&LF) = next {
+                            done = true;
+                        }
+                    } else {
+                        return Ok(None);
+                    }
+                }
+            }
+
+            // We've got a line terminating in \r\n.
+            let line = buf.split_to(total + 2);
+
+            trace!("Using line: {:?}", std::str::from_utf8(&line));
+
+            match (
+                &mut self.top_line,
+                chartype(line.first()),
+                &mut self.latest_header,
+            ) {
+                // Ignore empty top lines
+                (&mut None, CharType::Line, _) => {
+                    trace!("Ignoring empty top line");
+                }
+
+                // Top line beginnning with whitespace - ignore
+                (&mut None, CharType::Whitespace, _) => {
+                    trace!(
+                        "Got top line beginning with whitespace - ignore: {:?}",
+                        line
+                    );
+                }
+
+                // Top line with no headers! Discard.
+                (top_line @ &mut None, CharType::Other, _) => {
+                    trace!("Got new top line of request: {:?}", line);
+
+                    top_line.get_or_insert(UnparsedLine::new(line));
+                }
+
+                // Top line with no headers! Discard.
+                (top_line @ &mut Some(_), CharType::Line, &mut None) => {
+                    warn!("Got request with no headers - discarding");
+                    top_line.take();
+                }
+
+                // Whitespace wrapped req line
+                (&mut Some(ref mut top_line), CharType::Whitespace, &mut None) => {
+                    top_line.add(&line)
+                }
+
+                // Whitespace wrapped header
+                (&mut Some(_), CharType::Whitespace, &mut Some(ref mut latest_header)) => {
+                    latest_header.add(&line)
+                }
+
+                // First header
+                (&mut Some(_), CharType::Other, latest_header @ &mut None) => {
+                    latest_header.get_or_insert(UnparsedLine::new(line));
+                }
+
+                // New header
+                (&mut Some(_), CharType::Other, latest_header @ &mut Some(_)) => {
+                    self.headers.push(latest_header.take().unwrap());
+                    latest_header.get_or_insert(UnparsedLine::new(line));
+                }
+
+                // End of headers
+                (top_line @ &mut Some(_), CharType::Line, old_header @ &mut Some(_)) => {
+                    self.headers.push(old_header.take().unwrap());
+
+                    trace!("Got end of headers");
+
+                    if let Ok(new_message) =
+                        PartialMessage::new(top_line.take().unwrap(), &mut self.headers)
+                    {
+                        debug!("Got partial message: {:?}", new_message);
+
+                        self.headers.clear();
+
+                        let length = new_message.body_length();
+
+                        if length == 0 {
+                            if let Some(message) = Message::new(new_message) {
+                                debug!("Got message without body: {:?}", message);
+
+                                return Ok(Some(message));
+                            } else {
+                                debug!("Failed to parse message with no body!");
+                            }
+                        } else if length > buf.len() {
+                            self.message.get_or_insert(new_message);
+                            return Ok(None);
+                        } else {
+                            let body = buf.split_to(length);
+                            if let Some(message) = Message::new_with_body(new_message, body) {
+                                debug!("Got message with body: {:?}", message);
+
+                                return Ok(Some(message));
+                            } else {
+                                warn!("Failed to parse message with body!");
+                            }
+                        }
+                    } else {
+                        warn!("Failed to parse partial message!");
+
+                        // Message failed to parse
+                        top_line.take();
+                        self.headers.clear();
+                    }
+                }
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+struct PartialMessage {
+    headers: Vec<(Header, UnparsedLine)>,
+    top_line: UnparsedLine,
+}
+
+impl PartialMessage {
+    fn new(
+        top_line: UnparsedLine,
+        headers: &mut Vec<UnparsedLine>,
+    ) -> Result<PartialMessage, std::str::Utf8Error> {
+        Ok(PartialMessage {
+            top_line: top_line,
+            headers: headers
+                .drain(..)
+                .filter_map(|line| Header::parse(line))
+                .collect(),
+        })
+    }
+
+    fn body_length(&self) -> usize {
+        let body_length = 0;
+
+        body_length
+    }
+}
+
+#[derive(Debug)]
+pub enum Message {
+    Request(Request),
+    Response(Response),
+}
+
+#[derive(Debug)]
+pub struct Response {
+    status_line: (StatusLine, UnparsedLine),
+    headers: Vec<(Header, UnparsedLine)>,
+    body: Option<BytesMut>,
+}
+
+impl Response {
+    fn as_bytes(&self) -> &[u8] {
+        return self.status_line.1.as_bytes();
+    }
+}
+
+#[derive(Debug)]
+pub struct Request {
+    request_line: (RequestLine, UnparsedLine),
+    headers: Vec<(Header, UnparsedLine)>,
+    body: Option<BytesMut>,
+}
+
+impl Request {
+    fn as_bytes(&self) -> &[u8] {
+        return self.request_line.1.as_bytes();
+    }
+
+    pub fn method(&self) -> &Method {
+        &self.request_line.0.method
+    }
+}
+
+impl Message {
+    fn new(message: PartialMessage) -> Option<Message> {
+        Message::parse(message, None)
+    }
+
+    fn parse(message: PartialMessage, body: Option<BytesMut>) -> Option<Message> {
+        match top_line(message.top_line.as_bytes()) {
+            nom::IResult::Done(_, TopLine::RequestLine(r)) => Some(Message::Request(Request {
+                headers: message.headers,
+                request_line: (r, message.top_line.clone()),
+                body: body,
+            })),
+            nom::IResult::Done(_, TopLine::StatusLine(s)) => Some(Message::Response(Response {
+                headers: message.headers,
+                status_line: (s, message.top_line.clone()),
+                body: body,
+            })),
+            result => {
+                warn!("Failed to parse top line: {:?}", result);
+                None
+            }
+        }
+    }
+
+    fn new_with_body(message: PartialMessage, body: BytesMut) -> Option<Message> {
+        Message::parse(message, Some(body))
+    }
+
+    fn as_bytes<'a>(&'a self) -> &'a [u8] {
+        match self {
+            &Message::Request(ref r) => r.as_bytes(),
+            &Message::Response(ref r) => r.as_bytes(),
+        }
+    }
+}
+
+impl Decoder for SipCodec {
+    type Item = Message;
+    type Error = io::Error;
+
+    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
+        if let Some(_) = self.message {
+            trace!("Gathering body");
+
+            let length = self.message.iter().map(|m| m.body_length()).next().unwrap();
+
+            if length > buf.len() {
+                return Ok(None);
+            } else if let Some(message) =
+                Message::new_with_body(self.message.take().unwrap(), buf.split_to(length))
+            {
+                return Ok(Some(message));
+            } else {
+                warn!("Failed to parse message with no body!");
+            }
+        }
+
+        self.parse_message(buf)
+    }
+}
+
+impl Encoder for SipCodec {
+    type Item = Message;
+    type Error = io::Error;
+
+    fn encode(&mut self, msg: Message, buf: &mut BytesMut) -> io::Result<()> {
+        buf.extend(msg.as_bytes());
+        Ok(())
+    }
+}