// This source file is generated automatically from res.xml

use crate::base::{self, BaseError, BaseEvent, GeEvent, Raw, Reply, WiredIn, WiredOut, Xid};
use crate::ext;
use crate::ffi::base::*;
use crate::ffi::ext::*;
use crate::lat1_str::{Lat1Str, Lat1String, Lat1StrF};
use crate::xproto;
use crate::xproto::PropEl;

use bitflags::bitflags;
use libc::{self, iovec};
use std::convert::TryInto;
use std::hash::{Hash, Hasher};
use std::os::unix::io::RawFd;

/// The official identifier for the `Res` extension.
pub const XNAME: &str = "X-Resource";
/// The major version of the `Res` extension.
pub const MAJOR_VERSION: u32 = 1;
/// The minor version of the `Res` extension.
pub const MINOR_VERSION: u32 = 2;
/// The version string of the `Res` extension.
pub const VERSION_STRING: &str = "1.2";

pub(crate) static mut FFI_EXT: xcb_extension_t = xcb_extension_t {
    name: "X-Resource\0".as_ptr() as *const _,
    global_id: 0,
};

/// Prefetch server runtime info data of the `Res` extension.
pub fn prefetch_extension_data(conn: &base::Connection) {
    #[cfg(feature = "dl")]
    base::xcb_get_conn_funcs!(conn, xcb_prefetch_extension_data);
    unsafe {
        xcb_prefetch_extension_data(conn.get_raw_conn(), std::ptr::addr_of_mut!(FFI_EXT));
    }
}

/// Fetch server runtime info data of the `Res` extension.
///
/// Might be non-blocking if [prefetch_extension_data] was called before.
/// This function is of seldom use as the extensions are initialized by the
/// [Connection](crate::Connection) constructor.
pub fn get_extension_data(conn: &base::Connection) -> std::option::Option<ext::ExtensionData> {
    #[cfg(feature = "dl")]
    base::xcb_get_conn_funcs!(conn, xcb_get_extension_data);
    unsafe {
        let reply = xcb_get_extension_data(conn.get_raw_conn(), std::ptr::addr_of_mut!(FFI_EXT));
        assert!(!reply.is_null(), "Could not fetch Res extension data");
        let reply = xproto::QueryExtensionReply::from_raw(reply);
        if !reply.present() {
            std::mem::forget(reply);
            return None;
        }
        let res = ext::ExtensionData{
            ext: ext::Extension::Res,
            major_opcode: reply.major_opcode(),
            first_event: reply.first_event(),
            first_error: reply.first_error(),
        };
        std::mem::forget(reply);
        Some(res)
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct Client {
    pub resource_base: u32,
    pub resource_mask: u32,
}

#[test]
fn test_sizeof_client() {
    assert_eq!(std::mem::size_of::<Client>(), 8);
}

impl base::WiredOut for Client {
    fn wire_len(&self) -> usize { 8 }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        let me = unsafe {
            std::slice::from_raw_parts(self as *const Client as _, 8)
        };
        (&mut wire_buf[..me.len()]).copy_from_slice(me);
        8
    }
}

impl base::WiredIn for Client {
    type Params = ();
    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize { 8 }
    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        *offset += 8;
        *(ptr as *const Client)
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct Type {
    pub resource_type: xproto::Atom,
    pub count: u32,
}

#[test]
fn test_sizeof_type() {
    assert_eq!(std::mem::size_of::<Type>(), 8);
}

impl base::WiredOut for Type {
    fn wire_len(&self) -> usize { 8 }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        let me = unsafe {
            std::slice::from_raw_parts(self as *const Type as _, 8)
        };
        (&mut wire_buf[..me.len()]).copy_from_slice(me);
        8
    }
}

impl base::WiredIn for Type {
    type Params = ();
    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize { 8 }
    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        *offset += 8;
        *(ptr as *const Type)
    }
}

bitflags! {
    pub struct ClientIdMask: u32 {
        const CLIENT_XID = 0x00000001;
        const LOCAL_CLIENT_PID = 0x00000002;
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct ClientIdSpec {
    pub client: u32,
    pub mask: ClientIdMask,
}

#[test]
fn test_sizeof_client_id_spec() {
    assert_eq!(std::mem::size_of::<ClientIdSpec>(), 8);
}

impl base::WiredOut for ClientIdSpec {
    fn wire_len(&self) -> usize { 8 }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        let me = unsafe {
            std::slice::from_raw_parts(self as *const ClientIdSpec as _, 8)
        };
        (&mut wire_buf[..me.len()]).copy_from_slice(me);
        8
    }
}

impl base::WiredIn for ClientIdSpec {
    type Params = ();
    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize { 8 }
    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        *offset += 8;
        *(ptr as *const ClientIdSpec)
    }
}

pub struct ClientIdValue {
    data: [u8],
}

#[allow(unused_parens)]
impl ClientIdValue {
    pub(crate) unsafe fn from_data<D: AsRef<[u8]> + ?Sized>(data: &D) -> &ClientIdValue {
        debug_assert_eq!(data.as_ref().len(), <&ClientIdValue as base::WiredIn>::compute_wire_len(data.as_ref().as_ptr(), ()));
        &*(data.as_ref() as *const [u8] as *const ClientIdValue)
    }

    fn wire_ptr(&self) -> *const u8 { self.data.as_ptr() }

    pub fn spec(&self) -> ClientIdSpec {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const ClientIdSpec;
            ptr.read_unaligned()
        }
    }

    fn length(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn value(&self) -> &[u32] {
        unsafe {
            let offset = 12usize;
            let len = ((self.length() as usize) / 4usize);
            let ptr = self.wire_ptr().add(offset) as *const u32;
            std::slice::from_raw_parts(ptr, len)
        }
    }
}

impl base::WiredOut for ClientIdValue {
    fn wire_len(&self) -> usize { self.data.len() }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        (&mut wire_buf[..self.data.len()]).copy_from_slice(&self.data);
        self.data.len()
    }
}

impl base::WiredIn for &ClientIdValue {
    type Params = ();

    unsafe fn compute_wire_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // spec
        sz += 8usize;
        // length
        let length = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // value
        sz += (((length as usize) / 4usize) * 4usize);
        sz
    }
    unsafe fn unserialize(ptr: *const u8, params: (), offset: &mut usize) -> Self {
        let sz = Self::compute_wire_len(ptr, params);
        *offset += sz;
        let data = std::slice::from_raw_parts(ptr, sz);
        ClientIdValue::from_data(data)
    }
}

#[derive(Clone)]
pub struct ClientIdValueBuf {
    data: Vec<u8>,
}

impl ClientIdValueBuf {
    pub(crate) unsafe fn from_data(data: Vec<u8>) -> ClientIdValueBuf {
        debug_assert_eq!(<&ClientIdValue>::compute_wire_len(data.as_ptr(), ()), data.len());
        ClientIdValueBuf { data }
    }

    /// Construct a new [ClientIdValueBuf].
    #[allow(unused_assignments, unused_unsafe)]
    pub fn new(
        spec: ClientIdSpec,
        length: u32,
        value: &[u32],
    ) -> ClientIdValueBuf {
            unsafe {
            let mut wire_sz = 0usize;
            wire_sz += 8; // spec
            wire_sz += 4; // length
            wire_sz += value.iter().map(|el| el.wire_len()).sum::<usize>();
            let mut wire_buf = vec![0u8; wire_sz];
            let mut wire_off = 0usize;

            wire_off += spec.serialize(&mut wire_buf[wire_off .. ]);
            wire_off += length.serialize(&mut wire_buf[wire_off .. ]);
            for el in value {
                wire_off += el.serialize(&mut wire_buf[wire_off ..]);
            }

            ClientIdValueBuf { data: wire_buf }
        }
    }
}

impl base::WiredIn for ClientIdValueBuf {
    type Params = ();
    unsafe fn compute_wire_len(ptr: *const u8, params: ()) -> usize {
    <&ClientIdValue>::compute_wire_len(ptr, params)
}
    unsafe fn unserialize(ptr: *const u8, params: (), offset: &mut usize) -> Self {
        let sz = Self::compute_wire_len(ptr, params);
        *offset += sz;
        let data = std::slice::from_raw_parts(ptr, sz);
        ClientIdValueBuf::from_data(data.to_vec())
    }
}

impl std::ops::Deref for ClientIdValueBuf {
    type Target = ClientIdValue;
    fn deref(&self) -> &Self::Target {
        unsafe { ClientIdValue::from_data(&self.data) }
    }
}

impl std::borrow::Borrow<ClientIdValue> for ClientIdValueBuf {
    fn borrow(&self) -> &ClientIdValue {
        unsafe { ClientIdValue::from_data(&self.data) }
    }
}

impl std::borrow::ToOwned for ClientIdValue {
    type Owned = ClientIdValueBuf;
    fn to_owned(&self) -> Self::Owned {
        ClientIdValueBuf {
            data: self.data.to_vec()
        }
    }
}

impl std::fmt::Debug for ClientIdValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ClientIdValue")
            .field("spec", &self.spec())
            .field("length", &self.length())
            .field("value", &self.value())
            .finish()
    }
}

impl std::fmt::Debug for ClientIdValueBuf {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ClientIdValueBuf")
            .field("spec", &self.spec())
            .field("length", &self.length())
            .field("value", &self.value())
            .finish()
    }
}

#[derive(Clone)]
pub struct ClientIdValueIterator<'a> {
    pub(crate) params: (),
    pub(crate) rem: usize,
    pub(crate) ptr: *const u8,
    pub(crate) phantom: std::marker::PhantomData<&'a ClientIdValue>,
}

impl<'a> Iterator for ClientIdValueIterator<'a> {
    type Item = &'a ClientIdValue;

    fn next(&mut self) -> std::option::Option<Self::Item> {
        if self.rem == 0 {
            None
        } else { unsafe {
            self.rem -= 1;
            let mut offset = 0;
            let res = <&ClientIdValue>::unserialize(self.ptr, self.params, &mut offset);
            self.ptr = self.ptr.add(offset);
            Some(res)
        }}
    }
}

impl<'a> std::fmt::Debug for ClientIdValueIterator<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_list().entries(self.clone()).finish()
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct ResourceIdSpec {
    pub resource: u32,
    pub r#type: u32,
}

#[test]
fn test_sizeof_resource_id_spec() {
    assert_eq!(std::mem::size_of::<ResourceIdSpec>(), 8);
}

impl base::WiredOut for ResourceIdSpec {
    fn wire_len(&self) -> usize { 8 }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        let me = unsafe {
            std::slice::from_raw_parts(self as *const ResourceIdSpec as _, 8)
        };
        (&mut wire_buf[..me.len()]).copy_from_slice(me);
        8
    }
}

impl base::WiredIn for ResourceIdSpec {
    type Params = ();
    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize { 8 }
    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        *offset += 8;
        *(ptr as *const ResourceIdSpec)
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct ResourceSizeSpec {
    pub spec: ResourceIdSpec,
    pub bytes: u32,
    pub ref_count: u32,
    pub use_count: u32,
}

#[test]
fn test_sizeof_resource_size_spec() {
    assert_eq!(std::mem::size_of::<ResourceSizeSpec>(), 20);
}

impl base::WiredOut for ResourceSizeSpec {
    fn wire_len(&self) -> usize { 20 }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        let me = unsafe {
            std::slice::from_raw_parts(self as *const ResourceSizeSpec as _, 20)
        };
        (&mut wire_buf[..me.len()]).copy_from_slice(me);
        20
    }
}

impl base::WiredIn for ResourceSizeSpec {
    type Params = ();
    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize { 20 }
    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        *offset += 20;
        *(ptr as *const ResourceSizeSpec)
    }
}

pub struct ResourceSizeValue {
    data: [u8],
}

#[allow(unused_parens)]
impl ResourceSizeValue {
    pub(crate) unsafe fn from_data<D: AsRef<[u8]> + ?Sized>(data: &D) -> &ResourceSizeValue {
        debug_assert_eq!(data.as_ref().len(), <&ResourceSizeValue as base::WiredIn>::compute_wire_len(data.as_ref().as_ptr(), ()));
        &*(data.as_ref() as *const [u8] as *const ResourceSizeValue)
    }

    fn wire_ptr(&self) -> *const u8 { self.data.as_ptr() }

    pub fn size(&self) -> ResourceSizeSpec {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const ResourceSizeSpec;
            ptr.read_unaligned()
        }
    }

    fn num_cross_references(&self) -> u32 {
        unsafe {
            let offset = 20usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn cross_references(&self) -> &[ResourceSizeSpec] {
        unsafe {
            let offset = 24usize;
            let len = (self.num_cross_references() as usize) as _;
            let ptr = self.wire_ptr().add(offset) as *const ResourceSizeSpec;
            std::slice::from_raw_parts(ptr, len)
        }
    }
}

impl base::WiredOut for ResourceSizeValue {
    fn wire_len(&self) -> usize { self.data.len() }

    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
        (&mut wire_buf[..self.data.len()]).copy_from_slice(&self.data);
        self.data.len()
    }
}

impl base::WiredIn for &ResourceSizeValue {
    type Params = ();

    unsafe fn compute_wire_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // size
        sz += 20usize;
        // num_cross_references
        let num_cross_references = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // cross_references
        sz += ((num_cross_references as usize) * 20usize);
        sz
    }
    unsafe fn unserialize(ptr: *const u8, params: (), offset: &mut usize) -> Self {
        let sz = Self::compute_wire_len(ptr, params);
        *offset += sz;
        let data = std::slice::from_raw_parts(ptr, sz);
        ResourceSizeValue::from_data(data)
    }
}

#[derive(Clone)]
pub struct ResourceSizeValueBuf {
    data: Vec<u8>,
}

impl ResourceSizeValueBuf {
    pub(crate) unsafe fn from_data(data: Vec<u8>) -> ResourceSizeValueBuf {
        debug_assert_eq!(<&ResourceSizeValue>::compute_wire_len(data.as_ptr(), ()), data.len());
        ResourceSizeValueBuf { data }
    }

    /// Construct a new [ResourceSizeValueBuf].
    #[allow(unused_assignments, unused_unsafe)]
    pub fn new(
        size: ResourceSizeSpec,
        cross_references: &[ResourceSizeSpec],
    ) -> ResourceSizeValueBuf {
            unsafe {
            let mut wire_sz = 0usize;
            wire_sz += 20; // size
            wire_sz += 4; // num_cross_references
            wire_sz += cross_references.iter().map(|el| el.wire_len()).sum::<usize>();
            let mut wire_buf = vec![0u8; wire_sz];
            let mut wire_off = 0usize;

            wire_off += size.serialize(&mut wire_buf[wire_off .. ]);
            wire_off += (cross_references.len() as u32).serialize(&mut wire_buf[wire_off .. ]);
            for el in cross_references {
                wire_off += el.serialize(&mut wire_buf[wire_off ..]);
            }

            ResourceSizeValueBuf { data: wire_buf }
        }
    }
}

impl base::WiredIn for ResourceSizeValueBuf {
    type Params = ();
    unsafe fn compute_wire_len(ptr: *const u8, params: ()) -> usize {
    <&ResourceSizeValue>::compute_wire_len(ptr, params)
}
    unsafe fn unserialize(ptr: *const u8, params: (), offset: &mut usize) -> Self {
        let sz = Self::compute_wire_len(ptr, params);
        *offset += sz;
        let data = std::slice::from_raw_parts(ptr, sz);
        ResourceSizeValueBuf::from_data(data.to_vec())
    }
}

impl std::ops::Deref for ResourceSizeValueBuf {
    type Target = ResourceSizeValue;
    fn deref(&self) -> &Self::Target {
        unsafe { ResourceSizeValue::from_data(&self.data) }
    }
}

impl std::borrow::Borrow<ResourceSizeValue> for ResourceSizeValueBuf {
    fn borrow(&self) -> &ResourceSizeValue {
        unsafe { ResourceSizeValue::from_data(&self.data) }
    }
}

impl std::borrow::ToOwned for ResourceSizeValue {
    type Owned = ResourceSizeValueBuf;
    fn to_owned(&self) -> Self::Owned {
        ResourceSizeValueBuf {
            data: self.data.to_vec()
        }
    }
}

impl std::fmt::Debug for ResourceSizeValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ResourceSizeValue")
            .field("size", &self.size())
            .field("num_cross_references", &self.num_cross_references())
            .field("cross_references", &self.cross_references())
            .finish()
    }
}

impl std::fmt::Debug for ResourceSizeValueBuf {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ResourceSizeValueBuf")
            .field("size", &self.size())
            .field("num_cross_references", &self.num_cross_references())
            .field("cross_references", &self.cross_references())
            .finish()
    }
}

#[derive(Clone)]
pub struct ResourceSizeValueIterator<'a> {
    pub(crate) params: (),
    pub(crate) rem: usize,
    pub(crate) ptr: *const u8,
    pub(crate) phantom: std::marker::PhantomData<&'a ResourceSizeValue>,
}

impl<'a> Iterator for ResourceSizeValueIterator<'a> {
    type Item = &'a ResourceSizeValue;

    fn next(&mut self) -> std::option::Option<Self::Item> {
        if self.rem == 0 {
            None
        } else { unsafe {
            self.rem -= 1;
            let mut offset = 0;
            let res = <&ResourceSizeValue>::unserialize(self.ptr, self.params, &mut offset);
            self.ptr = self.ptr.add(offset);
            Some(res)
        }}
    }
}

impl<'a> std::fmt::Debug for ResourceSizeValueIterator<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_list().entries(self.clone()).finish()
    }
}

pub(crate) fn request_name(opcode: u16) -> std::option::Option<&'static str> {
    match opcode {
        0 => Some("res::QueryVersion"),
        1 => Some("res::QueryClients"),
        2 => Some("res::QueryClientResources"),
        3 => Some("res::QueryClientPixmapBytes"),
        4 => Some("res::QueryClientIds"),
        5 => Some("res::QueryResourceBytes"),
        _ => None,
    }
}

/// Reply type for [QueryVersion].
///
/// Can be obtained from a [QueryVersionCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryVersionCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryVersionReply {
    raw: *const u8,
}

impl QueryVersionReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn server_major(&self) -> u16 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn server_minor(&self) -> u16 {
        unsafe {
            let offset = 10usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }
}

impl base::Reply for QueryVersionReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryVersionReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryVersionReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("server_major", &self.server_major())
            .field("server_minor", &self.server_minor())
            .finish()
    }
}

impl Drop for QueryVersionReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryVersionReply {}
unsafe impl std::marker::Sync for QueryVersionReply {}

/// Cookie type for [QueryVersion].
///
/// This cookie can be used to get a [QueryVersionReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryVersionCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryVersion].
///
/// This cookie can be used to get a [QueryVersionReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryVersionCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryVersionCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryVersionCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryVersionCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryVersionCookie {
    type Reply = QueryVersionReply;
}

impl base::Cookie for QueryVersionCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryVersionCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryVersionCookieUnchecked {
    type Reply = QueryVersionReply;
}

/// The `QueryVersion` request.
///
/// This request replies [QueryVersionReply].
///
/// Associated cookie types are [QueryVersionCookie] and [QueryVersionCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryVersion {
    pub client_major: u8,
    pub client_minor: u8,
}

unsafe impl base::RawRequest for QueryVersion {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 0,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 6];
        self.client_major.serialize(&mut buf0[4 .. ]);
        self.client_minor.serialize(&mut buf0[5 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 6;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryVersion {
    type Cookie = QueryVersionCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryVersion {
    type Reply = QueryVersionReply;
    type Cookie = QueryVersionCookie;
    type CookieUnchecked = QueryVersionCookieUnchecked;
}

/// Reply type for [QueryClients].
///
/// Can be obtained from a [QueryClientsCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryClientsCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientsReply {
    raw: *const u8,
}

impl QueryClientsReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    unsafe fn compute_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // response_type
        sz += 1usize;
        // pad
        sz += 1usize;
        // sequence
        sz += 2usize;
        // length
        sz += 4usize;
        // num_clients
        let num_clients = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // pad
        sz += 20usize;
        // clients
        sz += ((num_clients as usize) * 8usize);
        sz
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    fn num_clients(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }


    pub fn clients(&self) -> &[Client] {
        unsafe {
            let offset = 32usize;
            let len = (self.num_clients() as usize) as _;
            let ptr = self.wire_ptr().add(offset) as *const Client;
            std::slice::from_raw_parts(ptr, len)
        }
    }
}

impl base::Reply for QueryClientsReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryClientsReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryClientsReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("num_clients", &self.num_clients())
            .field("pad", &20)
            .field("clients", &self.clients())
            .finish()
    }
}

impl Drop for QueryClientsReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryClientsReply {}
unsafe impl std::marker::Sync for QueryClientsReply {}

/// Cookie type for [QueryClients].
///
/// This cookie can be used to get a [QueryClientsReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryClientsCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryClients].
///
/// This cookie can be used to get a [QueryClientsReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientsCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryClientsCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientsCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryClientsCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryClientsCookie {
    type Reply = QueryClientsReply;
}

impl base::Cookie for QueryClientsCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientsCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryClientsCookieUnchecked {
    type Reply = QueryClientsReply;
}

/// The `QueryClients` request.
///
/// This request replies [QueryClientsReply].
///
/// Associated cookie types are [QueryClientsCookie] and [QueryClientsCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryClients {
}

unsafe impl base::RawRequest for QueryClients {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 1,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 4];
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 4;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryClients {
    type Cookie = QueryClientsCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryClients {
    type Reply = QueryClientsReply;
    type Cookie = QueryClientsCookie;
    type CookieUnchecked = QueryClientsCookieUnchecked;
}

/// Reply type for [QueryClientResources].
///
/// Can be obtained from a [QueryClientResourcesCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryClientResourcesCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientResourcesReply {
    raw: *const u8,
}

impl QueryClientResourcesReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    unsafe fn compute_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // response_type
        sz += 1usize;
        // pad
        sz += 1usize;
        // sequence
        sz += 2usize;
        // length
        sz += 4usize;
        // num_types
        let num_types = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // pad
        sz += 20usize;
        // types
        sz += ((num_types as usize) * 8usize);
        sz
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    fn num_types(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }


    pub fn types(&self) -> &[Type] {
        unsafe {
            let offset = 32usize;
            let len = (self.num_types() as usize) as _;
            let ptr = self.wire_ptr().add(offset) as *const Type;
            std::slice::from_raw_parts(ptr, len)
        }
    }
}

impl base::Reply for QueryClientResourcesReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryClientResourcesReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryClientResourcesReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("num_types", &self.num_types())
            .field("pad", &20)
            .field("types", &self.types())
            .finish()
    }
}

impl Drop for QueryClientResourcesReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryClientResourcesReply {}
unsafe impl std::marker::Sync for QueryClientResourcesReply {}

/// Cookie type for [QueryClientResources].
///
/// This cookie can be used to get a [QueryClientResourcesReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryClientResourcesCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryClientResources].
///
/// This cookie can be used to get a [QueryClientResourcesReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientResourcesCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryClientResourcesCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientResourcesCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryClientResourcesCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryClientResourcesCookie {
    type Reply = QueryClientResourcesReply;
}

impl base::Cookie for QueryClientResourcesCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientResourcesCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryClientResourcesCookieUnchecked {
    type Reply = QueryClientResourcesReply;
}

/// The `QueryClientResources` request.
///
/// This request replies [QueryClientResourcesReply].
///
/// Associated cookie types are [QueryClientResourcesCookie] and [QueryClientResourcesCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryClientResources {
    pub xid: u32,
}

unsafe impl base::RawRequest for QueryClientResources {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 2,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 8];
        self.xid.serialize(&mut buf0[4 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 8;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryClientResources {
    type Cookie = QueryClientResourcesCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryClientResources {
    type Reply = QueryClientResourcesReply;
    type Cookie = QueryClientResourcesCookie;
    type CookieUnchecked = QueryClientResourcesCookieUnchecked;
}

/// Reply type for [QueryClientPixmapBytes].
///
/// Can be obtained from a [QueryClientPixmapBytesCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryClientPixmapBytesCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientPixmapBytesReply {
    raw: *const u8,
}

impl QueryClientPixmapBytesReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn bytes(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn bytes_overflow(&self) -> u32 {
        unsafe {
            let offset = 12usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }
}

impl base::Reply for QueryClientPixmapBytesReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryClientPixmapBytesReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryClientPixmapBytesReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("bytes", &self.bytes())
            .field("bytes_overflow", &self.bytes_overflow())
            .finish()
    }
}

impl Drop for QueryClientPixmapBytesReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryClientPixmapBytesReply {}
unsafe impl std::marker::Sync for QueryClientPixmapBytesReply {}

/// Cookie type for [QueryClientPixmapBytes].
///
/// This cookie can be used to get a [QueryClientPixmapBytesReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryClientPixmapBytesCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryClientPixmapBytes].
///
/// This cookie can be used to get a [QueryClientPixmapBytesReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientPixmapBytesCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryClientPixmapBytesCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientPixmapBytesCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryClientPixmapBytesCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryClientPixmapBytesCookie {
    type Reply = QueryClientPixmapBytesReply;
}

impl base::Cookie for QueryClientPixmapBytesCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientPixmapBytesCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryClientPixmapBytesCookieUnchecked {
    type Reply = QueryClientPixmapBytesReply;
}

/// The `QueryClientPixmapBytes` request.
///
/// This request replies [QueryClientPixmapBytesReply].
///
/// Associated cookie types are [QueryClientPixmapBytesCookie] and [QueryClientPixmapBytesCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryClientPixmapBytes {
    pub xid: u32,
}

unsafe impl base::RawRequest for QueryClientPixmapBytes {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 3,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 8];
        self.xid.serialize(&mut buf0[4 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 8;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryClientPixmapBytes {
    type Cookie = QueryClientPixmapBytesCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryClientPixmapBytes {
    type Reply = QueryClientPixmapBytesReply;
    type Cookie = QueryClientPixmapBytesCookie;
    type CookieUnchecked = QueryClientPixmapBytesCookieUnchecked;
}

/// Reply type for [QueryClientIds].
///
/// Can be obtained from a [QueryClientIdsCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryClientIdsCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientIdsReply {
    raw: *const u8,
}

impl QueryClientIdsReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    unsafe fn compute_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // response_type
        sz += 1usize;
        // pad
        sz += 1usize;
        // sequence
        sz += 2usize;
        // length
        sz += 4usize;
        // num_ids
        let num_ids = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // pad
        sz += 20usize;
        // ids
        for _ in 0 .. (num_ids as usize) {
            sz += <&ClientIdValue>::compute_wire_len(ptr.add(sz), ());
        }
        sz
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    fn num_ids(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }


    pub fn ids(&self) -> ClientIdValueIterator<'_> {
        unsafe {
            let offset = 32usize;
            ClientIdValueIterator {
                params: (),
                rem: (self.num_ids() as usize),
                ptr: self.wire_ptr().add(offset),
                phantom: std::marker::PhantomData,
            }
        }
    }
}

impl base::Reply for QueryClientIdsReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryClientIdsReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryClientIdsReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("num_ids", &self.num_ids())
            .field("pad", &20)
            .field("ids", &self.ids())
            .finish()
    }
}

impl Drop for QueryClientIdsReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryClientIdsReply {}
unsafe impl std::marker::Sync for QueryClientIdsReply {}

/// Cookie type for [QueryClientIds].
///
/// This cookie can be used to get a [QueryClientIdsReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryClientIdsCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryClientIds].
///
/// This cookie can be used to get a [QueryClientIdsReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryClientIdsCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryClientIdsCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientIdsCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryClientIdsCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryClientIdsCookie {
    type Reply = QueryClientIdsReply;
}

impl base::Cookie for QueryClientIdsCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryClientIdsCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryClientIdsCookieUnchecked {
    type Reply = QueryClientIdsReply;
}

/// The `QueryClientIds` request.
///
/// This request replies [QueryClientIdsReply].
///
/// Associated cookie types are [QueryClientIdsCookie] and [QueryClientIdsCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryClientIds<'a> {
    pub specs: &'a [ClientIdSpec],
}

unsafe impl<'a> base::RawRequest for QueryClientIds<'a> {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 4,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 4,
            isvoid: 0,
        };

        let mut sections: [iovec; 6] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 6];

        let buf0: &mut [u8] = &mut [0; 8];
        (self.specs.len() as u32).serialize(&mut buf0[4 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 8;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        sections[4].iov_base = self.specs.as_ptr() as *mut _;
        sections[4].iov_len = self.specs.len() * std::mem::size_of::<ClientIdSpec>();
        sections[5].iov_len = base::align_pad(sections[4].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl<'a> base::Request for QueryClientIds<'a> {
    type Cookie = QueryClientIdsCookie;
    const IS_VOID: bool = false;
}

impl<'a> base::RequestWithReply for QueryClientIds<'a> {
    type Reply = QueryClientIdsReply;
    type Cookie = QueryClientIdsCookie;
    type CookieUnchecked = QueryClientIdsCookieUnchecked;
}

/// Reply type for [QueryResourceBytes].
///
/// Can be obtained from a [QueryResourceBytesCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryResourceBytesCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryResourceBytesReply {
    raw: *const u8,
}

impl QueryResourceBytesReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    unsafe fn compute_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // response_type
        sz += 1usize;
        // pad
        sz += 1usize;
        // sequence
        sz += 2usize;
        // length
        sz += 4usize;
        // num_sizes
        let num_sizes = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // pad
        sz += 20usize;
        // sizes
        for _ in 0 .. (num_sizes as usize) {
            sz += <&ResourceSizeValue>::compute_wire_len(ptr.add(sz), ());
        }
        sz
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    fn num_sizes(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }


    pub fn sizes(&self) -> ResourceSizeValueIterator<'_> {
        unsafe {
            let offset = 32usize;
            ResourceSizeValueIterator {
                params: (),
                rem: (self.num_sizes() as usize),
                ptr: self.wire_ptr().add(offset),
                phantom: std::marker::PhantomData,
            }
        }
    }
}

impl base::Reply for QueryResourceBytesReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryResourceBytesReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryResourceBytesReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("num_sizes", &self.num_sizes())
            .field("pad", &20)
            .field("sizes", &self.sizes())
            .finish()
    }
}

impl Drop for QueryResourceBytesReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryResourceBytesReply {}
unsafe impl std::marker::Sync for QueryResourceBytesReply {}

/// Cookie type for [QueryResourceBytes].
///
/// This cookie can be used to get a [QueryResourceBytesReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryResourceBytesCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryResourceBytes].
///
/// This cookie can be used to get a [QueryResourceBytesReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryResourceBytesCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryResourceBytesCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryResourceBytesCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryResourceBytesCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryResourceBytesCookie {
    type Reply = QueryResourceBytesReply;
}

impl base::Cookie for QueryResourceBytesCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryResourceBytesCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryResourceBytesCookieUnchecked {
    type Reply = QueryResourceBytesReply;
}

/// The `QueryResourceBytes` request.
///
/// This request replies [QueryResourceBytesReply].
///
/// Associated cookie types are [QueryResourceBytesCookie] and [QueryResourceBytesCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryResourceBytes<'a> {
    pub client: u32,
    pub specs: &'a [ResourceIdSpec],
}

unsafe impl<'a> base::RawRequest for QueryResourceBytes<'a> {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 4,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 5,
            isvoid: 0,
        };

        let mut sections: [iovec; 6] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 6];

        let buf0: &mut [u8] = &mut [0; 12];
        self.client.serialize(&mut buf0[4 .. ]);
        (self.specs.len() as u32).serialize(&mut buf0[8 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 12;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        sections[4].iov_base = self.specs.as_ptr() as *mut _;
        sections[4].iov_len = self.specs.len() * std::mem::size_of::<ResourceIdSpec>();
        sections[5].iov_len = base::align_pad(sections[4].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl<'a> base::Request for QueryResourceBytes<'a> {
    type Cookie = QueryResourceBytesCookie;
    const IS_VOID: bool = false;
}

impl<'a> base::RequestWithReply for QueryResourceBytes<'a> {
    type Reply = QueryResourceBytesReply;
    type Cookie = QueryResourceBytesCookie;
    type CookieUnchecked = QueryResourceBytesCookieUnchecked;
}
