use std::io;
use std::str;
use bytes::BytesMut;
use tokio_io::codec::{Encoder, Decoder};
pub struct DbgpClientCodec;
impl Decoder for DbgpClientCodec {
type Item = String; type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
if let Some(len_pos) = buf.iter().position(|&b| b == b'\n') {
if let Some(msg_pos) = buf.iter().skip(len_pos+1).position(|&b| b == b'\n') {
let length = buf.split_to(len_pos);
buf.split_to(1);
let message = buf.split_to(msg_pos);
buf.split_to(1);
match str::from_utf8(&message) {
Ok(s) => Ok(Some(s.to_string())),
Err(_) => Err(io::Error::new(io::ErrorKind::Other,
"invalid UTF-8")),
}
} else {
Ok(None)
}
} else {
Ok(None)
}
}
}
impl Encoder for DbgpClientCodec {
type Item = String;
type Error = io::Error;
fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
buf.extend(msg.as_bytes());
buf.extend(b"\n");
Ok(())
}
}
#[cfg(test)]
mod tests {
use codec::DbgpClientCodec;
use bytes::{BytesMut, BufMut};
use tokio_io::codec::{Encoder, Decoder};
#[test]
fn codec_decode_correct_packet() {
let mut codec = DbgpClientCodec;
let mut packet = BytesMut::from("4\nalcs\n");
let d = codec.decode(&mut packet);
assert_eq!(d.unwrap(), Some("alcs".to_string()));
}
#[test]
fn codec_decode_incomplete_packet() {
let mut codec = DbgpClientCodec;
let mut packet = BytesMut::from("4\nalcn");
let d = codec.decode(&mut packet);
assert_eq!(d.unwrap(), None);
}
#[test]
fn codec_decode_incomplete_packet_length() {
let mut codec = DbgpClientCodec;
let mut packet = BytesMut::from("4");
let d = codec.decode(&mut packet);
assert_eq!(d.unwrap(), None);
}
#[test]
#[ignore] fn codec_decode_wrong_length() {
let mut codec = DbgpClientCodec;
let mut packet = BytesMut::from("2\nalcn\n");
let d = codec.decode(&mut packet);
assert_eq!(d.unwrap(), None);
}
#[test]
fn codec_encode_packet() {
let mut codec = DbgpClientCodec;
let command = "command -a 10 -- aoysckuasjhkadhad";
let mut dest_buf = BytesMut::with_capacity(command.len());
codec.encode(command.to_owned().clone(), &mut dest_buf);
assert_eq!(dest_buf, BytesMut::from(format!("{}\n", command.clone())));
}
}