P3KI/bendy

Support decoding an initial bencode structure and retrieving the remaining bytes

jwodder opened this issue · 2 comments

BEP 9 (the protocol for resolving magnet URIs) defines a data packet that consists of a bencoded dictionary followed by arbitrary data (actually a slice of a torrent's info dict), and I would like to parse such a packet using bendy. The best way I've figured out to do this so far is to create a Decoder, call next_object(), retrieve the DictDecoder, iterate through & massage the dict's fields, call DictDecoder::into_raw() after handling all fields, get the length of the raw dict, and use that length as an offset to slice the original payload. This is rather unwieldy, and I believe this could be simplified by just giving Decoder a remaining(self) -> &'ser [u8] method for retrieving all remaining bytes of the payload after doing next_object() + FromBencode::decode_bencode_object().

I'm also trying to implement this exact feature, would be great if this could be supported by bendy

I'm doing a workaround. info_begin is the length of your payload - the length of the metadata. It is still using Bendy, we just split the buffer at the right spot and decode both sides, assuming both of them implements FromBencode.

pub struct Info {
    // .....
}
pub struct Metadata {
    pub msg_type: u8,
    pub piece: u32,
    pub total_size: u32,
}

impl Metadata {
    /// Tries to extract Info from the given buffer, which is the payload of the extended metadata "data" message.
    pub fn extract(mut buf: Vec<u8>, info_begin: usize) -> Result<(Self, Info), error::Error> {
        let info_buf: Vec<u8> = buf.drain(info_begin..).collect();

        let info = Info::from_bencode(&info_buf).unwrap();
        let metadata = Metadata::from_bencode(&buf).unwrap();

        Ok((metadata, info))
    }
}