diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index 91a0c02..c097d0b 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -45,8 +45,13 @@ impl Core { } /// Gets device plugins version information. - /// Device name can be complex and identify multiple devices at once like `HETERO:CPU,GPU`; - /// in this case, the returned map contains multiple entries, each per device. + /// + /// A device name can be complex and identify multiple devices at once, like `HETERO:CPU,GPU`. + /// In this case, the returned map contains multiple entries, each per device. + /// + /// # Panics + /// + /// This function panics if OpenVINO returns a device name these bindings do not yet recognize. pub fn versions(&self, device_name: &str) -> Result> { let device_name = cstr!(device_name); let mut ov_version_list = openvino_sys::ov_core_version_list_t { @@ -75,6 +80,10 @@ impl Core { } /// Gets devices available for inference. + /// + /// # Panics + /// + /// This function panics if OpenVINO returns a device name these bindings do not yet recognize. pub fn available_devices(&self) -> Result> { let mut ov_available_devices = openvino_sys::ov_available_devices_t { devices: std::ptr::null_mut(), @@ -101,8 +110,13 @@ impl Core { Ok(devices) } - /// Gets properties related to device behaviour for this core. + /// Gets properties related to device behavior. + /// /// The method extracts information that can be set via the [`set_property`] method. + /// + /// # Panics + /// + /// This function panics in the unlikely case OpenVINO returns a non-UTF8 string. pub fn get_property(&self, device_name: &DeviceType, key: &PropertyKey) -> Result { let ov_device_name = cstr!(device_name.as_ref()); let ov_prop_key = cstr!(key.as_ref()); @@ -142,11 +156,11 @@ impl Core { /// Sets properties for a device. pub fn set_properties<'a>( &mut self, - device_name: DeviceType, + device_name: &DeviceType, properties: impl IntoIterator, ) -> Result<()> { for (prop_key, prop_value) in properties { - self.set_property(&device_name, &prop_key, prop_value)?; + self.set_property(device_name, &prop_key, prop_value)?; } Ok(()) } @@ -177,7 +191,7 @@ impl Core { self.ptr, model_str.as_ptr().cast::(), model_str.len(), - weights_buffer.map_or(std::ptr::null(), |tensor| tensor.as_ptr()), + weights_buffer.map_or(std::ptr::null(), Tensor::as_ptr), std::ptr::addr_of_mut!(ptr) ))?; Ok(Model::from_ptr(ptr)) diff --git a/crates/openvino/src/element_type.rs b/crates/openvino/src/element_type.rs index f08aead..c387e2c 100644 --- a/crates/openvino/src/element_type.rs +++ b/crates/openvino/src/element_type.rs @@ -1,4 +1,12 @@ -use openvino_sys::*; +use openvino_sys::{ + ov_element_type_e_BF16, ov_element_type_e_DYNAMIC, ov_element_type_e_F16, + ov_element_type_e_F32, ov_element_type_e_F64, ov_element_type_e_F8E4M3, + ov_element_type_e_F8E5M3, ov_element_type_e_I16, ov_element_type_e_I32, ov_element_type_e_I4, + ov_element_type_e_I64, ov_element_type_e_I8, ov_element_type_e_NF4, + ov_element_type_e_OV_BOOLEAN, ov_element_type_e_U1, ov_element_type_e_U16, + ov_element_type_e_U32, ov_element_type_e_U4, ov_element_type_e_U64, ov_element_type_e_U8, + ov_element_type_e_UNDEFINED, +}; use std::convert::TryFrom; use std::error::Error; diff --git a/crates/openvino/src/layout.rs b/crates/openvino/src/layout.rs index 46a228c..3a26cc4 100644 --- a/crates/openvino/src/layout.rs +++ b/crates/openvino/src/layout.rs @@ -39,6 +39,6 @@ mod tests { .unwrap(); let layout_desc = "NCHW"; let layout = Layout::new(layout_desc).unwrap(); - assert_eq!(layout.ptr.is_null(), false); + assert!(!layout.ptr.is_null()); } } diff --git a/crates/openvino/src/model.rs b/crates/openvino/src/model.rs index b285930..fe46d72 100644 --- a/crates/openvino/src/model.rs +++ b/crates/openvino/src/model.rs @@ -207,7 +207,7 @@ impl CompiledModel { } /// Gets a property for the compiled model. - pub fn get_property(&self, key: PropertyKey) -> Result> { + pub fn get_property(&self, key: &PropertyKey) -> Result> { let ov_prop_key = cstr!(key.as_ref()); let mut ov_prop_value = std::ptr::null_mut(); try_unsafe!(ov_compiled_model_get_property( @@ -220,7 +220,7 @@ impl CompiledModel { } /// Sets a property for the compiled model. - pub fn set_property(&mut self, key: RwPropertyKey, value: &str) -> Result<()> { + pub fn set_property(&mut self, key: &RwPropertyKey, value: &str) -> Result<()> { let ov_prop_key = cstr!(key.as_ref()); let ov_prop_value = cstr!(value); try_unsafe!(ov_compiled_model_set_property( diff --git a/crates/openvino/src/node.rs b/crates/openvino/src/node.rs index 3bb3971..dea5242 100644 --- a/crates/openvino/src/node.rs +++ b/crates/openvino/src/node.rs @@ -32,6 +32,10 @@ impl Node { } /// Get the data type of elements of the port. + /// + /// # Panics + /// + /// This function panics in the unlikely case OpenVINO returns an unknown element type. pub fn get_element_type(&self) -> Result { let mut element_type = ElementType::Undefined as u32; try_unsafe!(ov_port_get_element_type( diff --git a/crates/openvino/src/property.rs b/crates/openvino/src/property.rs index 24d2ff8..0e88933 100644 --- a/crates/openvino/src/property.rs +++ b/crates/openvino/src/property.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; /// See [`Property`](https://docs.openvino.ai/2024/api/c_cpp_api/group__ov__property__c__api.html). -/// `PropertyKey` represents valid configuration properties for a [crate::Core] instance. +/// `PropertyKey` represents valid configuration properties for a [`crate::Core`] instance. #[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] pub enum PropertyKey { /// A string list of supported read-only properties. @@ -10,8 +10,8 @@ pub enum PropertyKey { AvailableDevices, /// An unsigned integer value of optimal number of compiled model infer requests. OptimalNumberOfInferRequests, - /// A hint for a range for number of async infer requests. - /// If device supports streams, the metric provides range for number of IRs per stream. + /// A hint for a range for number of async infer requests. If a device supports streams, the + /// metric provides the range for number of IRs per stream. RangeForAsyncInferRequests, /// Information about a range for streams on platforms where streams are supported. RangeForStreams, @@ -27,7 +27,7 @@ pub enum PropertyKey { MaxBatchSize, /// Read-write property key. Rw(RwPropertyKey), - /// Arbitrary string property key. + /// An arbitrary key. Other(Cow<'static, str>), } @@ -36,9 +36,9 @@ pub enum PropertyKey { pub enum RwPropertyKey { /// The directory which will be used to store any data cached by plugins. CacheDir, - /// The cache mode between optimize_size and optimize_speed. - /// If optimize_size is selected, smaller cache files will be created. - /// If optimize_speed is selected, loading time will decrease but the cache file size will increase. + /// The cache mode between `optimize_size` and `optimize_speed`. If `optimize_size` is selected, + /// smaller cache files will be created. If `optimize_speed` is selected, loading time will + /// decrease but the cache file size will increase. CacheMode, /// The number of executor logical partitions. NumStreams, @@ -56,10 +56,9 @@ pub enum RwPropertyKey { HintSchedulingCoreType, /// Hint for device to use specified precision for inference. HintInferencePrecision, - /// Backs the Performance Hints by giving - /// additional information on how many inference requests the application will be - /// keeping in flight usually this value comes from the actual use-case (e.g. - /// number of video-cameras, or other sources of inputs) + /// Backs the performance hints by giving additional information on how many inference requests + /// the application will be keeping in flight usually this value comes from the actual use-case + /// (e.g. number of video-cameras, or other sources of inputs) HintNumRequests, /// Desirable log level. LogLevel, @@ -67,17 +66,17 @@ pub enum RwPropertyKey { HintModelPriority, /// Performance counters. EnableProfiling, - /// Device Priorities config option, - /// with comma-separated devices listed in the desired priority. + /// Device priorities configuration, with comma-separated devices listed in the desired + /// priority. DevicePriorities, - /// High-level OpenVINO Execution hint - /// unlike low-level properties that are individual (per-device), the hints are something that every device accepts - /// and turns into device-specific settings - /// Execution mode hint controls preferred optimization targets (performance or accuracy) for given model + /// A high-level OpenVINO execution hint. Unlike low-level properties that are individual + /// (per-device), the hints are something that every device accepts and turns into + /// device-specific settings, the execution mode hint controls preferred optimization targets + /// (performance or accuracy) for a given model. /// /// It can be set to be below value: - /// - `"PERFORMANCE"`: Optimize for max performance - /// - `"ACCURACY"`: Optimize for max accuracy + /// - `"PERFORMANCE"`: optimize for max performance + /// - `"ACCURACY"`: optimize for max accuracy HintExecutionMode, /// Whether to force terminate TBB when OV Core is destroyed. ForceTbbTerminate, @@ -85,7 +84,7 @@ pub enum RwPropertyKey { EnableMmap, /// ? AutoBatchTimeout, - /// Arbitrary string property key. + /// An arbitrary key. Other(Cow<'static, str>), } diff --git a/crates/openvino/src/tensor.rs b/crates/openvino/src/tensor.rs index 012f151..6a295ce 100644 --- a/crates/openvino/src/tensor.rs +++ b/crates/openvino/src/tensor.rs @@ -41,7 +41,7 @@ impl Tensor { } /// (Re)Set the shape of the tensor to a new shape. - pub fn set_shape(&self, shape: Shape) -> Result { + pub fn set_shape(&self, shape: &Shape) -> Result { try_unsafe!(ov_tensor_set_shape(self.ptr, shape.as_c_struct()))?; Ok(Self { ptr: self.ptr }) } @@ -57,6 +57,10 @@ impl Tensor { } /// Get the data type of elements of the tensor. + /// + /// # Panics + /// + /// This function panics in the unlikely case OpenVINO returns an unknown element type. pub fn get_element_type(&self) -> Result { let mut element_type = ElementType::Undefined as u32; try_unsafe!(ov_tensor_get_element_type( @@ -135,12 +139,14 @@ impl Tensor { /// Convenience function for checking that we can cast `data` to a slice of `T`, returning the /// length of that slice. fn get_safe_len(data: &[u8]) -> usize { - if data.len() % std::mem::size_of::() != 0 { - panic!("data size is not a multiple of the size of `T`"); - } - if data.as_ptr() as usize % std::mem::align_of::() != 0 { - panic!("raw data is not aligned to `T`'s alignment"); - } + assert!( + data.len() % std::mem::size_of::() == 0, + "data size is not a multiple of the size of `T`" + ); + assert!( + data.as_ptr() as usize % std::mem::align_of::() == 0, + "raw data is not aligned to `T`'s alignment" + ); data.len() / std::mem::size_of::() } @@ -151,7 +157,7 @@ mod tests { #[test] fn test_create_tensor() { openvino_sys::library::load().unwrap(); - let shape = Shape::new(&vec![1, 3, 227, 227]).unwrap(); + let shape = Shape::new(&[1, 3, 227, 227]).unwrap(); let tensor = Tensor::new(ElementType::F32, &shape).unwrap(); assert!(!tensor.ptr.is_null()); } @@ -159,11 +165,8 @@ mod tests { #[test] fn test_get_shape() { openvino_sys::library::load().unwrap(); - let tensor = Tensor::new( - ElementType::F32, - &Shape::new(&vec![1, 3, 227, 227]).unwrap(), - ) - .unwrap(); + let tensor = + Tensor::new(ElementType::F32, &Shape::new(&[1, 3, 227, 227]).unwrap()).unwrap(); let shape = tensor.get_shape().unwrap(); assert_eq!(shape.get_rank(), 4); } @@ -171,11 +174,8 @@ mod tests { #[test] fn test_get_element_type() { openvino_sys::library::load().unwrap(); - let tensor = Tensor::new( - ElementType::F32, - &Shape::new(&vec![1, 3, 227, 227]).unwrap(), - ) - .unwrap(); + let tensor = + Tensor::new(ElementType::F32, &Shape::new(&[1, 3, 227, 227]).unwrap()).unwrap(); let element_type = tensor.get_element_type().unwrap(); assert_eq!(element_type, ElementType::F32); } @@ -183,34 +183,25 @@ mod tests { #[test] fn test_get_size() { openvino_sys::library::load().unwrap(); - let tensor = Tensor::new( - ElementType::F32, - &Shape::new(&vec![1, 3, 227, 227]).unwrap(), - ) - .unwrap(); + let tensor = + Tensor::new(ElementType::F32, &Shape::new(&[1, 3, 227, 227]).unwrap()).unwrap(); let size = tensor.get_size().unwrap(); - assert_eq!(size, 1 * 3 * 227 * 227); + assert_eq!(size, 3 * 227 * 227); } #[test] fn test_get_byte_size() { openvino_sys::library::load().unwrap(); - let tensor = Tensor::new( - ElementType::F32, - &Shape::new(&vec![1, 3, 227, 227]).unwrap(), - ) - .unwrap(); + let tensor = + Tensor::new(ElementType::F32, &Shape::new(&[1, 3, 227, 227]).unwrap()).unwrap(); let byte_size = tensor.get_byte_size().unwrap(); - assert_eq!( - byte_size, - 1 * 3 * 227 * 227 * std::mem::size_of::() as usize - ); + assert_eq!(byte_size, 3 * 227 * 227 * std::mem::size_of::()); } #[test] fn casting() { openvino_sys::library::load().unwrap(); - let shape = Shape::new(&vec![10, 10, 10]).unwrap(); + let shape = Shape::new(&[10, 10, 10]).unwrap(); let tensor = Tensor::new(ElementType::F32, &shape).unwrap(); let data = tensor.get_data::().unwrap(); assert_eq!(data.len(), 10 * 10 * 10); @@ -220,7 +211,7 @@ mod tests { #[should_panic(expected = "data size is not a multiple of the size of `T`")] fn casting_check() { openvino_sys::library::load().unwrap(); - let shape = Shape::new(&vec![10, 10, 10]).unwrap(); + let shape = Shape::new(&[10, 10, 10]).unwrap(); let tensor = Tensor::new(ElementType::F32, &shape).unwrap(); #[allow(dead_code)] struct LargeOddType([u8; 1061]); diff --git a/crates/openvino/tests/classify-alexnet.rs b/crates/openvino/tests/classify-alexnet.rs index bf06260..5eb5026 100644 --- a/crates/openvino/tests/classify-alexnet.rs +++ b/crates/openvino/tests/classify-alexnet.rs @@ -25,7 +25,7 @@ fn classify_alexnet() -> anyhow::Result<()> { // Retrieve the tensor from the test fixtures. let data = fs::read(Fixture::tensor())?; - let input_shape = Shape::new(&vec![1, 227, 227, 3])?; + let input_shape = Shape::new(&[1, 227, 227, 3])?; let element_type = ElementType::F32; let mut tensor = Tensor::new(element_type, &input_shape)?; let buffer = tensor.get_raw_data_mut()?; @@ -53,7 +53,7 @@ fn classify_alexnet() -> anyhow::Result<()> { let mut infer_request = executable_model.create_infer_request()?; infer_request.set_tensor("data", &tensor)?; infer_request.infer()?; - let mut results = infer_request.get_tensor(&output_port.get_name()?)?; + let results = infer_request.get_tensor(&output_port.get_name()?)?; // Sort results. let buffer = results.get_data::()?.to_vec(); diff --git a/crates/openvino/tests/classify-inception.rs b/crates/openvino/tests/classify-inception.rs index 2f93954..86a2d68 100644 --- a/crates/openvino/tests/classify-inception.rs +++ b/crates/openvino/tests/classify-inception.rs @@ -25,7 +25,7 @@ fn classify_inception() -> anyhow::Result<()> { // Retrieve the tensor from the test fixtures. let data = fs::read(Fixture::tensor())?; - let input_shape = Shape::new(&vec![1, 299, 299, 3])?; + let input_shape = Shape::new(&[1, 299, 299, 3])?; let element_type = ElementType::F32; let mut tensor = Tensor::new(element_type, &input_shape)?; let buffer = tensor.get_raw_data_mut()?; @@ -50,7 +50,7 @@ fn classify_inception() -> anyhow::Result<()> { let mut infer_request = executable_model.create_infer_request()?; infer_request.set_tensor("input", &tensor)?; infer_request.infer()?; - let mut results = infer_request.get_tensor(&output_port.get_name()?)?; + let results = infer_request.get_tensor(&output_port.get_name()?)?; // Sort results. let buffer = results.get_data::()?.to_vec(); diff --git a/crates/openvino/tests/classify-mobilenet.rs b/crates/openvino/tests/classify-mobilenet.rs index e18cb24..d27af58 100644 --- a/crates/openvino/tests/classify-mobilenet.rs +++ b/crates/openvino/tests/classify-mobilenet.rs @@ -25,7 +25,7 @@ fn classify_mobilenet() -> anyhow::Result<()> { // Retrieve the tensor from the test fixtures. let data = fs::read(Fixture::tensor())?; - let input_shape = Shape::new(&vec![1, 224, 224, 3])?; + let input_shape = Shape::new(&[1, 224, 224, 3])?; let element_type = ElementType::F32; let mut tensor = Tensor::new(element_type, &input_shape)?; let buffer = tensor.get_raw_data_mut()?; @@ -53,7 +53,7 @@ fn classify_mobilenet() -> anyhow::Result<()> { let mut infer_request = executable_model.create_infer_request()?; infer_request.set_tensor("input", &tensor)?; infer_request.infer()?; - let mut results = infer_request.get_tensor(&output_port.get_name()?)?; + let results = infer_request.get_tensor(&output_port.get_name()?)?; // Sort results. It is unclear why the MobileNet output indices are "off by one" but the // `.skip(1)` below seems necessary to get results that make sense (e.g. 763 = "revolver" vs 762 diff --git a/crates/xtask/src/codegen.rs b/crates/xtask/src/codegen.rs index 9f39ddf..803a55d 100644 --- a/crates/xtask/src/codegen.rs +++ b/crates/xtask/src/codegen.rs @@ -46,7 +46,7 @@ impl CodegenCommand { let functions_to_modify = vec!["ov_core_set_property", "ov_compiled_model_set_property"]; let mut function_bindings_string = function_bindings.to_string(); for function in &functions_to_modify { - let re = Regex::new(&format!(r"(?s){}.*?\.\.\.", function)).unwrap(); + let re = Regex::new(&format!(r"(?s){function}.*?\.\.\.")).unwrap(); if re.is_match(&function_bindings_string) { function_bindings_string = re.replace(&function_bindings_string, |caps: ®ex::Captures| { caps[0].replace("...", "property_key: *const ::std::os::raw::c_char,\n property_value: *const ::std::os::raw::c_char") diff --git a/crates/xtask/src/publish.rs b/crates/xtask/src/publish.rs index 38aa733..408a658 100644 --- a/crates/xtask/src/publish.rs +++ b/crates/xtask/src/publish.rs @@ -51,7 +51,7 @@ impl PublishCommand { } // Tag the repository. - let tag = format!("v{}", version); + let tag = format!("v{version}"); if self.git { println!("> push Git tag: {tag}"); if !self.dry_run {