This seems like it's doing a little more work than necessary, but it's a little tough to follow. Awhile back I actually kinda implemented this (but not as well as you did with conditions and whatnot), and that implementation may help out reducing the amount of shifting/checking/conditionals:

https://github.com/alexcrichton/rust/blob/5af700c677034499827de9682097ae375fe69cb7/src/libstd/io/comm.rs#L65