changed CodecUdp::decode to return Self::In instead of Option<Self::In>

This commit is contained in:
Rick Richardson
2016-11-22 08:29:02 -08:00
parent b12d32ce1c
commit 2cb600bd19
2 changed files with 20 additions and 20 deletions
+16 -9
View File
@@ -25,20 +25,27 @@ use std::str;
/// so that it can respond back. /// so that it can respond back.
/// In the real world, one would probably /// In the real world, one would probably
/// want an associative of remote peers to their state /// want an associative of remote peers to their state
///
/// Note that this takes a pretty draconian stance by returning
/// an error if it can't find a newline in the datagram it received
pub struct LineCodec { pub struct LineCodec {
addr : Option<SocketAddr> addr : Option<SocketAddr>
} }
impl CodecUdp for LineCodec { impl CodecUdp for LineCodec {
type In = Vec<u8>; type In = Vec<Vec<u8>>;
type Out = Vec<u8>; type Out = Vec<u8>;
fn decode(&mut self, addr : &SocketAddr, buf: &[u8]) -> Result<Option<Self::In>, io::Error> { fn decode(&mut self, addr : &SocketAddr, buf: &[u8]) -> Result<Self::In, io::Error> {
trace!("decoding {} - {}", str::from_utf8(buf).unwrap(), addr); trace!("decoding {} - {}", str::from_utf8(buf).unwrap(), addr);
self.addr = Some(*addr); self.addr = Some(*addr);
match buf.iter().position(|&b| b == b'\n') { let res : Vec<Vec<u8>> = buf.split(|c| *c == b'\n').map(|s| s.into()).collect();
Some(i) => Ok(Some(buf[.. i].into())), if res.len() > 0 {
None => Ok(None), Ok(res)
}
else {
Err(io::Error::new(io::ErrorKind::Other,
"failed to find newline in datagram"))
} }
} }
@@ -83,8 +90,8 @@ fn main() {
//Note that we pass srvsink into fold, so that it can be //Note that we pass srvsink into fold, so that it can be
//supplied to every iteration. The reason for this is //supplied to every iteration. The reason for this is
//sink.send moves itself into `send` and then returns itself //sink.send moves itself into `send` and then returns itself
let srvloop = srvstream.fold(srvsink, move |sink, buf| { let srvloop = srvstream.fold(srvsink, move |sink, lines| {
println!("{}", str::from_utf8(buf.as_slice()).unwrap()); println!("{}", str::from_utf8(lines[0].as_slice()).unwrap());
sink.send(b"PONG".to_vec()) sink.send(b"PONG".to_vec())
}).map(|_| ()); }).map(|_| ());
@@ -92,8 +99,8 @@ fn main() {
let (clistream, clisink) = client.framed(clicodec).split(); let (clistream, clisink) = client.framed(clicodec).split();
//And another infinite iteration //And another infinite iteration
let cliloop = clistream.fold(clisink, move |sink, buf| { let cliloop = clistream.fold(clisink, move |sink, lines| {
println!("{}", str::from_utf8(buf.as_slice()).unwrap()); println!("{}", str::from_utf8(lines[0].as_slice()).unwrap());
sink.send(b"PING".to_vec()) sink.send(b"PING".to_vec())
}).map(|_| ()); }).map(|_| ());
+4 -11
View File
@@ -45,17 +45,11 @@ pub trait CodecUdp {
/// decode, as the next poll_read that occurs will write the next datagram /// decode, as the next poll_read that occurs will write the next datagram
/// into the buffer, without regard for what is already there. /// into the buffer, without regard for what is already there.
/// ///
/// If the bytes look valid, but a frame isn't fully available yet, then
/// `Ok(None)` is returned. This indicates to the `Framed` instance that
/// it needs to read some more bytes before calling this method again.
/// In such a case, it is decode's responsibility to copy the data
/// into their own internal buffer for future use.
///
/// Finally, if the bytes in the buffer are malformed then an error is /// Finally, if the bytes in the buffer are malformed then an error is
/// returned indicating why. This informs `Framed` that the stream is now /// returned indicating why. This informs `Framed` that the stream is now
/// corrupt and should be terminated. /// corrupt and should be terminated.
/// ///
fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> Result<Option<Self::In>, io::Error>; fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> Result<Self::In, io::Error>;
} }
/// A unified `Stream` and `Sink` interface to an underlying `Io` object, using /// A unified `Stream` and `Sink` interface to an underlying `Io` object, using
@@ -82,10 +76,9 @@ impl<C : CodecUdp> Stream for FramedUdp<C> {
Ok((n, addr)) => { Ok((n, addr)) => {
trace!("read {} bytes", n); trace!("read {} bytes", n);
trace!("attempting to decode a frame"); trace!("attempting to decode a frame");
if let Some(frame) = try!(self.codec.decode(&addr, & self.rd[.. n])) { let frame = try!(self.codec.decode(&addr, & self.rd[.. n]));
trace!("frame decoded from buffer"); trace!("frame decoded from buffer");
return Ok(Async::Ready(Some(frame))); return Ok(Async::Ready(Some(frame)));
}
} }
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
return Ok(Async::NotReady) return Ok(Async::NotReady)