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