use std::{
    fmt::{self, Debug},
    mem,
    ptr::NonNull,
    sync::Mutex,
    time::Duration,
};

use libc::{c_int, c_uchar, c_uint};
use libusb1_sys::{constants::*, *};

use crate::{
    config_descriptor::ConfigDescriptor,
    device::{self, Device},
    device_descriptor::DeviceDescriptor,
    error::{self, Error},
    fields::{request_type, Direction, Recipient, RequestType},
    interface_descriptor::InterfaceDescriptor,
    language::Language,
    UsbContext,
};

/// Bit set representing claimed USB interfaces.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
struct ClaimedInterfaces {
    inner: [u128; 2],
}

impl ClaimedInterfaces {
    /// Create a new bit set.
    fn new() -> Self {
        Self { inner: [0, 0] }
    }

    fn get_index_and_mask(interface: u8) -> (usize, u128) {
        ((interface / 128) as usize, 1 << (interface % 128))
    }

    /// Mark `interface` as claimed.
    fn insert(&mut self, interface: u8) {
        let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
        self.inner[index] |= mask;
    }

    /// Mark `interface` as not claimed.
    fn remove(&mut self, interface: u8) {
        let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
        self.inner[index] &= !mask;
    }

    /// Returns true if this set contains `interface`.
    fn contains(&self, interface: u8) -> bool {
        let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
        self.inner[index] & mask != 0
    }

    /// Returns a count of the interfaces contained in this set.
    fn size(&self) -> usize {
        self.inner.iter().map(|v| v.count_ones()).sum::<u32>() as usize
    }

    /// Returns an iterator over the interfaces in this set.
    fn iter(&self) -> ClaimedInterfacesIter {
        ClaimedInterfacesIter::new(self)
    }
}

/// Iterator over interfaces.
struct ClaimedInterfacesIter<'a> {
    // Next interface to check as a possible value to return from the interator.
    index: u16,

    // Number of elements remaining in this iterator.
    remaining: usize,

    // The ClaimedInterfaces object that we're iterating over.
    source: &'a ClaimedInterfaces,
}

impl ClaimedInterfacesIter<'_> {
    /// Create a new iterator over the interfaces in `source`.
    fn new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter {
        ClaimedInterfacesIter {
            index: 0,
            remaining: source.size(),
            source,
        }
    }
}

impl<'a> Iterator for ClaimedInterfacesIter<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        while self.index <= u8::MAX as u16 {
            let index = self.index as u8;
            let contains = self.source.contains(index);
            self.index += 1;
            if contains {
                self.remaining -= 1;
                return Some(index);
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.remaining, Some(self.remaining))
    }
}

/// A handle to an open USB device.
pub struct DeviceHandle<T: UsbContext> {
    context: T,
    handle: Option<NonNull<libusb_device_handle>>,
    interfaces: Mutex<ClaimedInterfaces>,
}

impl<T: UsbContext> Drop for DeviceHandle<T> {
    /// Closes the device.
    fn drop(&mut self) {
        unsafe {
            let interfaces = self.interfaces.lock().unwrap();
            for iface in interfaces.iter() {
                libusb_release_interface(self.as_raw(), iface as c_int);
            }

            if let Some(handle) = self.handle {
                libusb_close(handle.as_ptr());
            }
        }
    }
}

unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
unsafe impl<T: UsbContext> Sync for DeviceHandle<T> {}

impl<T: UsbContext> Debug for DeviceHandle<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("DeviceHandle")
            .field("device", &self.device())
            .field("handle", &self.handle)
            .field("interfaces", &*self.interfaces.lock().unwrap())
            .finish()
    }
}

impl<T: UsbContext + PartialEq> PartialEq for DeviceHandle<T> {
    fn eq(&self, other: &Self) -> bool {
        self.context == other.context
            && self.handle == other.handle
            && *self.interfaces.lock().unwrap() == *other.interfaces.lock().unwrap()
    }
}

impl<T: UsbContext + PartialEq> Eq for DeviceHandle<T> {}

impl<T: UsbContext> DeviceHandle<T> {
    /// Get the raw libusb_device_handle pointer, for advanced use in unsafe code.
    ///
    /// This structure tracks claimed interfaces, and will get out if sync if interfaces are
    /// manipulated externally. Use only libusb endpoint IO functions.
    pub fn as_raw(&self) -> *mut libusb_device_handle {
        // Safety: handle is Some() after initialization
        match self.handle {
            Some(it) => it.as_ptr(),
            _ => unreachable!(),
        }
    }

    /// Consumes the `DeviceHandle`, returning the raw libusb_device_handle
    /// pointer, for advanced use in unsafe code.
    ///
    /// # Safety
    ///
    /// Panics if you have any claimed interfaces on this handle.
    pub fn into_raw(mut self) -> *mut libusb_device_handle {
        assert_eq!(self.interfaces.lock().unwrap().size(), 0);
        match self.handle.take() {
            Some(it) => it.as_ptr(),
            _ => unreachable!(),
        }
    }

    /// Get the context associated with this device
    pub fn context(&self) -> &T {
        &self.context
    }

    /// Get the device associated to this handle
    pub fn device(&self) -> Device<T> {
        unsafe {
            device::Device::from_libusb(
                self.context.clone(),
                std::ptr::NonNull::new_unchecked(libusb_get_device(self.as_raw())),
            )
        }
    }

    /// # Safety
    ///
    /// Converts an existing `libusb_device_handle` pointer into a `DeviceHandle<T>`.
    /// `handle` must be a pointer to a valid `libusb_device_handle`. Rusb assumes ownership of the handle, and will close it on `drop`.
    pub unsafe fn from_libusb(
        context: T,
        handle: NonNull<libusb_device_handle>,
    ) -> DeviceHandle<T> {
        DeviceHandle {
            context,
            handle: Some(handle),
            interfaces: Mutex::new(ClaimedInterfaces::new()),
        }
    }

    /// Returns the active configuration number.
    pub fn active_configuration(&self) -> crate::Result<u8> {
        let mut config = mem::MaybeUninit::<c_int>::uninit();

        try_unsafe!(libusb_get_configuration(self.as_raw(), config.as_mut_ptr()));
        Ok(unsafe { config.assume_init() } as u8)
    }

    /// Sets the device's active configuration.
    pub fn set_active_configuration(&self, config: u8) -> crate::Result<()> {
        try_unsafe!(libusb_set_configuration(self.as_raw(), c_int::from(config)));
        Ok(())
    }

    /// Puts the device in an unconfigured state.
    pub fn unconfigure(&self) -> crate::Result<()> {
        try_unsafe!(libusb_set_configuration(self.as_raw(), -1));
        Ok(())
    }

    /// Resets the device.
    pub fn reset(&self) -> crate::Result<()> {
        try_unsafe!(libusb_reset_device(self.as_raw()));
        Ok(())
    }

    /// Clear the halt/stall condition for an endpoint.
    pub fn clear_halt(&self, endpoint: u8) -> crate::Result<()> {
        try_unsafe!(libusb_clear_halt(self.as_raw(), endpoint));
        Ok(())
    }

    /// Indicates whether the device has an attached kernel driver.
    ///
    /// This method is not supported on all platforms.
    pub fn kernel_driver_active(&self, iface: u8) -> crate::Result<bool> {
        match unsafe { libusb_kernel_driver_active(self.as_raw(), c_int::from(iface)) } {
            0 => Ok(false),
            1 => Ok(true),
            err => Err(error::from_libusb(err)),
        }
    }

    /// Detaches an attached kernel driver from the device.
    ///
    /// This method is not supported on all platforms.
    pub fn detach_kernel_driver(&self, iface: u8) -> crate::Result<()> {
        try_unsafe!(libusb_detach_kernel_driver(
            self.as_raw(),
            c_int::from(iface)
        ));
        Ok(())
    }

    /// Attaches a kernel driver to the device.
    ///
    /// This method is not supported on all platforms.
    pub fn attach_kernel_driver(&self, iface: u8) -> crate::Result<()> {
        try_unsafe!(libusb_attach_kernel_driver(
            self.as_raw(),
            c_int::from(iface)
        ));
        Ok(())
    }

    /// Enable/disable automatic kernel driver detachment.
    ///
    /// When this is enabled rusb will automatically detach the
    /// kernel driver on an interface when claiming the interface, and
    /// attach it when releasing the interface.
    ///
    /// On platforms which do not have support, this function will
    /// return `Error::NotSupported`, and rusb will continue as if
    /// this function was never called.
    pub fn set_auto_detach_kernel_driver(&self, auto_detach: bool) -> crate::Result<()> {
        try_unsafe!(libusb_set_auto_detach_kernel_driver(
            self.as_raw(),
            auto_detach.into()
        ));
        Ok(())
    }

    /// Claims one of the device's interfaces.
    ///
    /// An interface must be claimed before operating on it. All claimed interfaces are released
    /// when the device handle goes out of scope.
    pub fn claim_interface(&self, iface: u8) -> crate::Result<()> {
        try_unsafe!(libusb_claim_interface(self.as_raw(), c_int::from(iface)));
        self.interfaces.lock().unwrap().insert(iface);
        Ok(())
    }

    /// Releases a claimed interface.
    pub fn release_interface(&self, iface: u8) -> crate::Result<()> {
        try_unsafe!(libusb_release_interface(self.as_raw(), c_int::from(iface)));
        self.interfaces.lock().unwrap().remove(iface);
        Ok(())
    }

    /// Sets an interface's active setting.
    pub fn set_alternate_setting(&self, iface: u8, setting: u8) -> crate::Result<()> {
        try_unsafe!(libusb_set_interface_alt_setting(
            self.as_raw(),
            c_int::from(iface),
            c_int::from(setting)
        ));
        Ok(())
    }

    /// Reads from an interrupt endpoint.
    ///
    /// This function attempts to read from the interrupt endpoint with the address given by the
    /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function
    /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds,
    /// anything smaller will result in an infinite block.
    ///
    /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received
    /// from the endpoint.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were read.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if the endpoint is not an input endpoint.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the endpoint halted.
    /// * `Overflow` if the device offered more data.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn read_interrupt(
        &self,
        endpoint: u8,
        buf: &mut [u8],
        timeout: Duration,
    ) -> crate::Result<usize> {
        if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
            return Err(Error::InvalidParam);
        }
        let mut transferred = mem::MaybeUninit::<c_int>::uninit();
        unsafe {
            match libusb_interrupt_transfer(
                self.as_raw(),
                endpoint,
                buf.as_mut_ptr() as *mut c_uchar,
                buf.len() as c_int,
                transferred.as_mut_ptr(),
                timeout.as_millis() as c_uint,
            ) {
                0 => Ok(transferred.assume_init() as usize),
                err if err == LIBUSB_ERROR_INTERRUPTED => {
                    let transferred = transferred.assume_init();
                    if transferred > 0 {
                        Ok(transferred as usize)
                    } else {
                        Err(error::from_libusb(err))
                    }
                }
                err => Err(error::from_libusb(err)),
            }
        }
    }

    /// Writes to an interrupt endpoint.
    ///
    /// This function attempts to write the contents of `buf` to the interrupt endpoint with the
    /// address given by the `endpoint` parameter. The function blocks up to the amount of time
    /// specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will
    /// result in an infinite block.
    ///
    /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were written.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if the endpoint is not an output endpoint.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the endpoint halted.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn write_interrupt(
        &self,
        endpoint: u8,
        buf: &[u8],
        timeout: Duration,
    ) -> crate::Result<usize> {
        if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
            return Err(Error::InvalidParam);
        }
        let mut transferred = mem::MaybeUninit::<c_int>::uninit();
        unsafe {
            match libusb_interrupt_transfer(
                self.as_raw(),
                endpoint,
                buf.as_ptr() as *mut c_uchar,
                buf.len() as c_int,
                transferred.as_mut_ptr(),
                timeout.as_millis() as c_uint,
            ) {
                0 => Ok(transferred.assume_init() as usize),
                err if err == LIBUSB_ERROR_INTERRUPTED => {
                    let transferred = transferred.assume_init();
                    if transferred > 0 {
                        Ok(transferred as usize)
                    } else {
                        Err(error::from_libusb(err))
                    }
                }
                err => Err(error::from_libusb(err)),
            }
        }
    }

    /// Reads from a bulk endpoint.
    ///
    /// This function attempts to read from the bulk endpoint with the address given by the
    /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function
    /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds,
    /// anything smaller will result in an infinite block.
    ///
    /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received
    /// from the endpoint.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were read.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if the endpoint is not an input endpoint.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the endpoint halted.
    /// * `Overflow` if the device offered more data.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn read_bulk(
        &self,
        endpoint: u8,
        buf: &mut [u8],
        timeout: Duration,
    ) -> crate::Result<usize> {
        if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
            return Err(Error::InvalidParam);
        }
        let mut transferred = mem::MaybeUninit::<c_int>::uninit();
        unsafe {
            match libusb_bulk_transfer(
                self.as_raw(),
                endpoint,
                buf.as_mut_ptr() as *mut c_uchar,
                buf.len() as c_int,
                transferred.as_mut_ptr(),
                timeout.as_millis() as c_uint,
            ) {
                0 => Ok(transferred.assume_init() as usize),
                err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => {
                    let transferred = transferred.assume_init();
                    if transferred > 0 {
                        Ok(transferred as usize)
                    } else {
                        Err(error::from_libusb(err))
                    }
                }
                err => Err(error::from_libusb(err)),
            }
        }
    }

    /// Writes to a bulk endpoint.
    ///
    /// This function attempts to write the contents of `buf` to the bulk endpoint with the address
    /// given by the `endpoint` parameter. The function blocks up to the amount of time specified
    /// by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will result in an
    /// infinite block.
    ///
    /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were written.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if the endpoint is not an output endpoint.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the endpoint halted.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn write_bulk(&self, endpoint: u8, buf: &[u8], timeout: Duration) -> crate::Result<usize> {
        if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
            return Err(Error::InvalidParam);
        }
        let mut transferred = mem::MaybeUninit::<c_int>::uninit();
        unsafe {
            match libusb_bulk_transfer(
                self.as_raw(),
                endpoint,
                buf.as_ptr() as *mut c_uchar,
                buf.len() as c_int,
                transferred.as_mut_ptr(),
                timeout.as_millis() as c_uint,
            ) {
                0 => Ok(transferred.assume_init() as usize),
                err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => {
                    let transferred = transferred.assume_init();
                    if transferred > 0 {
                        Ok(transferred as usize)
                    } else {
                        Err(error::from_libusb(err))
                    }
                }
                err => Err(error::from_libusb(err)),
            }
        }
    }

    /// Reads data using a control transfer.
    ///
    /// This function attempts to read data from the device using a control transfer and fills
    /// `buf` with any data received during the transfer. The function blocks up to the amount of
    /// time specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will
    /// result in an infinite block.
    ///
    /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the
    /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex`
    /// respectively). The values for each of these parameters shall be given in host-endian byte
    /// order. The value for the `request_type` parameter can be built with the helper function,
    /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the
    /// type of control request.
    ///
    /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were read.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if `request_type` does not specify a read transfer.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the control request was not supported by the device.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn read_control(
        &self,
        request_type: u8,
        request: u8,
        value: u16,
        index: u16,
        buf: &mut [u8],
        timeout: Duration,
    ) -> crate::Result<usize> {
        if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
            return Err(Error::InvalidParam);
        }
        let res = unsafe {
            libusb_control_transfer(
                self.as_raw(),
                request_type,
                request,
                value,
                index,
                buf.as_mut_ptr() as *mut c_uchar,
                buf.len() as u16,
                timeout.as_millis() as c_uint,
            )
        };

        if res < 0 {
            Err(error::from_libusb(res))
        } else {
            Ok(res as usize)
        }
    }

    /// Writes data using a control transfer.
    ///
    /// This function attempts to write the contents of `buf` to the device using a control
    /// transfer. The function blocks up to the amount of time specified by `timeout`.
    /// Minimal `timeout` is 1 milliseconds, anything smaller will result in an infinite block.
    ///
    /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the
    /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex`
    /// respectively). The values for each of these parameters shall be given in host-endian byte
    /// order. The value for the `request_type` parameter can be built with the helper function,
    /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the
    /// type of control request.
    ///
    /// If the return value is `Ok(n)`, then `n` bytes of `buf` were transfered.
    ///
    /// ## Errors
    ///
    /// If this function encounters any form of error while fulfilling the transfer request, an
    /// error variant will be returned. If an error variant is returned, no bytes were read.
    ///
    /// The errors returned by this function include:
    ///
    /// * `InvalidParam` if `request_type` does not specify a write transfer.
    /// * `Timeout` if the transfer timed out.
    /// * `Pipe` if the control request was not supported by the device.
    /// * `NoDevice` if the device has been disconnected.
    /// * `Io` if the transfer encountered an I/O error.
    pub fn write_control(
        &self,
        request_type: u8,
        request: u8,
        value: u16,
        index: u16,
        buf: &[u8],
        timeout: Duration,
    ) -> crate::Result<usize> {
        if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
            return Err(Error::InvalidParam);
        }
        let res = unsafe {
            libusb_control_transfer(
                self.as_raw(),
                request_type,
                request,
                value,
                index,
                buf.as_ptr() as *mut c_uchar,
                buf.len() as u16,
                timeout.as_millis() as c_uint,
            )
        };

        if res < 0 {
            Err(error::from_libusb(res))
        } else {
            Ok(res as usize)
        }
    }

    /// Reads the languages supported by the device's string descriptors.
    ///
    /// This function returns a list of languages that can be used to read the device's string
    /// descriptors.
    pub fn read_languages(&self, timeout: Duration) -> crate::Result<Vec<Language>> {
        let mut buf = [0u8; 255];

        let len = self.read_control(
            request_type(Direction::In, RequestType::Standard, Recipient::Device),
            LIBUSB_REQUEST_GET_DESCRIPTOR,
            u16::from(LIBUSB_DT_STRING) << 8,
            0,
            &mut buf,
            timeout,
        )?;

        if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 {
            return Err(Error::BadDescriptor);
        }

        if len == 2 {
            return Ok(Vec::new());
        }

        Ok(buf[0..len]
            .chunks(2)
            .skip(1)
            .map(|chunk| {
                let lang_id = u16::from(chunk[0]) | u16::from(chunk[1]) << 8;
                crate::language::from_lang_id(lang_id)
            })
            .collect())
    }

    /// Reads a ascii string descriptor from the device.
    ///
    pub fn read_string_descriptor_ascii(&self, index: u8) -> crate::Result<String> {
        let mut buf = Vec::<u8>::with_capacity(255);

        let ptr = buf.as_mut_ptr() as *mut c_uchar;
        let capacity = buf.capacity() as i32;

        let res =
            unsafe { libusb_get_string_descriptor_ascii(self.as_raw(), index, ptr, capacity) };

        if res < 0 {
            return Err(error::from_libusb(res));
        }

        unsafe {
            buf.set_len(res as usize);
        }

        String::from_utf8(buf).map_err(|_| Error::Other)
    }

    /// Reads a string descriptor from the device.
    ///
    /// `language` should be one of the languages returned from [`read_languages`](#method.read_languages).
    pub fn read_string_descriptor(
        &self,
        language: Language,
        index: u8,
        timeout: Duration,
    ) -> crate::Result<String> {
        let mut buf = [0u16; 128];

        let len = {
            // SAFETY: since we create slice from existing slice pointer valid
            // alignment of [u8] less or equal to the [u16]
            // size is less then allocated buffer (128 * 2 = 256 => 256 < 255)
            let buf = unsafe {
                std::slice::from_raw_parts_mut(
                    buf.as_mut_ptr().cast::<u8>(),
                    255, // Some devices choke on size > 255
                )
            };

            let len = self.read_control(
                request_type(Direction::In, RequestType::Standard, Recipient::Device),
                LIBUSB_REQUEST_GET_DESCRIPTOR,
                u16::from(LIBUSB_DT_STRING) << 8 | u16::from(index),
                language.lang_id(),
                buf,
                timeout,
            )?;

            if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 {
                return Err(Error::BadDescriptor);
            }

            len
        };

        if len == 2 {
            return Ok(String::new());
        }

        // len in bytes, skip first element(it's contain descriptor type and len)
        String::from_utf16(&buf[1..(len / 2)]).map_err(|_| Error::Other)
    }

    /// Reads the device's manufacturer string descriptor (ascii).
    pub fn read_manufacturer_string_ascii(
        &self,
        device: &DeviceDescriptor,
    ) -> crate::Result<String> {
        match device.manufacturer_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor_ascii(n),
        }
    }

    /// Reads the device's manufacturer string descriptor.
    pub fn read_manufacturer_string(
        &self,
        language: Language,
        device: &DeviceDescriptor,
        timeout: Duration,
    ) -> crate::Result<String> {
        match device.manufacturer_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor(language, n, timeout),
        }
    }

    /// Reads the device's product string descriptor (ascii).
    pub fn read_product_string_ascii(&self, device: &DeviceDescriptor) -> crate::Result<String> {
        match device.product_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor_ascii(n),
        }
    }

    /// Reads the device's product string descriptor.
    pub fn read_product_string(
        &self,
        language: Language,
        device: &DeviceDescriptor,
        timeout: Duration,
    ) -> crate::Result<String> {
        match device.product_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor(language, n, timeout),
        }
    }

    /// Reads the device's serial number string descriptor (ascii).
    pub fn read_serial_number_string_ascii(
        &self,
        device: &DeviceDescriptor,
    ) -> crate::Result<String> {
        match device.serial_number_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor_ascii(n),
        }
    }

    /// Reads the device's serial number string descriptor.
    pub fn read_serial_number_string(
        &self,
        language: Language,
        device: &DeviceDescriptor,
        timeout: Duration,
    ) -> crate::Result<String> {
        match device.serial_number_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor(language, n, timeout),
        }
    }

    /// Reads the string descriptor for a configuration's description.
    pub fn read_configuration_string(
        &self,
        language: Language,
        configuration: &ConfigDescriptor,
        timeout: Duration,
    ) -> crate::Result<String> {
        match configuration.description_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor(language, n, timeout),
        }
    }

    /// Reads the string descriptor for a interface's description.
    pub fn read_interface_string(
        &self,
        language: Language,
        interface: &InterfaceDescriptor,
        timeout: Duration,
    ) -> crate::Result<String> {
        match interface.description_string_index() {
            None => Err(Error::InvalidParam),
            Some(n) => self.read_string_descriptor(language, n, timeout),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::ClaimedInterfaces;
    use std::u8;

    #[test]
    fn claimed_interfaces_empty() {
        let empty = ClaimedInterfaces::new();
        assert_eq!(empty.size(), 0);
        for i in 0..=u8::MAX {
            assert!(!empty.contains(i), "empty set should not contain {}", i);
        }

        let mut iter = empty.iter();
        assert_eq!(iter.size_hint(), (0, Some(0)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn claimed_interfaces_one_element() {
        let mut interfaces = ClaimedInterfaces::new();
        interfaces.insert(94);
        assert_eq!(interfaces.size(), 1);
        assert!(interfaces.contains(94));
        for i in 0..=u8::MAX {
            if i == 94 {
                continue;
            }
            assert!(
                !interfaces.contains(i),
                "interfaces should not contain {}",
                i
            );
        }

        let mut iter = interfaces.iter();
        assert_eq!(iter.size_hint(), (1, Some(1)));
        assert_eq!(iter.next(), Some(94));
        assert_eq!(iter.size_hint(), (0, Some(0)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn claimed_interfaces_many_elements() {
        let mut interfaces = ClaimedInterfaces::new();
        let elements = vec![94, 0, 255, 17, 183, 6];

        for (index, &interface) in elements.iter().enumerate() {
            interfaces.insert(interface);
            assert_eq!(interfaces.size(), index + 1);
        }

        // Validate contains().
        for &interface in elements.iter() {
            assert!(
                interfaces.contains(interface),
                "interfaces should contain {}",
                interface
            );
        }

        // Validate iter().
        let contents = interfaces.iter().collect::<Vec<_>>().sort();
        assert_eq!(contents, elements.clone().sort());

        // Validate size_hint().
        let mut iter = interfaces.iter();
        let mut read = 0;
        loop {
            assert!(
                read <= elements.len(),
                "read elements {} should not exceed elements size {}",
                read,
                elements.len()
            );
            let remaining = elements.len() - read;
            assert_eq!(iter.size_hint(), (remaining, Some(remaining)));
            match iter.next() {
                Some(_) => read += 1,
                None => break,
            }
        }
    }
}
