use std::ffi::CStr;
use std::fmt;
use std::str;
#[derive(Debug)]
pub struct XmpString(*mut c::XmpString);
impl Default for XmpString {
fn default() -> XmpString {
XmpString(unsafe { c::xmp_string_new() })
}
}
impl XmpString {
pub fn new() -> XmpString {
XmpString::default()
}
pub fn is_null(&self) -> bool {
self.0.is_null()
}
pub fn as_ptr(&self) -> *const c::XmpString {
self.0
}
pub fn as_mut_ptr(&mut self) -> *mut c::XmpString {
self.0
}
pub fn len(&self) -> usize {
if self.0.is_null() {
return 0;
}
unsafe { c::xmp_string_len(self.0) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn to_str(&self) -> Result<&str, std::str::Utf8Error> {
unsafe {
let s = CStr::from_ptr(c::xmp_string_cstr(self.0));
str::from_utf8(s.to_bytes())
}
}
}
impl From<&XmpString> for String {
fn from(s: &XmpString) -> String {
unsafe {
let s = CStr::from_ptr(c::xmp_string_cstr(s.0));
String::from_utf8_lossy(s.to_bytes()).to_string()
}
}
}
impl Drop for XmpString {
fn drop(&mut self) {
if !self.is_null() {
unsafe { c::xmp_string_free(self.0) };
}
}
}
impl Eq for XmpString {}
impl PartialEq for XmpString {
fn eq(&self, other: &XmpString) -> bool {
unsafe {
CStr::from_ptr(c::xmp_string_cstr(self.0))
== CStr::from_ptr(c::xmp_string_cstr(other.0))
}
}
}
impl fmt::Display for XmpString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", String::from(self))
}
}
#[cfg(test)]
mod test {
use super::XmpString;
#[test]
fn test_xmpstring() {
let s = XmpString::default();
assert!(!s.is_null());
assert!(s.is_empty());
assert_eq!(s.len(), 0);
let s2 = XmpString::new();
assert_eq!(s, s2);
let string = String::from(&s2);
assert_eq!(string, "".to_owned());
}
}