libopenraw 0.1.2

Rust API bindings for libopenraw
Documentation
/*
 * libopenraw-rs
 *
 * Copyright (C) 2021-2022 Hubert Figuière
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

use std::borrow::Cow;
use std::ffi::CStr;

use ffi::or_ifd_dir_type;
use libopenraw_sys as ffi;

#[repr(u32)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DirType {
    Other = or_ifd_dir_type::OR_IFD_OTHER as u32,
    Main = or_ifd_dir_type::OR_IFD_MAIN as u32,
    Exif = or_ifd_dir_type::OR_IFD_EXIF as u32,
    MNote = or_ifd_dir_type::OR_IFD_MNOTE as u32,
    Raw = or_ifd_dir_type::OR_IFD_RAW as u32,
    SubIfd = or_ifd_dir_type::OR_IFD_SUBIFD as u32,
    Invalid = or_ifd_dir_type::OR_IFD_INVALID as u32,
}

impl From<DirType> for ffi::or_ifd_dir_type {
    fn from(t: DirType) -> Self {
        match t {
            DirType::Other => or_ifd_dir_type::OR_IFD_OTHER,
            DirType::Main => or_ifd_dir_type::OR_IFD_MAIN,
            DirType::Exif => or_ifd_dir_type::OR_IFD_EXIF,
            DirType::MNote => or_ifd_dir_type::OR_IFD_MNOTE,
            DirType::Raw => or_ifd_dir_type::OR_IFD_RAW,
            DirType::SubIfd => or_ifd_dir_type::OR_IFD_SUBIFD,
            DirType::Invalid => or_ifd_dir_type::OR_IFD_INVALID,
        }
    }
}

impl From<ffi::or_ifd_dir_type> for DirType {
    fn from(t: ffi::or_ifd_dir_type) -> Self {
        match t {
            or_ifd_dir_type::OR_IFD_OTHER => Self::Other,
            or_ifd_dir_type::OR_IFD_MAIN => Self::Main,
            or_ifd_dir_type::OR_IFD_EXIF => Self::Exif,
            or_ifd_dir_type::OR_IFD_MNOTE => Self::MNote,
            or_ifd_dir_type::OR_IFD_RAW => Self::Raw,
            or_ifd_dir_type::OR_IFD_SUBIFD => Self::SubIfd,
            or_ifd_dir_type::OR_IFD_INVALID => Self::Invalid,
        }
    }
}

pub struct Ifd(ffi::ORIfdDirRef);

impl Ifd {
    /// New `Ifd`
    pub(crate) fn new(ifd: ffi::ORIfdDirRef) -> Self {
        Self(ifd)
    }

    /// Count tags in `Ifd`.
    pub fn count_tags(&self) -> i32 {
        unsafe { ffi::or_ifd_count_tags(self.0) }
    }

    /// Get MakerNote id.
    pub fn get_makernote_id(&self) -> Cow<str> {
        let id = unsafe { CStr::from_ptr(ffi::or_ifd_get_makernote_id(self.0)) };
        id.to_string_lossy()
    }

    /// Get tag name for `tag`.
    pub fn get_tag_name(&self, tag: u32) -> Cow<str> {
        let name = unsafe { CStr::from_ptr(ffi::or_ifd_get_tag_name(self.0, tag)) };
        name.to_string_lossy()
    }
}

impl Drop for Ifd {
    fn drop(&mut self) {
        unsafe { ffi::or_ifd_release(self.0) };
    }
}