From 5e7bc7aa681723f3ab887bc0c5de7bd052cd880b Mon Sep 17 00:00:00 2001 From: Eric Scouten Date: Sat, 16 Jul 2022 22:11:08 -0700 Subject: [PATCH] Introduce new error type `XmpErrorType::NulInRustString` (#68) Use this to remove some `.unwrap()` calls in `XmpMeta`. --- src/tests/xmp_meta.rs | 33 +++++++++++++++++++++++++++++++++ src/xmp_error.rs | 29 +++++++++++++++++++++++------ src/xmp_meta.rs | 10 +++++----- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/tests/xmp_meta.rs b/src/tests/xmp_meta.rs index bc3fc0a..c46ba64 100644 --- a/src/tests/xmp_meta.rs +++ b/src/tests/xmp_meta.rs @@ -144,6 +144,23 @@ mod set_property { assert_eq!(err.error_type, XmpErrorType::BadXPath); assert_eq!(err.debug_message, "Empty property name"); } + + #[test] + fn error_nul_in_name() { + let mut m = XmpMeta::from_file(fixture_path("Purple Square.psd")).unwrap(); + + XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms").unwrap(); + + let err = m + .set_property("http://purl.org/dc/terms/", "x\0x", "blah") + .unwrap_err(); + + assert_eq!(err.error_type, XmpErrorType::NulInRustString); + assert_eq!( + err.debug_message, + "Unable to convert to C string because a NUL byte was found" + ); + } } mod does_property_exist { @@ -200,4 +217,20 @@ mod set_property_date { assert_eq!(err.error_type, XmpErrorType::BadSchema); assert_eq!(err.debug_message, "Empty schema namespace URI"); } + + #[test] + fn error_nul_in_name() { + let mut m = XmpMeta::from_file(fixture_path("Purple Square.psd")).unwrap(); + let updated_time = XmpDateTime::current().unwrap(); + + let err = m + .set_property_date("x\0x", "MetadataDate", &updated_time) + .unwrap_err(); + + assert_eq!(err.error_type, XmpErrorType::NulInRustString); + assert_eq!( + err.debug_message, + "Unable to convert to C string because a NUL byte was found" + ); + } } diff --git a/src/xmp_error.rs b/src/xmp_error.rs index 6de0d8b..1f2a056 100644 --- a/src/xmp_error.rs +++ b/src/xmp_error.rs @@ -11,12 +11,15 @@ // specific language governing permissions and limitations under // each license. -use std::{ffi::CStr, fmt}; - -use num_enum::FromPrimitive; -use thiserror::Error; - -use crate::ffi::CXmpError; +use { + crate::ffi::CXmpError, + num_enum::FromPrimitive, + std::{ + ffi::{CStr, NulError}, + fmt, + }, + thiserror::Error, +}; /// Describes error conditions returned by most XMP Toolkit operations. #[derive(Debug)] @@ -51,6 +54,15 @@ impl XmpError { } } +impl From for XmpError { + fn from(_: NulError) -> Self { + XmpError { + error_type: XmpErrorType::NulInRustString, + debug_message: "Unable to convert to C string because a NUL byte was found".to_owned(), + } + } +} + impl fmt::Display for XmpError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { if self.debug_message.is_empty() { @@ -263,6 +275,11 @@ pub enum XmpErrorType { /// PNG format error. #[error("PNG format error")] BadPng = 213, + + // --- Rust-specific errors --- + /// Can not convert from Rust string to C string because a NUL byte was found. + #[error("Unable to convert to C string because a NUL byte was found")] + NulInRustString = -432, } /// A specialized `Result` type for XMP Toolkit operations. diff --git a/src/xmp_meta.rs b/src/xmp_meta.rs index 81e6dd9..0a1cab4 100644 --- a/src/xmp_meta.rs +++ b/src/xmp_meta.rs @@ -158,9 +158,9 @@ impl XmpMeta { prop_name: &str, prop_value: &str, ) -> XmpResult<()> { - let c_ns = CString::new(schema_ns).unwrap(); - let c_name = CString::new(prop_name).unwrap(); - let c_value = CString::new(prop_value).unwrap(); + let c_ns = CString::new(schema_ns)?; + let c_name = CString::new(prop_name)?; + let c_value = CString::new(prop_value)?; let mut err = ffi::CXmpError::default(); unsafe { @@ -196,8 +196,8 @@ impl XmpMeta { prop_name: &str, prop_value: &XmpDateTime, ) -> XmpResult<()> { - let c_ns = CString::new(schema_ns).unwrap(); - let c_name = CString::new(prop_name).unwrap(); + let c_ns = CString::new(schema_ns)?; + let c_name = CString::new(prop_name)?; let mut err = ffi::CXmpError::default(); unsafe {