Skip to content

Instantly share code, notes, and snippets.

@dckc
Created August 2, 2014 19:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dckc/1f7f6937483c7c34c579 to your computer and use it in GitHub Desktop.
Save dckc/1f7f6937483c7c34c579 to your computer and use it in GitHub Desktop.
closure lifetime issues
pub fn decode_id_string(buf: &[u8]) -> IoResult<ServerProtocol> {
debug!("decode_id_string(buf={})", buf);
if buf.len() != 32 {
return Err(IoError{ kind: InvalidInput, desc: "id string length must be 32", detail: None});
}
let pick_attr = |i: uint| {
let offset = i * 4;
let bytes = buf.slice(offset, offset + 4);
match from_utf8(buf.slice(offset, offset + 4)) {
Some(str) => Ok(str),
None => Err(bytes)
}
};
let check = |attr: AttrIndex, expected| {
match pick_attr(attr as uint) {
Ok(txt) if txt == expected => Ok(txt),
Ok(txt) => Err(IoError{ kind: InvalidInput, desc: "unsupported attribute",
detail: Some(format!("expected {} for {} but got {}",
expected, attr, txt)) }),
Err(bytes) => Err(IoError{ kind: InvalidInput, desc: "attribute not utf-8",
detail: Some(format!("attribute: {} is {}", attr, bytes)) })
}
};
try!(check(IDsig, "Rsrv"));
try!(check(Protocol, "QAP1"));
let version = pick_attr(ServerVersion as uint).unwrap_or("");
let attrs = range_inclusive(Opt4 as uint, Opt8 as uint).map(|ix| {
let offset = ix * 4;
let bt = |i| buf[offset + i];
let ch = |i| bt(i) as char;
let other = || AnyAttr({
let bytes = buf.slice(offset, offset + 4);
match from_utf8(bytes) {
Some(txt) => Ok(txt.to_string()),
None => Err((bt(0), bt(1), bt(2), bt(3)))
}
});
match (ch(0), ch(1)) {
('R', _) => match (ch(1).to_digit(10),
ch(2).to_digit(10),
ch(3).to_digit(10)) {
(Some(d1), Some(d2), Some(d3)) => RVersion(d1 as u8, d2 as u8, d3 as u8),
_ => other()
},
('A', 'R') => AuthorizationRequired(match (ch(2), ch(3)) {
('p', 't') => PlainText,
('u', 'c') => UnixCrypt,
('m', '5') => MD5,
(_, _) => AnyAuth(ch(2), ch(3))
}),
('K', _) => Key(bt(1), bt(2), bt(3)),
(_, _) => other()
}
}).collect();
Ok(QAP1(version.to_string(), attrs))
}
pub trait ReadIDString {
fn read_id_string(&mut self) -> IoResult<ServerProtocol>;
}
impl<R: Reader> ReadIDString for R {
fn read_id_string(&mut self) -> IoResult<ServerProtocol> {
let mut buf = [0u8, ..32];
try!(self.read_at_least(32, buf));
decode_id_string(buf)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment