///|
/// Parse a positive STAT reply as message count and total octets.
pub fn Reply::stat(self : Reply) -> (Int, Int) raise PopError {
if !self.ok {
raise Invalid("negative server reply")
}
let fields = self.message.split(" ").filter(x => !x.is_empty()).collect()
if fields.length() != 2 {
raise Invalid("STAT requires count and octets")
}
let count = @string.parse_int(fields[0]) catch {
_ => raise Invalid("STAT count")
}
let octets = @string.parse_int(fields[1]) catch {
_ => raise Invalid("STAT octets")
}
if count < 0 || octets < 0 {
raise Invalid("negative STAT value")
}
(count, octets)
}
///|
/// Parse the unstuffed multiline LIST body; reject duplicate message numbers.
pub fn Reply::listing(self : Reply) -> Array[(Int, Int)] raise PopError {
if !self.ok {
raise Invalid("negative server reply")
}
let body = @utf8.decode(self.body) catch {
_ => raise Invalid("invalid LIST text")
}
let out = []
let seen : Map[Int, Bool] = Map([])
for line in body.split("\r\n") {
if line.is_empty() {
continue
}
let f = line.split(" ").filter(x => !x.is_empty()).collect()
if f.length() != 2 {
raise Invalid("LIST row")
}
let id = @string.parse_int(f[0]) catch { _ => raise Invalid("LIST id") }
let size = @string.parse_int(f[1]) catch {
_ => raise Invalid("LIST octets")
}
if id < 1 || size < 0 || seen.contains(id) {
raise Invalid("LIST invalid or duplicate id")
}
seen[id] = true
out.push((id, size))
}
out
}