waynest 0.0.26

Core wayland stuff
Documentation
use std::os::fd::{IntoRawFd, OwnedFd, RawFd};

use bytes::{BufMut, Bytes, BytesMut};

use super::{Fixed, NewId, ObjectId};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PayloadBuilder {
    payload: BytesMut,
    fds: Vec<RawFd>,
}

impl Default for PayloadBuilder {
    fn default() -> Self {
        Self::new()
    }
}

impl PayloadBuilder {
    pub fn new() -> Self {
        Self {
            payload: BytesMut::new(),
            fds: Vec::new(),
        }
    }

    pub fn put_int(mut self, int: i32) -> Self {
        self.payload.reserve(4);
        self.payload.put_i32_ne(int);

        self
    }

    pub fn put_uint(mut self, uint: u32) -> Self {
        self.payload.reserve(4);
        self.payload.put_u32_ne(uint);

        self
    }

    pub fn put_fixed(mut self, fixed: Fixed) -> Self {
        self.payload.reserve(4);
        self.payload.put_u32_ne(fixed.into_raw());

        self
    }

    pub fn put_string<T: AsRef<str>>(mut self, string: Option<T>) -> Self {
        if let Some(string) = string {
            let string = string.as_ref();
            let total_len = 5 + string.len();
            let mut padding = 0;

            if total_len % 4 != 0 {
                padding = 4 - (total_len % 4);
            }

            self.payload.reserve(total_len + padding);
            self.payload.put_u32_ne((string.len() + 1) as u32);
            self.payload.put_slice(string.as_bytes());
            self.payload.put_u8(b'\0');

            for _ in 0..padding {
                self.payload.put_u8(0);
            }

            return self;
        }

        self.put_uint(0)
    }

    pub fn put_object(self, object: Option<ObjectId>) -> Self {
        if let Some(id) = object {
            return self.put_uint(id.as_raw());
        }

        self.put_uint(0)
    }

    pub fn put_new_id(self, new_id: NewId) -> Self {
        self.put_string(Some(new_id.interface))
            .put_uint(new_id.version)
            .put_object(Some(new_id.object_id))
    }

    pub fn put_array<T: AsRef<[u8]>>(mut self, array: T) -> Self {
        let array = array.as_ref();
        let total_len = 4 + array.len();
        let mut padding = 0;

        if total_len % 4 != 0 {
            padding = 4 - (total_len % 4);
        }

        self.payload.reserve(total_len + padding);
        self.payload.put_u32_ne(array.len() as u32);
        self.payload.put_slice(array);

        for _ in 0..padding {
            self.payload.put_u8(0);
        }

        self
    }

    pub fn put_fd<Fd: Into<OwnedFd>>(mut self, fd: Fd) -> Self {
        self.fds.push(fd.into().into_raw_fd());

        self
    }

    pub fn build(self) -> (Bytes, Vec<RawFd>) {
        (self.payload.freeze(), self.fds)
    }
}