From b47ed8ed6b38ea194370c945d408c8cc076a2cd2 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 27 Mar 2023 12:05:13 +0000 Subject: [PATCH] use std::ptr::NonNull for ExifKey --- src/exif.rs | 179 +++++++++++++------------------------------ src/ext/rawhandle.rs | 12 +++ 2 files changed, 67 insertions(+), 124 deletions(-) diff --git a/src/exif.rs b/src/exif.rs index e76106c..5851003 100644 --- a/src/exif.rs +++ b/src/exif.rs @@ -1,5 +1,6 @@ use crate::_exif; pub use crate::_exif::{ExifDataRef, ExifDatumRef, ExifValueRef}; +use crate::ext::rawhandle::AsNonNullPtr; use crate::ext::rawhandle::FromRawHandle; use crate::ext::rawhandle::ToRawHandle; use c_fixed_string::CFixedStr; @@ -23,6 +24,7 @@ use std::ops::DerefMut; use std::ops::Drop; use std::os::raw::c_long; use std::path::Path; +use std::ptr::NonNull; /// Used primarily as identifiers when creating ExifValue #[repr(i32)] @@ -98,7 +100,7 @@ pub enum ExifByteOrder { /// Exif Key
/// See [all available keys](https://exiv2.org/tags.html). pub struct ExifKey { - key: *mut _exif::ExifKey, + key: NonNull<_exif::ExifKey>, } impl TryFrom for ExifKey { @@ -106,10 +108,9 @@ impl TryFrom for ExifKey { fn try_from(value: CString) -> Result { let ptr = value.as_ptr(); let re = unsafe { _exif::exif_create_key_by_key(ptr) }; - if re.is_null() { - return Err(()); - } - Ok(Self { key: re }) + Ok(Self { + key: NonNull::new(re).ok_or(())?, + }) } } @@ -126,25 +127,22 @@ impl TryFrom<&str> for ExifKey { impl Drop for ExifKey { fn drop(&mut self) { - if !self.key.is_null() { - unsafe { _exif::exif_free_key(self.key) }; - } + unsafe { _exif::exif_free_key(self.key.as_ptr()) }; } } impl Clone for ExifKey { fn clone(&self) -> Self { - let key = unsafe { _exif::exif_create_key_by_another(self.key) }; - if key.is_null() { - panic!("Out of memory."); + let key = unsafe { _exif::exif_create_key_by_another(self.key.as_ptr()) }; + Self { + key: NonNull::new(key).expect("Out of memory:"), } - Self { key } } } -impl ToRawHandle<_exif::ExifKey> for ExifKey { - unsafe fn to_raw_handle(&self) -> *mut _exif::ExifKey { - self.key +impl AsNonNullPtr<_exif::ExifKey> for ExifKey { + fn as_non_null(&self) -> &NonNull<_exif::ExifKey> { + &self.key } } @@ -159,162 +157,95 @@ impl ExifKey { let p = p.unwrap(); let ptr = p.as_ptr(); let re = unsafe { _exif::exif_create_key_by_id(id, ptr) }; - if re.is_null() { - return Err(()); - } - Ok(Self { key: re }) + Ok(Self { + key: NonNull::new(re).ok_or(())?, + }) } /// Return the key of the metadatum as a string. /// The key is of the form `familyName.groupName.tagName` /// # Note /// However that the key is not necessarily unique, e.g., an ExifData may contain multiple metadata with the same key. - pub fn key(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_key(self.key) }; + pub fn key(&self) -> String { + let r = unsafe { _exif::exif_get_key_key(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return an identifier for the type of metadata (the first part of the key) - pub fn family_name(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_family_name(self.key) }; + pub fn family_name(&self) -> String { + let r = unsafe { _exif::exif_get_key_family_name(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return the name of the group (the second part of the key) - pub fn group_name(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_group_name(self.key) }; + pub fn group_name(&self) -> String { + let r = unsafe { _exif::exif_get_key_group_name(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return the name of the tag (which is also the third part of the key) - pub fn tag_name(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_tag_name(self.key) }; + pub fn tag_name(&self) -> String { + let r = unsafe { _exif::exif_get_key_tag_name(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return the tag number. - pub fn tag(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_tag_tag(self.key) }; - if r == 65535 { - None - } else { - Some(r) - } + pub fn tag(&self) -> u16 { + unsafe { _exif::exif_get_key_tag_tag(self.key.as_ptr()) } } /// Return a label for the tag. - pub fn tag_label(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_tag_label(self.key) }; + pub fn tag_label(&self) -> String { + let r = unsafe { _exif::exif_get_key_tag_label(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return the tag description. - pub fn tag_desc(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_tag_desc(self.key) }; + pub fn tag_desc(&self) -> String { + let r = unsafe { _exif::exif_get_key_tag_desc(self.key.as_ptr()) }; if r.is_null() { - return None; + panic!("Out of memory."); } let s = unsafe { CStr::from_ptr(r) }; let s = s.to_owned(); unsafe { _exif::exif_free(r as *mut ::std::os::raw::c_void) }; - let s = s.to_str(); - if s.is_err() { - return None; - } - let s = s.unwrap(); - Some(s.to_owned()) + s.to_string_lossy().into_owned() } /// Return the default type id for this tag. pub fn default_typeid(&self) -> Option { - if self.key.is_null() { - return None; - } - let r = unsafe { _exif::exif_get_key_default_type_id(self.key) }; - if r == -1 { - return None; - } - let re = ExifTypeID::from_int(r); - if re.is_err() { - return None; - } - Some(re.unwrap()) + let r = unsafe { _exif::exif_get_key_default_type_id(self.key.as_ptr()) }; + ExifTypeID::from_int(r).ok() } } @@ -701,9 +632,9 @@ impl ExifDataRef { /// No duplicate checks are performed, i.e., it is possible to add multiple metadata with the same key. pub fn add(&mut self, key: &ExifKey, value: &ExifValueRef) -> Result<(), ()> { let data = unsafe { self.to_raw_handle() }; - let k = unsafe { key.to_raw_handle() }; + let k = key.as_ptr(); let v = unsafe { value.to_raw_handle() }; - if k.is_null() || v.is_null() || data.is_null() { + if v.is_null() || data.is_null() { return Err(()); } let r = unsafe { _exif::exif_data_ref_add(data, k, v) }; @@ -1062,23 +993,23 @@ fn test_exif_key() { let k = ExifKey::try_from("Exif.Image.XPTitle"); assert!(k.is_ok()); let k = k.unwrap(); - assert_eq!(Some(String::from("Exif.Image.XPTitle")), k.key()); - assert_eq!(Some(String::from("Exif")), k.family_name()); - assert_eq!(Some(String::from("Image")), k.group_name()); - assert_eq!(Some(String::from("XPTitle")), k.tag_name()); - assert_eq!(Some(40091), k.tag()); - assert_eq!(Some(String::from("Windows Title")), k.tag_label()); + assert_eq!(String::from("Exif.Image.XPTitle"), k.key()); + assert_eq!(String::from("Exif"), k.family_name()); + assert_eq!(String::from("Image"), k.group_name()); + assert_eq!(String::from("XPTitle"), k.tag_name()); + assert_eq!(40091, k.tag()); + assert_eq!(String::from("Windows Title"), k.tag_label()); assert_eq!( - Some(String::from("Title tag used by Windows, encoded in UCS2")), + String::from("Title tag used by Windows, encoded in UCS2"), k.tag_desc() ); assert_eq!(Some(ExifTypeID::BYTE), k.default_typeid()); let k2 = ExifKey::from_id(40091, "Image"); assert!(k2.is_ok()); let k2 = k2.unwrap(); - assert_eq!(Some(String::from("Exif.Image.XPTitle")), k2.key()); + assert_eq!(String::from("Exif.Image.XPTitle"), k2.key()); let k3 = k2.clone(); - assert_eq!(Some(String::from("Exif.Image.XPTitle")), k3.key()); + assert_eq!(String::from("Exif.Image.XPTitle"), k3.key()); } #[test] diff --git a/src/ext/rawhandle.rs b/src/ext/rawhandle.rs index c4e8dd0..365ff7e 100644 --- a/src/ext/rawhandle.rs +++ b/src/ext/rawhandle.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + /// Return raw pointer of the handle pub trait ToRawHandle { /// Return raw pointer of the handle @@ -9,6 +11,16 @@ pub trait ToRawHandle { } } +/// Return a Non null Pointer +pub trait AsNonNullPtr { + /// Return a [NonNull] + fn as_non_null(&self) -> &NonNull; + /// Return a non null pointer + fn as_ptr(&self) -> *mut T { + self.as_non_null().as_ptr() + } +} + pub trait FromRawHandle { unsafe fn from_raw_handle<'a>(ptr: *mut T) -> &'a mut Self; unsafe fn from_const_handle<'a>(ptr: *const T) -> &'a Self;