Skip to content

Make it (somehow) possible to avoid needless allocations when serialising requests (needs GAT?) #711

@psychon

Description

@psychon

I just was looking at some code and wondered why we really need vec! here:

impl GetInputFocusRequest {
    /// Serialize this request into bytes for the provided connection
    pub fn serialize(self) -> BufWithFds<PiecewiseBuf<'static>> {
        let length_so_far = 0;
        let mut request0 = vec![
            GET_INPUT_FOCUS_REQUEST,
            0,
            0,
            0,
        ];
        let length_so_far = length_so_far + request0.len();
        assert_eq!(length_so_far % 4, 0);
        let length = u16::try_from(length_so_far / 4).unwrap_or(0);
        request0[2..4].copy_from_slice(&length.to_ne_bytes());
        (vec![request0.into()], vec![])
    }
}

All of this is static. It would e.g. possible to do something like this (however, no idea how to set the length field in a way that works for both big endian and little endian):

fn serialize(self) -> &'static [u8] {
    &[GET_INPUT_FOCUS_REQUEST, 0, 1, 0]
}

Of course, this return type is not compatible with everything else. Perhaps a Cow<'static, [u8]> could work?

Also: Of course, "just because" is not good enough, so: Would there be any actual benefit to doing this?

(The original code has two allocations. The one I am talking about above is for the "actual on-the-wire bytes". There is also the two vec!s in the last line. The first one could also be replaced with something static, but Cow<'static, [Cow<'static, [u8]]> seems a bit ugly. The second is actually free since there are no FDs and AFAIK an empty Vec does not allocate anything.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions