mido

thinking so ur dog doesnt have to

I like making little games with friends :] Mostly shit posting and vibing.


something O(n^2) this way comes

#[derive(Default)]
struct StreamPartBundler {
    bundles: HashMap<Range<u16>, Vec<StreamPart>>,
}

impl StreamPartBundler {
    /// Consume part of a chunked message and if it happens
    /// to complete as a result of this final piece of the puzzle then
    /// please assemble it and output the final Bytes payload.
    fn process_part(&mut self, sequence_number: &u16, part: StreamPart) -> Option<Bytes> {
        if part.part_offset == 0 && part.part_total == 1 {
            // this is a special case: a simple <=MTU send! we can
            // emit it right away.
            return if part.payload.len() > 0 {
                Some(part.payload)
            } else {
                // If the payload is empty for some reason
                // let's reduce confusion and not emit it. This might
                // be the case for "just ACKs" for example.
                None
            };
        }

        let range_start = sequence_number - part.part_offset;
        let range_end = range_start + part.part_total;
        let range_key = range_start..range_end;

        if let Some(pile) = self.bundles.get_mut(&range_key) {
            let parts_total = part.part_total as usize;
            pile.push(part);
            match pile.len() {
                i if i == parts_total => {
                    // it looks like the parts are complete, it's time to sort and
                    // assemble!
                    // NOTE: this is probably gonna be pretty slow and shitty!!! we probably want to
                    // sort on insert since those will be smaller discrete moments
                    pile.sort_by(|a, b| a.part_offset.partial_cmp(&b.part_offset).unwrap())

                    //TODO: when i return, assemble da boi
                }
                i if i > parts_total => {
                    panic!("This should be impossible bro!!")
                }
                _ => {} // noop
            }
        } else {
            self.bundles.insert(range_key.clone(), vec![part]);
            // todo: spot check that we dont have more than 32 of these in progress at any
            // point in time, that SHOULDNT BE POSSIBLE with how the ack masks work, unless
            // we start interleaving fragmented messages in the stream for some god-forsaken
            // reason in the future.
        }

        None
    }
}

You must log in to comment.

in reply to @mido's post:

Absolutely, yes! This was a super rough sketch last night before I went to bed, there’s even a few additional concerns it’s not even beginning to tackle yet. I’ll probably just do an ordered insert of some kind once I finalize my core behavior and do a cleanup pass. I’m hoping to avoid preallocating right now because the current structure of the surrounding protocol could allow for expansion attacks, so lots of kinda obvious approaches to avoid sorting when it’s time to render the final payload and this is just my sloppy late night doodling