1 #![allow(deprecated)]
2 
3 use bytes::{BufMut, BytesMut};
4 use codec::{Decoder, Encoder};
5 use std::{io, str};
6 
7 /// A simple `Codec` implementation that splits up data into lines.
8 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
9 #[deprecated(since = "0.1.7", note = "Moved to tokio-codec")]
10 pub struct LinesCodec {
11     // Stored index of the next index to examine for a `\n` character.
12     // This is used to optimize searching.
13     // For example, if `decode` was called with `abc`, it would hold `3`,
14     // because that is the next index to examine.
15     // The next time `decode` is called with `abcde\n`, the method will
16     // only look at `de\n` before returning.
17     next_index: usize,
18 }
19 
20 impl LinesCodec {
21     /// Returns a `LinesCodec` for splitting up data into lines.
new() -> LinesCodec22     pub fn new() -> LinesCodec {
23         LinesCodec { next_index: 0 }
24     }
25 }
26 
utf8(buf: &[u8]) -> Result<&str, io::Error>27 fn utf8(buf: &[u8]) -> Result<&str, io::Error> {
28     str::from_utf8(buf)
29         .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Unable to decode input as UTF8"))
30 }
31 
without_carriage_return(s: &[u8]) -> &[u8]32 fn without_carriage_return(s: &[u8]) -> &[u8] {
33     if let Some(&b'\r') = s.last() {
34         &s[..s.len() - 1]
35     } else {
36         s
37     }
38 }
39 
40 impl Decoder for LinesCodec {
41     type Item = String;
42     type Error = io::Error;
43 
decode(&mut self, buf: &mut BytesMut) -> Result<Option<String>, io::Error>44     fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<String>, io::Error> {
45         if let Some(newline_offset) = buf[self.next_index..].iter().position(|b| *b == b'\n') {
46             let newline_index = newline_offset + self.next_index;
47             let line = buf.split_to(newline_index + 1);
48             let line = &line[..line.len() - 1];
49             let line = without_carriage_return(line);
50             let line = utf8(line)?;
51             self.next_index = 0;
52             Ok(Some(line.to_string()))
53         } else {
54             self.next_index = buf.len();
55             Ok(None)
56         }
57     }
58 
decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<String>, io::Error>59     fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<String>, io::Error> {
60         Ok(match self.decode(buf)? {
61             Some(frame) => Some(frame),
62             None => {
63                 // No terminating newline - return remaining data, if any
64                 if buf.is_empty() || buf == &b"\r"[..] {
65                     None
66                 } else {
67                     let line = buf.take();
68                     let line = without_carriage_return(&line);
69                     let line = utf8(line)?;
70                     self.next_index = 0;
71                     Some(line.to_string())
72                 }
73             }
74         })
75     }
76 }
77 
78 impl Encoder for LinesCodec {
79     type Item = String;
80     type Error = io::Error;
81 
encode(&mut self, line: String, buf: &mut BytesMut) -> Result<(), io::Error>82     fn encode(&mut self, line: String, buf: &mut BytesMut) -> Result<(), io::Error> {
83         buf.reserve(line.len() + 1);
84         buf.put(line);
85         buf.put_u8(b'\n');
86         Ok(())
87     }
88 }
89