diff --git a/secret-sys/src/lib.rs b/secret-sys/src/lib.rs index 5acc03f..d8d9a8e 100644 --- a/secret-sys/src/lib.rs +++ b/secret-sys/src/lib.rs @@ -2,8 +2,9 @@ extern crate libc; extern crate glib; -use libc::{c_uint, c_char, c_int, c_ulong, c_long}; -use glib::ffi::{GError, GType, GList, gboolean, gsize, gpointer, GHashTable}; +use libc::{c_uint, c_char, c_int, c_ulong, c_long, size_t}; +use glib::ffi::{GError, GType, GList, gboolean, gpointer, GHashTable}; +type gsize = size_t; //glib stuff not provided by glib-rs pub type gchar = c_char; @@ -11,15 +12,18 @@ pub type gint = c_int; pub type guint = c_uint; pub type guint64 = c_ulong; pub type gssize = c_long; -#[repr(C)] pub struct GCancellable; +#[repr(C)] pub struct GCancellable { private: [u8; 0] } //libsecret -#[repr(C)] pub struct SecretService; -#[repr(C)] pub struct SecretSchema; -#[repr(C)] pub struct SecretCollection; -#[repr(C)] pub struct SecretItem; -#[repr(C)] pub struct SecretValue; +#[repr(C)] pub struct SecretService { private: [u8; 0] } +#[repr(C)] pub struct SecretServiceClass { private: [u8; 0] } +#[repr(C)] pub struct SecretSchema { private: [u8; 0] } +#[repr(C)] pub struct SecretCollection { private: [u8; 0] } +#[repr(C)] pub struct SecretCollectionClass { private: [u8; 0] } +#[repr(C)] pub struct SecretItem { private: [u8; 0] } +#[repr(C)] pub struct SecretItemClass { private: [u8; 0] } +#[repr(C)] pub struct SecretValue { private: [u8; 0] } #[link(name="secret-1")] extern "C" { diff --git a/src/lib.rs b/src/lib.rs index f163a2a..1c28693 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,20 +18,20 @@ mod secret_item; mod secret_value; mod util; -pub use self::secret_sys as ffi; +use self::secret_sys as ffi; pub use self::secret_service::SecretService; pub use self::secret_collection::SecretCollection; pub use self::secret_item::SecretItem; pub use self::secret_value::SecretValue; use glib::Error; -use glib::object::Wrapper; +use glib::object::ObjectType; /// A Result which may contain an error from the SecretService backend. pub type SecretResult = Result; /// This Trait is implemented by objects which can be locked and unlocked -pub trait Lock { +pub trait Lock { /// Lock the object. fn lock(&self) -> SecretResult>; diff --git a/src/secret_collection.rs b/src/secret_collection.rs index 0551d6b..bc57e18 100644 --- a/src/secret_collection.rs +++ b/src/secret_collection.rs @@ -1,9 +1,6 @@ use std::ptr; -use glib::Error; -use glib::object::{Object, Upcast, Wrapper, Ref}; -use glib::types::{StaticType, Type}; use glib::translate::*; -use glib::glib_container::GlibContainer; +use glib::wrapper; use secret_service::SecretService; use secret_item::SecretItem; use SecretResult; @@ -11,13 +8,19 @@ use util::{lock_object, unlock_object}; use Lock; use ffi; -/// SecretCollection represents a collection of secret items stored in the -/// Secret Service. -/// A collection can be in a locked or unlocked state. Use `Lock::lock()` or -/// `Lock::unlock()` to lock or unlock the collection. -/// Use `get_items()` to lookup the items in the collection. There may not be -/// any items exposed when the collection is locked. -pub struct SecretCollection(Ref); +wrapper! { + /// SecretCollection represents a collection of secret items stored in the + /// Secret Service. + /// A collection can be in a locked or unlocked state. Use `Lock::lock()` or + /// `Lock::unlock()` to lock or unlock the collection. + /// Use `get_items()` to lookup the items in the collection. There may not be + /// any items exposed when the collection is locked. + pub struct SecretCollection(Object); + + match fn { + type_ => || ffi::secret_collection_get_type(), + } +} impl SecretCollection { @@ -42,7 +45,11 @@ impl SecretCollection { } ) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -68,9 +75,13 @@ impl SecretCollection { unsafe { from_glib_full(ptr) } - ) + ) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -88,7 +99,11 @@ impl SecretCollection { if err.is_null(){ Ok(()) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -167,7 +182,7 @@ impl SecretCollection { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -187,7 +202,7 @@ impl SecretCollection { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -199,32 +214,7 @@ impl SecretCollection { self.to_glib_none().0 ) }; - from_glib(gbool) - } -} - -impl StaticType for SecretCollection { - fn static_type() -> Type{ - unsafe { - from_glib(ffi::secret_collection_get_type()) - } - } -} - -unsafe impl Upcast for SecretCollection { } - -impl Wrapper for SecretCollection { - type GlibType = ffi::SecretCollection; - unsafe fn wrap(r: Ref) -> Self{ - SecretCollection(r) - } - - fn as_ref(&self) -> &Ref{ - &self.0 - } - - fn unwrap(self) -> Ref{ - self.0 + unsafe { from_glib(gbool) } } } @@ -262,9 +252,9 @@ mod test { #[test] pub fn test_sc_static_type() { - match SecretCollection::static_type() { - Type::Other(_) => {}, - _ => panic!("Expected Type::Other") - } + let type_ = SecretCollection::static_type(); + assert!(type_.is_valid()); + assert!(type_ > Type::OBJECT); + assert_eq!(type_.name(), "SecretCollection"); } } diff --git a/src/secret_item.rs b/src/secret_item.rs index 08be80c..4bcff44 100644 --- a/src/secret_item.rs +++ b/src/secret_item.rs @@ -1,10 +1,7 @@ use std::ptr; use std::collections::HashMap; -use glib::Error; -use glib::glib_container::GlibContainer; -use glib::object::{Wrapper, Ref, Object, Upcast}; -use glib::types::{StaticType, Type}; use glib::translate::*; +use glib::wrapper; use secret_service::SecretService; use secret_collection::SecretCollection; use secret_value::SecretValue; @@ -13,22 +10,28 @@ use ffi; use util::{lock_object, unlock_object}; use Lock; -/// SecretItem represents a secret item stored in the Secret Service. -/// Each item has a value, represented by a SecretValue, which can be retrieved -/// by `get_secret()` or set by `set_secret()`. The item is only available when -/// the item is not locked. -/// Items can be locked or unlocked using the `Lock::lock()` or `Lock::unlock()` -/// functions. The Lock trait is implemented by SecretItem. The Secret Service -/// may not be able to unlock individual items, and may unlock an entire -/// collection when a single item is unlocked. -/// Each item has a set of attributes, which are used to locate the item later. -/// These are not stored or transferred in a secure manner. Each attribute has -/// a string name and a string value. Use `SecretService::search()` to search -/// for items based on their attributes, and `set_attributes()` to change the -/// attributes associated with an item. -/// Items can be created with `create()` or `SecretService::store()`. -/// -pub struct SecretItem(Ref); +wrapper! { + /// SecretItem represents a secret item stored in the Secret Service. + /// Each item has a value, represented by a SecretValue, which can be retrieved + /// by `get_secret()` or set by `set_secret()`. The item is only available when + /// the item is not locked. + /// Items can be locked or unlocked using the `Lock::lock()` or `Lock::unlock()` + /// functions. The Lock trait is implemented by SecretItem. The Secret Service + /// may not be able to unlock individual items, and may unlock an entire + /// collection when a single item is unlocked. + /// Each item has a set of attributes, which are used to locate the item later. + /// These are not stored or transferred in a secure manner. Each attribute has + /// a string name and a string value. Use `SecretService::search()` to search + /// for items based on their attributes, and `set_attributes()` to change the + /// attributes associated with an item. + /// Items can be created with `create()` or `SecretService::store()`. + /// + pub struct SecretItem(Object); + + match fn { + type_ => || ffi::secret_item_get_type(), + } +} impl SecretItem { @@ -54,7 +57,7 @@ impl SecretItem { if err.is_null() { //TODO for all patterns like this: This if does not need to be in the unsafe block. Fix pls. Ok(from_glib_full(item)) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -72,7 +75,11 @@ impl SecretItem { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -129,7 +136,11 @@ impl SecretItem { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -161,7 +172,7 @@ impl SecretItem { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -188,7 +199,7 @@ impl SecretItem { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -198,32 +209,7 @@ impl SecretItem { let gbool = unsafe { ffi::secret_item_get_locked(self.to_glib_none().0) }; - from_glib(gbool) - } -} - -impl StaticType for SecretItem { - fn static_type() -> Type{ - unsafe { - from_glib(ffi::secret_item_get_type()) - } - } -} - -unsafe impl Upcast for SecretItem { } - -impl Wrapper for SecretItem { - type GlibType = ffi::SecretItem; - unsafe fn wrap(r: Ref) -> Self{ - SecretItem(r) - } - - fn as_ref(&self) -> &Ref{ - &self.0 - } - - fn unwrap(self) -> Ref{ - self.0 + unsafe { from_glib(gbool) } } } diff --git a/src/secret_service.rs b/src/secret_service.rs index 921de83..7ae85ac 100644 --- a/src/secret_service.rs +++ b/src/secret_service.rs @@ -10,29 +10,32 @@ pub use secret_value::*; //========================================================================= use std::ptr; use std::collections::HashMap; -use glib::Error; -use glib::glib_container::GlibContainer; -use glib::object::{Ref, Wrapper, Object, Upcast}; -use glib::types::{StaticType, Type}; use glib::translate::*; +use glib::wrapper; use SecretResult; use ffi; -/// A SecretService object represents the Secret Service implementation which -/// runs as a D-Bus service. -/// In order to securely transfer secrets to the Sercret Service, a session is -/// established. This will automatically be done when calling -/// `SecretService::get()` -/// To search for items, use the `search()` method. -/// Multiple collections can exist in the Secret Service, each of which -/// contains secret items. To access the list of Collections, use -/// `get_collections()`. -/// Certain actions on the Secret Service require user prompting to complete, -/// such as creating a collection, or unlocking a collection. When such a -/// prompt is necessary, then a SecretPrompt object is created by libsecret, -/// and passed to the secret_service_prompt() method. In this way it is handled -/// automatically. -pub struct SecretService(Ref); +wrapper! { + /// A SecretService object represents the Secret Service implementation which + /// runs as a D-Bus service. + /// In order to securely transfer secrets to the Sercret Service, a session is + /// established. This will automatically be done when calling + /// `SecretService::get()` + /// To search for items, use the `search()` method. + /// Multiple collections can exist in the Secret Service, each of which + /// contains secret items. To access the list of Collections, use + /// `get_collections()`. + /// Certain actions on the Secret Service require user prompting to complete, + /// such as creating a collection, or unlocking a collection. When such a + /// prompt is necessary, then a SecretPrompt object is created by libsecret, + /// and passed to the secret_service_prompt() method. In this way it is handled + /// automatically. + pub struct SecretService(Object); + + match fn { + type_ => || ffi::secret_service_get_type(), + } +} impl SecretService { @@ -52,7 +55,11 @@ impl SecretService { if err.is_null() { Ok(unsafe{from_glib_full(ptr)}) } else { - Err(Error::wrap(err)) + Err( + unsafe { + from_glib_full(err) + } + ) } } @@ -110,7 +117,7 @@ impl SecretService { if err.is_null() { Ok(Vec::from_glib_full(glist)) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -140,7 +147,7 @@ impl SecretService { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -166,7 +173,7 @@ impl SecretService { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -183,7 +190,7 @@ impl SecretService { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } @@ -200,38 +207,12 @@ impl SecretService { if err.is_null() { Ok(()) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } } -unsafe impl Upcast for SecretService { } - -impl StaticType for SecretService { - fn static_type() -> Type{ - unsafe { - from_glib(ffi::secret_service_get_type()) - } - } -} - -impl Wrapper for SecretService { - type GlibType = ffi::SecretService; - - unsafe fn wrap(r: Ref) -> Self{ - SecretService(r) - } - - fn as_ref(&self) -> &Ref{ - &self.0 - } - - fn unwrap(self) -> Ref{ - self.0 - } -} - #[allow(dead_code)] const SECRET_SERVICE_NONE: i32 = 0; const SECRET_SERVICE_OPEN_SESSION: i32 = 1 << 1; @@ -267,10 +248,10 @@ mod test { #[test] pub fn test_ss_static_type() { - match SecretService::static_type() { - Type::Other(_) => {}, - _ => panic!("Expected Type::Other") - } + let type_ = SecretService::static_type(); + assert!(type_.is_valid()); + assert!(type_ > Type::OBJECT); + assert_eq!(type_.name(), "SecretService"); } #[test] diff --git a/src/util.rs b/src/util.rs index 1615a0e..8fc0600 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,25 +1,27 @@ use std::ptr; -use glib::Error; -use glib::ffi::{GList}; -use glib::object::{Wrapper}; -use glib::translate::{ToGlibPtr, FromGlibPtrContainer}; -use glib::glib_container::GlibContainer; +use glib::ffi::GList; +use glib::translate::*; use glib::types::StaticType; use secret_item::SecretItem; use secret_collection::SecretCollection; use ffi; use SecretResult; -pub fn lock_object(obj: &W) -> SecretResult>{ +pub fn lock_object(obj: &W) -> SecretResult> +where + W: StaticType + GlibPtrDefault, + W: FromGlibPtrFull + FromGlibPtrNone, + for<'a> W: ToGlibPtr<'a, W::GlibType> +{ debug_assert!(W::static_type() == SecretItem::static_type() || W::static_type() == SecretCollection::static_type(), "Can only lock items or collections"); let mut err = ptr::null_mut(); let mut res = ptr::null_mut(); let arr = [obj]; - let slice = (&arr[..]).to_glib_none(); + let slice: Stash<'_, *mut GList, [&W]> = (&arr[..]).to_glib_none(); unsafe { ffi::secret_service_lock_sync( ptr::null_mut(), - slice.0 as *mut GList, + slice.0, ptr::null_mut(), &mut res, &mut err @@ -27,21 +29,26 @@ pub fn lock_object(obj: &W) -> SecretResult>{ if err.is_null() { Ok(Vec::from_glib_full(res)) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } } -pub fn unlock_object(obj: &W) -> SecretResult>{ +pub fn unlock_object(obj: &W) -> SecretResult> +where + W: StaticType + GlibPtrDefault, + W: FromGlibPtrFull + FromGlibPtrNone, + for<'a> W: ToGlibPtr<'a, W::GlibType> +{ debug_assert!(W::static_type() == SecretItem::static_type() || W::static_type() == SecretCollection::static_type(), "Can only unlock items or collections"); let mut err = ptr::null_mut(); let mut res = ptr::null_mut(); let arr = [obj]; - let slice = (&arr[..]).to_glib_none(); + let slice: Stash<'_, *mut GList, [&W]> = (&arr[..]).to_glib_none(); unsafe { ffi::secret_service_unlock_sync( ptr::null_mut(), - slice.0 as *mut GList, + slice.0, ptr::null_mut(), &mut res, &mut err @@ -49,7 +56,7 @@ pub fn unlock_object(obj: &W) -> SecretResult>{ if err.is_null() { Ok(Vec::from_glib_full(res)) } else { - Err(Error::wrap(err)) + Err(from_glib_full(err)) } } }