Skip to content

Commit

Permalink
adds image
Browse files Browse the repository at this point in the history
  • Loading branch information
dcuddeback committed Oct 30, 2015
1 parent 842f02b commit 81a2f3f
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
139 changes: 139 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use std::error::Error as StdError;
use std::ffi::CStr;
use std::fmt;
use std::result::Result as StdResult;

use libc::{c_int};

/// Result type returned by libraw functions.
pub type Result<T> = StdResult<T, Error>;

/// The error type for libraw functions.
#[derive(Debug)]
pub struct Error {
repr: Repr,
message: String,
}

#[derive(Debug)]
enum Repr {
LibRaw(c_int),
Os(i32),
}

impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
fmt.write_str(&self.message)
}
}

impl StdError for Error {
fn description(&self) -> &str {
&self.message
}
}

#[doc(hidden)]
pub fn from_libraw(error: c_int) -> Error {
let message = String::from_utf8_lossy(unsafe {
CStr::from_ptr(::libraw::libraw_strerror(error))
}.to_bytes()).into_owned();

Error {
repr: Repr::LibRaw(error),
message: message,
}
}

#[doc(hidden)]
pub fn from_raw_os_error(errno: i32) -> Error {
Error {
repr: Repr::Os(errno),
message: os::error_string(errno),
}
}


// adapted from libstd
pub mod os {
use std::ffi::CStr;
use std::str;

use libc::{c_char,c_int,size_t};

const TMPBUF_SZ: usize = 128;

#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd"))]
unsafe fn errno_location() -> *mut c_int {
extern { fn __error() -> *mut c_int; }
__error()
}

#[cfg(target_os = "bitrig")]
fn errno_location() -> *mut c_int {
extern {
fn __errno() -> *mut c_int;
}
unsafe {
__errno()
}
}

#[cfg(target_os = "dragonfly")]
unsafe fn errno_location() -> *mut c_int {
extern { fn __dfly_error() -> *mut c_int; }
__dfly_error()
}

#[cfg(target_os = "openbsd")]
unsafe fn errno_location() -> *mut c_int {
extern { fn __errno() -> *mut c_int; }
__errno()
}

#[cfg(any(target_os = "linux", target_os = "android"))]
unsafe fn errno_location() -> *mut c_int {
extern { fn __errno_location() -> *mut c_int; }
__errno_location()
}

pub fn errno() -> i32 {
unsafe {
(*errno_location()) as i32
}
}

pub fn clear_errno() {
unsafe {
(*errno_location()) = 0;
}
}

pub fn error_string(errno: i32) -> String {
#[cfg(target_os = "linux")]
extern {
#[link_name = "__xpg_strerror_r"]
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: size_t) -> c_int;
}
#[cfg(not(target_os = "linux"))]
extern {
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: size_t) -> c_int;
}

let mut buf = [0 as c_char; TMPBUF_SZ];

let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as c_int, p, buf.len() as size_t) < 0 {
panic!("strerror_r failure");
}

let p = p as *const _;
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
}
}
}
57 changes: 57 additions & 0 deletions src/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::ffi::CString;
use std::path::Path;

use std::os::unix::prelude::*;

use libc::{EINVAL,ENOMEM};

/// A raw image.
pub struct Image {
data: *mut ::libraw::libraw_data_t,
}

impl Drop for Image {
fn drop(&mut self) {
unsafe {
::libraw::libraw_close(self.data);
}
}
}

impl Image {
fn new() -> ::Result<Image> {
let data = unsafe {
::libraw::libraw_init(::libraw::LIBRAW_OPIONS_NO_MEMERR_CALLBACK | ::libraw::LIBRAW_OPIONS_NO_DATAERR_CALLBACK)
};

if !data.is_null() {
Ok(Image { data: data })
}
else {
Err(::error::from_raw_os_error(ENOMEM))
}
}

/// Opens the raw image file at the specified path.
pub fn open(path: &Path) -> ::Result<Image> {
let filename = match CString::new(path.as_os_str().as_bytes()) {
Ok(s) => s,
Err(_) => return Err(::error::from_raw_os_error(EINVAL))
};

let image = try!(Image::new());

::error::os::clear_errno();

match unsafe { ::libraw::libraw_open_file(image.data, filename.as_ptr()) } {
::libraw::LIBRAW_SUCCESS => Ok(image),
::libraw::LIBRAW_IO_ERROR => {
match ::error::os::errno() {
0 => Err(::error::from_libraw(::libraw::LIBRAW_IO_ERROR)),
errno => Err(::error::from_raw_os_error(errno)),
}
},
err => Err(::error::from_libraw(err)),
}
}
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ extern crate libraw_sys as libraw;
extern crate libc;

pub use camera::{Cameras,camera_list};
pub use error::{Error,Result};
pub use image::{Image};
pub use version::{Version,version};

mod camera;
mod error;
mod image;
mod version;

0 comments on commit 81a2f3f

Please sign in to comment.