@@ -4,9 +4,12 @@ use crate::api_commands::{
44} ;
55use crate :: utils;
66use hidapi:: HidApi ;
7- use pyo3:: prelude:: * ;
87use std:: str:: FromStr ;
98use std:: vec;
9+ use core:: result:: Result ;
10+
11+ #[ cfg( feature = "python" ) ]
12+ use pyo3:: prelude:: * ;
1013
1114const COMMAND_START : u8 = 0x00 ;
1215
@@ -21,14 +24,14 @@ pub type Layer = u8;
2124pub type Row = u8 ;
2225pub type Column = u8 ;
2326
24- #[ pyclass]
27+ #[ cfg_attr ( feature = "python" , pyclass) ]
2528#[ derive( Clone , Copy , Debug ) ]
2629pub struct MatrixInfo {
2730 pub rows : u8 ,
2831 pub cols : u8 ,
2932}
3033
31- #[ pyclass]
34+ #[ cfg_attr ( feature = "python" , pyclass) ]
3235#[ derive( Clone , Copy , Debug ) ]
3336pub enum KeyboardValue {
3437 Uptime = 0x01 ,
@@ -53,18 +56,50 @@ impl FromStr for KeyboardValue {
5356 }
5457}
5558
56- #[ pyclass( unsendable) ]
59+ #[ cfg_attr ( feature = "python" , pyclass( unsendable) ) ]
5760pub struct KeyboardApi {
5861 device : hidapi:: HidDevice ,
5962}
6063
64+ #[ cfg( feature = "python" ) ]
6165#[ pymethods]
6266impl KeyboardApi {
6367 #[ new]
64- pub fn new ( vid : u16 , pid : u16 , usage_page : u16 ) -> PyResult < Self > {
65- let api = HidApi :: new ( ) . map_err ( |e| {
66- PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( format ! ( "Error: {}" , e) )
67- } ) ?;
68+ pub fn py_new ( vid : u16 , pid : u16 , usage_page : u16 ) -> Result < Self , Error > {
69+ KeyboardApi :: new ( vid, pid, usage_page)
70+ }
71+ }
72+
73+ #[ cfg( feature = "python" ) ]
74+ impl From < Error > for PyErr {
75+ fn from ( err : Error ) -> Self {
76+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( err. 0 )
77+ }
78+ }
79+
80+ pub struct Error ( pub String ) ;
81+
82+ impl std:: fmt:: Display for Error {
83+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
84+ f. write_str ( self . 0 . as_str ( ) )
85+ }
86+ }
87+
88+ impl From < String > for Error {
89+ fn from ( err : String ) -> Self {
90+ Error ( err)
91+ }
92+ }
93+
94+ impl From < & str > for Error {
95+ fn from ( err : & str ) -> Self {
96+ Error ( err. to_string ( ) )
97+ }
98+ }
99+
100+ impl KeyboardApi {
101+ pub fn new ( vid : u16 , pid : u16 , usage_page : u16 ) -> Result < KeyboardApi , Error > {
102+ let api = HidApi :: new ( ) . map_err ( |e| format ! ( "Error: {e}" ) ) ?;
68103
69104 let device = api
70105 . device_list ( )
@@ -73,16 +108,16 @@ impl KeyboardApi {
73108 && device. product_id ( ) == pid
74109 && device. usage_page ( ) == usage_page
75110 } )
76- . ok_or_else ( || {
77- PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Could not find keyboard." )
78- } ) ?
111+ . ok_or ( "Could not find keyboard." ) ?
79112 . open_device ( & api)
80- . map_err ( |_| {
81- PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Could not open HID device." )
82- } ) ?;
113+ . map_err ( |_| "Could not open HID device." ) ?;
83114
84115 Ok ( KeyboardApi { device } )
85116 }
117+ }
118+
119+ #[ cfg_attr( feature = "python" , pymethods) ]
120+ impl KeyboardApi {
86121
87122 /// Sends a raw HID command prefixed with the command byte and returns the response if successful.
88123 pub fn hid_command ( & self , command : ViaCommandId , bytes : Vec < u8 > ) -> Option < Vec < u8 > > {
@@ -188,23 +223,21 @@ impl KeyboardApi {
188223 fn fast_read_raw_matrix ( & self , matrix_info : MatrixInfo , layer : Layer ) -> Option < Vec < u16 > > {
189224 const MAX_KEYCODES_PARTIAL : usize = 14 ;
190225 let length = matrix_info. rows as usize * matrix_info. cols as usize ;
191- let buffer_list = vec ! [ 0 ; length. div_ceil( MAX_KEYCODES_PARTIAL ) as usize ] ;
226+ let buffer_len = length. div_ceil ( MAX_KEYCODES_PARTIAL ) ;
192227 let mut remaining = length;
193228 let mut result = Vec :: new ( ) ;
194- for _ in 0 ..buffer_list . len ( ) {
229+ for _ in 0 ..buffer_len {
195230 if remaining < MAX_KEYCODES_PARTIAL {
196- self . get_keymap_buffer (
231+ if let Some ( val ) = self . get_keymap_buffer (
197232 layer as u16 * length as u16 * 2 + 2 * ( length - remaining) as u16 ,
198233 ( remaining * 2 ) as u8 ,
199- )
200- . map ( |val| result. extend ( val) ) ;
234+ ) { result. extend ( val) }
201235 remaining = 0 ;
202236 } else {
203- self . get_keymap_buffer (
237+ if let Some ( val ) = self . get_keymap_buffer (
204238 layer as u16 * length as u16 * 2 + 2 * ( length - remaining) as u16 ,
205239 ( MAX_KEYCODES_PARTIAL * 2 ) as u8 ,
206- )
207- . map ( |val| result. extend ( val) ) ;
240+ ) { result. extend ( val) }
208241 remaining -= MAX_KEYCODES_PARTIAL ;
209242 }
210243 }
@@ -217,7 +250,7 @@ impl KeyboardApi {
217250 for i in 0 ..length {
218251 let row = ( i as u16 / matrix_info. cols as u16 ) as u8 ;
219252 let col = ( i as u16 % matrix_info. cols as u16 ) as u8 ;
220- self . get_key ( layer, row, col) . map ( |val| res. push ( val) ) ;
253+ if let Some ( val ) = self . get_key ( layer, row, col) { res. push ( val) }
221254 }
222255 Some ( res)
223256 }
@@ -238,8 +271,7 @@ impl KeyboardApi {
238271 for ( key_idx, keycode) in layer. iter ( ) . enumerate ( ) {
239272 let row = ( key_idx as u16 / matrix_info. cols as u16 ) as u8 ;
240273 let col = ( key_idx as u16 % matrix_info. cols as u16 ) as u8 ;
241- self . set_key ( layer_idx as u8 , row, col, * keycode)
242- . map ( |_| ( ) ) ;
274+ self . set_key ( layer_idx as u8 , row, col, * keycode) ;
243275 }
244276 }
245277 Some ( ( ) )
@@ -257,8 +289,7 @@ impl KeyboardApi {
257289 let buffer = shifted_data[ offset..end] . to_vec ( ) ;
258290 let mut bytes = vec ! [ offset_bytes. 0 , offset_bytes. 1 , buffer. len( ) as u8 ] ;
259291 bytes. extend ( buffer) ;
260- self . hid_command ( ViaCommandId :: DynamicKeymapSetBuffer , bytes)
261- . map ( |_| ( ) ) ;
292+ self . hid_command ( ViaCommandId :: DynamicKeymapSetBuffer , bytes) ;
262293 }
263294 Some ( ( ) )
264295 }
0 commit comments