1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use std::error; use std::ffi::CStr; use std::fmt; use std::io; use std::io::prelude::*; use std::str::Utf8Error; use libc; use ffi; use error::Error; macro_rules! try_opt { ($e:expr) => (match $e { Some(v) => v, None => return None }); } macro_rules! list_iterator { ($item:ty, $constructor:path) => { type Item = $item; fn next(&mut self) -> Option<Self::Item> { let current = self.current; if !current.is_null() { unsafe { self.current = (*current).next; Some($constructor(current)) } } else { None } } }; ($item:ty) => (list_iterator!($item, $item::from_raw)); } macro_rules! ffi_enum_wrapper { ($(#[$Attr:meta])* pub enum $Name:ident: $T:ty { $($(#[$ItemAttr:meta])* $Item:ident = $Value:expr),+ }) => { #[derive(Copy, Clone, Eq, PartialEq, Hash)] $(#[$Attr])* pub struct $Name($T); $(pub const $Item: $Name = $Name($Value as $T);)+ impl $Name { pub unsafe fn from_raw(raw: $T) -> $Name { $Name(raw) } pub fn raw(&self) -> $T { self.0 } } impl ::std::fmt::Debug for $Name { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { $($Item => write!(f, concat!(stringify!($Item), "({:?})"), self.0),)+ _ => write!(f, concat!(stringify!($Name), "({:?})"), self.0), } } } }; ($(#[$Attr:meta])* pub enum $Name:ident: $T:ty { $($(#[$ItemAttr:meta])* $Item:ident = $Value:expr,)+ }) => { ffi_enum_wrapper! { $(#[$Attr])* pub enum $Name: $T { $($(#[$ItemAttr])* $Item = $Value),+ } } }; } #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum StrError<'a> { NotPresent, NotUtf8(&'a CStr, Utf8Error), } pub type StrResult<'a> = Result<&'a str, StrError<'a>>; impl<'a> fmt::Display for StrError<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { StrError::NotPresent => write!(f, "no string present"), StrError::NotUtf8(ref s, _) => { write!(f, "string was not valid utf-8: {:?}", s) } } } } impl<'a> error::Error for StrError<'a> { fn description(&self) -> &str { match *self { StrError::NotPresent => "no string present", StrError::NotUtf8(..) => "string was not valid utf-8", } } } pub unsafe fn from_cstr<'a>(s: *const libc::c_char) -> StrResult<'a> { if !s.is_null() { let s = CStr::from_ptr(s); s.to_str().map_err(|e| StrError::NotUtf8(s, e)) } else { Err(StrError::NotPresent) } } pub struct FdWriter { fd: libc::c_int, } impl FdWriter { pub unsafe fn new(fd: libc::c_int) -> FdWriter { FdWriter { fd: fd } } } impl Write for FdWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { let result = unsafe { ffi::gpgme_io_write(self.fd, buf.as_ptr() as *const _, buf.len() as libc::size_t) }; if result >= 0 { Ok(result as usize) } else { Err(Error::last_os_error().into()) } } fn flush(&mut self) -> io::Result<()> { Ok(()) } }