benc0de 0.2.0

A super-faster bencode parser
Documentation
#[derive(Debug, PartialEq)]
pub(super) enum BenToken {
    ByteString(usize, usize), // begin, end
    Number(isize),
    Dict(usize),
    List(usize),
    None
}

impl BenToken {
    pub(super) fn len(&self) -> usize {
        return match self {
            Self::ByteString(_, _) => 1,
            Self::Dict(len) | Self::List(len) => *len,
            Self::Number(_) => 1,
            Self::None => 1
        };
    }
}

#[derive(PartialEq)]
pub(super) enum BenTokenIndex {
    Dict(usize),
    List(usize)
}

pub(super) fn tokenize(bytes: &[u8], tokens: &mut Vec<BenToken>, indices: &mut Vec<BenTokenIndex>) -> bool {
    let mut offset = 0usize;
    let mut b;

    while offset < bytes.len() {
        b = bytes[offset];

        match b {
            0x30..=0x39 => {
                let mut len = b.wrapping_sub(0x30) as usize;

                offset += 1;
                while offset < bytes.len() {
                    b = bytes[offset];
                    offset += 1;

                    if b != b':' {
                        len = len.wrapping_mul(10)
                                 .wrapping_add(b.wrapping_sub(0x30) as usize);
                    } else {
                        break;
                    }
                }

                if offset + len < bytes.len() {
                    tokens.push(BenToken::ByteString(offset, offset+len));
                    offset += len;
                    continue;
                } else {
                    return false;
                }
            },
            b'e' => {
                match indices.pop() {
                    Some(BenTokenIndex::Dict(idx)) => {
                        tokens[idx] = BenToken::Dict(tokens.len() - idx);
                    },
                    Some(BenTokenIndex::List(idx)) => {
                        tokens[idx] = BenToken::List(tokens.len() - idx);
                    },
                    None => return false
                }
            },
            b'd' => {
                indices.push(BenTokenIndex::Dict(tokens.len()));
                tokens.push(BenToken::None);
            },
            b'l' => {
                indices.push(BenTokenIndex::List(tokens.len()));
                tokens.push(BenToken::None);
            },
            b'i' => {
                offset += 1;
                // Check sign.
                if offset < bytes.len() {
                    b = bytes[offset];
                    // Negative number
                    if b == b'-' {
                        offset += 1;

                        if offset >= bytes.len() {
                            return false;
                        }

                        b = bytes[offset];
                        let mut num = -(b.wrapping_sub(0x30) as isize);

                        loop {
                            offset += 1;
                            if offset >= bytes.len() {
                                return false;
                            }

                            b = bytes[offset];
                            
                            if b != b'e' {
                                num = num.wrapping_mul(10).wrapping_sub(b.wrapping_sub(0x30) as isize);
                            } else {
                                break;
                            }
                        }

                        tokens.push(BenToken::Number(num));
                    // Positive number
                    } else {
                        let mut num = b.wrapping_sub(0x30) as isize;

                        loop {
                            offset += 1;
                            if offset >= bytes.len() {
                                return false;
                            }

                            b = bytes[offset];

                            if b != b'e' {
                                num = num.wrapping_mul(10).wrapping_add(b.wrapping_sub(0x30) as isize);
                            } else {
                                break;
                            }
                        }

                        tokens.push(BenToken::Number(num));
                    }
                }
            },
            _ => return false
        }

        if indices.len() == 0 {
            return true;
        }

        offset += 1;
    }

    return false;
}