From fa615fb1bbadea3e8b503d0e65730d138032e240 Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Wed, 3 Oct 2018 15:22:48 +0200 Subject: [PATCH] Add ObjectName wrapper to solve hashing issues --- rust-bindings/rust/libostree/src/lib.rs | 3 + .../rust/libostree/src/object_name.rs | 59 +++++++++++++++++++ rust-bindings/rust/libostree/src/repo.rs | 18 +++--- rust-bindings/rust/sample/src/main.rs | 24 ++++---- 4 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 rust-bindings/rust/libostree/src/object_name.rs diff --git a/rust-bindings/rust/libostree/src/lib.rs b/rust-bindings/rust/libostree/src/lib.rs index cca9c9ca..62dafff9 100644 --- a/rust-bindings/rust/libostree/src/lib.rs +++ b/rust-bindings/rust/libostree/src/lib.rs @@ -20,6 +20,9 @@ pub use auto::functions::*; mod repo; +mod object_name; +pub use object_name::ObjectName; + // public modules pub mod prelude { pub use auto::traits::*; diff --git a/rust-bindings/rust/libostree/src/object_name.rs b/rust-bindings/rust/libostree/src/object_name.rs new file mode 100644 index 00000000..05246631 --- /dev/null +++ b/rust-bindings/rust/libostree/src/object_name.rs @@ -0,0 +1,59 @@ +use ffi; +use functions::object_name_deserialize; +use glib; +use glib_ffi; +use glib::translate::*; +use ObjectType; +use std::fmt::Display; +use std::fmt::Error; +use std::fmt::Formatter; +use std::hash::Hash; +use std::hash::Hasher; +use functions::object_to_string; + +fn hash_object_name(v: &glib::Variant) -> u32 { + unsafe { ffi::ostree_hash_object_name(v.to_glib_none().0 as glib_ffi::gconstpointer) } +} + +#[derive(PartialEq, Eq, Debug)] +pub struct ObjectName { + variant: glib::Variant, + checksum: String, + object_type: ObjectType, +} + +impl ObjectName { + pub fn new(variant: glib::Variant) -> ObjectName { + let deserialize = object_name_deserialize(&variant); + ObjectName { + variant, + checksum: deserialize.0, + object_type: deserialize.1, + } + } + + pub fn checksum(&self) -> &str { + self.checksum.as_ref() + } + + pub fn object_type(&self) -> ObjectType { + self.object_type + } + + pub fn name(&self) -> String { + object_to_string(self.checksum(), self.object_type()) + .expect("type checks should make this safe") + } +} + +impl Display for ObjectName { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "{}", self.name()) + } +} + +impl Hash for ObjectName { + fn hash(&self, state: &mut H) { + state.write_u32(hash_object_name(&self.variant)); + } +} diff --git a/rust-bindings/rust/libostree/src/repo.rs b/rust-bindings/rust/libostree/src/repo.rs index 5bce9fe0..272c9002 100644 --- a/rust-bindings/rust/libostree/src/repo.rs +++ b/rust-bindings/rust/libostree/src/repo.rs @@ -8,19 +8,19 @@ use glib::translate::*; use glib_ffi; use std::collections::HashSet; use std::ptr; - +use ObjectName; unsafe extern "C" fn read_variant_table(_key: glib_ffi::gpointer, value: glib_ffi::gpointer, hash_set: glib_ffi::gpointer) { let value: glib::Variant = from_glib_none(value as *const glib_ffi::GVariant); // TODO: this set is degenerate because g_variant_hash for my Variants is always 0 - let set: &mut HashSet = &mut *(hash_set as *mut HashSet); - set.insert(value); + let set: &mut HashSet = &mut *(hash_set as *mut HashSet); + set.insert(ObjectName::new(value)); } -unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> HashSet { +unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> HashSet { let mut set = HashSet::new(); - glib_ffi::g_hash_table_foreach(ptr, Some(read_variant_table), &mut set as *mut HashSet as *mut _); + glib_ffi::g_hash_table_foreach(ptr, Some(read_variant_table), &mut set as *mut HashSet as *mut _); glib_ffi::g_hash_table_unref(ptr); set } @@ -28,11 +28,11 @@ unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> Has pub trait RepoExtManual { fn new_for_str(path: &str) -> Repo; - fn traverse_commit_manual<'a, P: Into>>( + fn traverse_commit<'a, P: Into>>( &self, commit_checksum: &str, maxdepth: i32, - cancellable: P) -> Result, Error>; + cancellable: P) -> Result, Error>; } impl + IsA + Clone + 'static> RepoExtManual for O { @@ -40,12 +40,12 @@ impl + IsA + Clone + 'static> RepoExtManual for O { Repo::new(&gio::File::new_for_path(path)) } - fn traverse_commit_manual<'a, P: Into>>( + fn traverse_commit<'a, P: Into>>( &self, commit_checksum: &str, maxdepth: i32, cancellable: P, - ) -> Result, Error> { + ) -> Result, Error> { unsafe { let mut error = ptr::null_mut(); let mut hashtable = ptr::null_mut(); diff --git a/rust-bindings/rust/sample/src/main.rs b/rust-bindings/rust/sample/src/main.rs index e6da49e1..a42d52ac 100644 --- a/rust-bindings/rust/sample/src/main.rs +++ b/rust-bindings/rust/sample/src/main.rs @@ -21,25 +21,21 @@ fn main() { println!("sha256: {}", checksum); - let objs = repo.traverse_commit_manual(checksum.as_str(), -1, None).unwrap(); + let objs = repo.traverse_commit(checksum.as_str(), -1, None).unwrap(); for obj in objs { - let (name, obj_type) = libostree::object_name_deserialize(&obj); - println!(" {}", libostree::object_to_string(name.as_str(), obj_type).unwrap()); + //let (name, obj_type) = libostree::object_name_deserialize(&obj); + println!(" {}", obj.name()); - let (stream, size) = repo.load_object_stream(obj_type, name.as_str(), None).unwrap(); + let (stream, size) = repo.load_object_stream(obj.object_type(), obj.checksum(), None).unwrap(); println!(" bytes: {}", size); - if obj_type == libostree::ObjectType::File { - let mut file = File::create("./object.file").unwrap(); - let mut read = 1; - let mut buffer = [0 as u8; 4096]; - while read != 0 { - read = stream.read(buffer.as_mut(), None).unwrap(); - file.write(&buffer[0 .. read]); - } + let mut file = File::create(obj.name()).unwrap(); + let mut read = 1; + let mut buffer = [0 as u8; 4096]; + while read != 0 { + read = stream.read(buffer.as_mut(), None).unwrap(); + file.write(&buffer[0 .. read]).unwrap(); } - - //println!("{:?}", obj.type_()); } }