1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use ::std::io::{Read, Write, Result};
use ::std::io::{Error, ErrorKind};
const DIGIT_LIMIT: usize = 64;
pub trait ReadNetstring {
fn read_netstring(&mut self) -> Result<String>;
}
pub trait WriteNetstring {
fn write_netstring<S: AsRef<str>>(&mut self, value: S) -> Result<()>;
}
impl<R: Read> ReadNetstring for R {
fn read_netstring(&mut self) -> Result<String> {
let ln = try!(read_length(self));
let mut data = vec![0u8;ln];
let mut offset = 0usize;
let mut done = false;
while !done {
let r = try!(self.read(data[offset..].as_mut()));
offset = offset + r;
if r == 0 || offset == ln {
done = true;
}
}
let mut t = vec![0u8].into_boxed_slice();
try!(self.read(t[..].as_mut()));
if t[0] != b","[0] {
return Err(Error::new(ErrorKind::InvalidData, "Expected `,` delimiter."));
}
match String::from_utf8(data) {
Ok(s) => Ok(s),
Err(err) => Err(Error::new(ErrorKind::InvalidData, err)),
}
}
}
impl<W: Write> WriteNetstring for W {
fn write_netstring<S: AsRef<str>>(&mut self, value: S) -> Result<()> {
let value = value.as_ref();
let s = format!("{}:{},", value.len(), value);
try!(self.write(s.as_bytes()));
Ok(())
}
}
fn read_length<R: Read>(r: &mut R) -> Result<usize> {
let mut t = [0u8; DIGIT_LIMIT];
let mut current = 0usize;
let mut done = false;
while !done {
let r = try!(r.read(t[current..current+1].as_mut()));
if r == 0 {
return Err(Error::new(ErrorKind::ConnectionAborted, "Connection closed by target."));
}
if t[current] == 0x3A {
done = true;
} else {
current += 1;
}
}
let s = match String::from_utf8(t[..current].to_vec()) {
Ok(s) => s,
Err(err) => return Err(Error::new(ErrorKind::InvalidData, err)),
};
let ln = match s.parse::<u64>() {
Ok(x) => x,
Err(err) => return Err(Error::new(ErrorKind::InvalidData, err)),
};
Ok(ln as usize)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_read() {
let mut raw = "5:hello,".as_bytes();
let x = raw.read_netstring().unwrap();
assert_eq!("hello", x);
}
#[test]
fn basic_write() {
let mut raw = vec![];
let _ = raw.write_netstring("hello").unwrap();
assert_eq!(raw, b"5:hello,");
}
#[test]
#[should_panic(expected="Expected `,` delimiter.")]
fn invalid_delimiter() {
let mut raw = "5:hello?".as_bytes();
raw.read_netstring().unwrap();
}
#[test]
#[should_panic(expected="Expected `,` delimiter.")]
fn longer() {
let mut raw = "10:hello,".as_bytes();
raw.read_netstring().unwrap();
}
#[test]
#[should_panic(expected="Expected `,` delimiter.")]
fn shorter() {
let mut raw = "2:hello,".as_bytes();
raw.read_netstring().unwrap();
}
}