From 5aa21072a7665fd5ca59b9f5f24a253a95e1d4f7 Mon Sep 17 00:00:00 2001 From: Ilya Averyanov Date: Mon, 2 Aug 2021 15:44:34 +0300 Subject: [PATCH] Improve read_string_descriptor Remove unnecessary vector allocation. --- src/device_handle.rs | 49 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/device_handle.rs b/src/device_handle.rs index b3ee37e..3c06f7f 100644 --- a/src/device_handle.rs +++ b/src/device_handle.rs @@ -691,32 +691,41 @@ impl DeviceHandle { index: u8, timeout: Duration, ) -> crate::Result { - 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 | u16::from(index), - language.lang_id(), - &mut buf, - timeout, - )?; + 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::(), + 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); + } - if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 { - return Err(Error::BadDescriptor); - } + len + }; if len == 2 { return Ok(String::new()); } - let utf16: Vec = buf[..len] - .chunks(2) - .skip(1) - .map(|chunk| u16::from(chunk[0]) | u16::from(chunk[1]) << 8) - .collect(); - - String::from_utf16(&utf16).map_err(|_| Error::Other) + // 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).