From: Hwankyu Jhun Date: Tue, 13 Aug 2024 09:28:05 +0000 (+0900) Subject: Separate packages from rust-tizen-base X-Git-Tag: accepted/tizen/unified/20240814.180345~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=df883bef2f26f7622e8f21ffe69cd934b4427bcf;p=platform%2Fcore%2Fbase%2Fbundle.git Separate packages from rust-tizen-base The following packages are separated: - rust-tizen-bundle (crate: tizen_base) - rust-tizen-parcel (crate: tizen_parcel) Change-Id: I7172142b2535e1be0730dfdd00a2f0ec7572e22a Signed-off-by: Hwankyu Jhun --- diff --git a/packaging/bundle.spec b/packaging/bundle.spec index e09f952..b46c8ce 100644 --- a/packaging/bundle.spec +++ b/packaging/bundle.spec @@ -20,10 +20,10 @@ BuildRequires: rust-libc BuildRequires: rust-glib-sys BuildRequires: rust-mockall BuildRequires: rust-mockall_double -BuildRequires: zip %if 0%{?gcov:1} BuildRequires: lcov +BuildRequires: zip %endif %description @@ -128,20 +128,31 @@ Group: Development/Libraries GTest for tizen-shared-queue ################################################# -# rust-tizen-base +# rust-tizen-bundle +################################################# +%package -n rust-tizen-bundle +Summary: Bundle Library for Tizen rust applications +Group: Development/Libraries + +%description -n rust-tizen-bundle +Bundle Library for Tizen rust applications + +################################################# +# rust-tizen-parcel ################################################# -%package -n rust-tizen-base -Summary: Library for Tizen rust applications +%package -n rust-tizen-parcel +Summary: Parcel Library for Tizen rust applications Group: Development/Libraries -%description -n rust-tizen-base -Libraries for Tizen rust applications +%description -n rust-tizen-parcel +parcel Library for Tizen rust applications %prep %setup -q -n %{name}-%{version} cp %{SOURCE1001} . cp %{SOURCE1002} . -cp %{SOURCE1001} ./rust-tizen-base.manifest +cp %{SOURCE1001} ./rust-tizen-bundle.manifest +cp %{SOURCE1001} ./rust-tizen-parcel.manifest %build %if 0%{?gcov:1} @@ -154,37 +165,51 @@ export LDFLAGS+=" -lgcov" MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake -DFULLVER=%{version} \ -DMAJORVER=${MAJORVER} \ - -DRUST_LIBDIR=%{_rust_libdir} \ - -DRUST_DYLIBDIR=%{_rust_dylibdir} \ - -DCMAKE_BUILD_TYPE=%{?build_type:%build_type} \ . %__make %{?_smp_mflags} %{rustc_std_build} --crate-type=dylib \ - --crate-name=tizen_base \ - -L native="./src/parcel" \ + --crate-name=tizen_bundle \ -L native="./src/bundle" \ %{?rustc_edition:--edition=%{rustc_edition}} \ %rust_dylib_extern libc \ - src/rust-tizen-base/src/lib.rs + src/rust-tizen-bundle/src/lib.rs %{rustc_std_build} --test --crate-type=bin \ - --crate-name=tizen_base_unittests \ - -L native="./src/parcel" \ + --crate-name=tizen_bundle_unittests \ -L native="./src/bundle" \ %{?rustc_edition:--edition=%{rustc_edition}} \ %rust_dylib_extern libc \ %rust_dylib_extern mockall \ %rust_dylib_extern mockall_double \ - src/rust-tizen-base/src/lib.rs + src/rust-tizen-bundle/src/lib.rs + +%{rustc_std_build} --crate-type=dylib \ + --crate-name=tizen_parcel \ + -L native="./src/parcel" \ + %{?rustc_edition:--edition=%{rustc_edition}} \ + %rust_dylib_extern libc \ + src/rust-tizen-parcel/src/lib.rs + +%{rustc_std_build} --test --crate-type=bin \ + --crate-name=tizen_parcel_unittests \ + -L native="./src/parcel" \ + %{?rustc_edition:--edition=%{rustc_edition}} \ + %rust_dylib_extern libc \ + %rust_dylib_extern mockall \ + %rust_dylib_extern mockall_double \ + src/rust-tizen-parcel/src/lib.rs %check export LD_LIBRARY_PATH="../../src/bundle:../../src/parcel" ctest --verbose %{?_smp_mflags} -export LD_LIBRARY_PATH="%{_rust_dylibdir}:./src/parcel:./src/bundle" -RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./tizen_base_unittests +export LD_LIBRARY_PATH="%{_rust_dylibdir}:./src/bundle" +RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./tizen_bundle_unittests + +export LD_LIBRARY_PATH="%{_rust_dylibdir}:./src/parcel:" +RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./tizen_parcel_unittests %if 0%{?gcov:1} lcov -c --ignore-errors mismatch,graph,unused --no-external -b . -d . -o %{name}.info @@ -256,8 +281,11 @@ install -m 0755 run-unittest.sh %{buildroot}%{_bindir}/tizen-unittests/tizen-sha sed -i -e 's//tizen-shared-queue/g' %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue/run-unittest.sh install -d -m 0755 %{buildroot}%{_rust_dylibdir} -install -m 0644 libtizen_base.so %{buildroot}/%{_rust_dylibdir}/libtizen_base.so -strip -s -N .rustc %{buildroot}/%{_rust_dylibdir}/libtizen_base.so +install -m 0644 libtizen_bundle.so %{buildroot}/%{_rust_dylibdir}/libtizen_bundle.so +strip -s -N .rustc %{buildroot}/%{_rust_dylibdir}/libtizen_bundle.so + +install -m 0644 libtizen_parcel.so %{buildroot}/%{_rust_dylibdir}/libtizen_parcel.so +strip -s -N .rustc %{buildroot}/%{_rust_dylibdir}/libtizen_parcel.so %post -p /sbin/ldconfig @@ -274,13 +302,16 @@ strip -s -N .rustc %{buildroot}/%{_rust_dylibdir}/libtizen_base.so %{_bindir}/bundle_unittests %endif -%post -n rust-tizen-base +%post -n rust-tizen-bundle /sbin/ldconfig -unzip %{_rust_dylibdir}/libtizen_base.zip -d %{_rust_dylibdir}/ -rm %{_rust_dylibdir}/libtizen_base.zip +%postun -n rust-tizen-bundle +/sbin/ldconfig + +%post -n rust-tizen-parcel +/sbin/ldconfig -%postun -n rust-tizen-base +%postun -n rust-tizen-parcel /sbin/ldconfig %files @@ -352,9 +383,17 @@ rm %{_rust_dylibdir}/libtizen_base.zip %{_bindir}/tizen-unittests/tizen-shared-queue/run-unittest.sh ################################################# -# rust-tizen-base +# rust-tizen-bundle +################################################# +%files -n rust-tizen-bundle +%manifest rust-tizen-bundle.manifest +%license LICENSE +%{_rust_dylibdir}/libtizen_bundle.so + +################################################# +# rust-tizen-parcel ################################################# -%files -n rust-tizen-base -%manifest rust-tizen-base.manifest +%files -n rust-tizen-parcel +%manifest rust-tizen-parcel.manifest %license LICENSE -%{_rust_dylibdir}/libtizen_base.so +%{_rust_dylibdir}/libtizen_parcel.so diff --git a/src/rust-tizen-base/Cargo.toml b/src/rust-tizen-base/Cargo.toml deleted file mode 100644 index 46e9148..0000000 --- a/src/rust-tizen-base/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "rust-tizen-base" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = [ "dylib" ] -crate-name = [ "tizen_base" ] diff --git a/src/rust-tizen-base/src/bundle.rs b/src/rust-tizen-base/src/bundle.rs deleted file mode 100644 index 0e62aea..0000000 --- a/src/rust-tizen-base/src/bundle.rs +++ /dev/null @@ -1,818 +0,0 @@ -extern crate libc; - -use self::libc::{EINVAL, ENOKEY, ENOMEM}; -use std::collections::VecDeque; -use std::ffi::{c_char, c_int, c_uchar, c_uint, c_void, CStr, CString}; -use std::ptr; - -const TIZEN_ERROR_BUNDLE: i32 = -0x01180000; -const BUNDLE_ERROR_NONE: i32 = 0; -const BUNDLE_ERROR_OUT_OF_MEMORY: i32 = -ENOMEM; -const BUNDLE_ERROR_INVALID_PARAMETER: i32 = -EINVAL; -const BUNDLE_ERROR_KEY_NOT_AVAILABLE: i32 = -ENOKEY; -const BUNDLE_ERROR_KEY_EXISTS: i32 = TIZEN_ERROR_BUNDLE | 0x01; -const BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS: i32 = TIZEN_ERROR_BUNDLE | 0x02; - -const BUNDLE_TYPE_ARRAY: i32 = 0x0100; -const BUNDLE_TYPE_MEASURABLE: i32 = 0x0400; -const BUNDLE_TYPE_NONE: i32 = -1; -const BUNDLE_TYPE_ANY: i32 = 0; -const BUNDLE_TYPE_STR: i32 = 1 | BUNDLE_TYPE_MEASURABLE; -const BUNDLE_TYPE_STR_ARRAY: i32 = BUNDLE_TYPE_STR | BUNDLE_TYPE_ARRAY | BUNDLE_TYPE_MEASURABLE; -const BUNDLE_TYPE_BYTE: i32 = 2; -const BUNDLE_TYPE_BYTE_ARRAY: i32 = BUNDLE_TYPE_BYTE | BUNDLE_TYPE_ARRAY; - -#[link(name = "bundle")] -extern "C" { - fn bundle_create() -> *mut c_void; - fn bundle_free(b: *mut c_void) -> c_int; - fn bundle_add_str_array( - b: *mut c_void, - key: *const c_char, - array: *const *const c_char, - len: c_int, - ) -> c_int; - fn bundle_del(b: *mut c_void, key: *const c_char) -> c_int; - fn bundle_get_str_array( - b: *mut c_void, - key: *const c_char, - len: *mut c_int, - ) -> *const *const c_char; - fn bundle_get_count(b: *mut c_void) -> c_int; - fn bundle_get_type(b: *mut c_void, key: *const c_char) -> c_int; - fn bundle_dup(b: *mut c_void) -> *mut c_void; - fn bundle_foreach( - b: *mut c_void, - callback: extern "C" fn(*const c_char, c_int, *const c_void, *mut c_void), - user_data: *mut c_void, - ) -> c_int; - fn bundle_encode(b: *mut c_void, r: *mut *mut c_char, len: *mut c_int) -> c_int; - fn bundle_decode(r: *const c_char, len: c_int) -> *mut c_void; - fn bundle_add_str(b: *mut c_void, key: *const c_char, value: *const c_char) -> c_int; - fn bundle_add_byte( - b: *mut c_void, - key: *const c_char, - bytes: *const c_uchar, - size: c_uint, - ) -> c_int; - fn bundle_get_str(b: *mut c_void, key: *const c_char, val: *mut *mut c_char) -> c_int; - fn bundle_get_byte( - b: *mut c_void, - key: *const c_char, - bytes: *mut *mut c_void, - size: *mut c_uint, - ) -> c_int; - fn bundle_add_byte_array(b: *mut c_void, key: *const c_char, len: c_uint) -> c_int; - fn bundle_set_byte_array_element( - b: *mut c_void, - key: *const c_char, - idx: c_uint, - bytes: *const c_void, - size: c_uint, - ) -> c_int; - fn bundle_get_byte_array( - b: *mut c_void, - key: *const c_char, - byte_array: *mut *mut *mut c_void, - len: *mut c_uint, - array_element_size: *mut *mut c_uint, - ) -> c_int; - fn bundle_keyval_get_basic_val( - kv: *mut c_void, - val: *mut *mut c_void, - size: *mut c_uint, - ) -> c_int; - fn bundle_keyval_get_array_val( - kv: *mut c_void, - array_val: *mut *mut *mut c_void, - array_len: *mut c_uint, - array_element_size: *mut *mut c_uint, - ) -> c_int; -} - -#[link(name = "capi-base-common")] -extern "C" { - fn get_last_result() -> c_int; -} - -/// Represents a value of a bundle. -#[derive(Debug)] -pub enum BundleValue { - /// A string value. - String(String), - /// A vector of strings. - StringVector(Vec), - /// A byte vector. - Bytes(Vec), - /// A vector of byte vectors. - BytesVector(Vec>), -} - -/// Represents an error that can occur when working with a `Bundle`. -#[derive(Debug, PartialEq)] -pub enum BundleError { - /// Out of memory. - /// There is not enough memory to complete the operation. This error occurs when the memory allocation fails. - OutOfMemory, - /// Invalid parameter. - /// The input parameter is invalid. This error occurs when the input parameter is out of range. - InvalidParameter, - /// Key not available. - /// The key does not exist in the bundle. This error occurs when you try to get a value with a non-existent key. - KeyNotAvailable, - /// Key exists. - /// The key already exists in the bundle. This error occurs when you try to add a key that already exists. - KeyExists, - /// The index is out of bounds of the array. - ArrayIndexOutOfBounds, - /// No ownership. - /// The bundle does not own the data. This error occurs when you try to detach the data that was not allocated by the bundle. - NoOwnership, -} - -impl BundleError { - fn from_c_int(result: c_int) -> BundleError { - match result { - BUNDLE_ERROR_OUT_OF_MEMORY => BundleError::OutOfMemory, - BUNDLE_ERROR_INVALID_PARAMETER => BundleError::InvalidParameter, - BUNDLE_ERROR_KEY_NOT_AVAILABLE => BundleError::KeyNotAvailable, - BUNDLE_ERROR_KEY_EXISTS => BundleError::KeyExists, - BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS => BundleError::ArrayIndexOutOfBounds, - _ => panic!("Unexpected error code {}", result), - } - } -} - -/// Represents a type of a bundle key. -#[derive(Debug, PartialEq)] -pub enum BundleType { - /// None. - None, - /// Any type. - Any, - /// A string type. - String, - /// A vector of strings. - StringVector, - /// Bytes type. - Bytes, - /// A vector of bytes. - BytesVector, -} - -impl BundleType { - fn from_c_int(key_type: c_int) -> BundleType { - match key_type { - BUNDLE_TYPE_NONE => BundleType::None, - BUNDLE_TYPE_ANY => BundleType::Any, - BUNDLE_TYPE_STR => BundleType::String, - BUNDLE_TYPE_STR_ARRAY => BundleType::StringVector, - BUNDLE_TYPE_BYTE => BundleType::Bytes, - BUNDLE_TYPE_BYTE_ARRAY => BundleType::BytesVector, - _ => panic!("Unexpected type code: {}", key_type), - } - } -} - -/// A representation of a Bundle, which is a key-value pair container. -#[derive(Debug)] -pub struct Bundle { - handle: *mut c_void, - ownership: bool, -} - -impl Clone for Bundle { - fn clone(&self) -> Self { - let handle = unsafe { bundle_dup(self.handle) }; - Self { handle, ownership: true } - } -} - -impl Drop for Bundle { - fn drop(&mut self) { - if self.ownership && !self.handle.is_null() { - unsafe { - bundle_free(self.handle); - } - } - } -} - -impl Default for Bundle { - fn default() -> Self { - Self::new() - } -} - -impl Bundle { - /// Creates a new `Bundle` instance. - /// - /// # Panics - /// - /// This function will panic if the creation of a `Bundle` fails. - pub fn new() -> Self { - let handle = unsafe { bundle_create() }; - if handle.is_null() { - panic!("Failed to create bundle"); - } - Self { handle, ownership: true } - } - - /// Creates a new `Bundle` instance from a raw handle. - /// - /// # Arguments - /// - /// * `b`: The raw handle to the bundle. - /// * `ownership`: Whether or not the `Bundle` should take ownership of the raw handle. If `false`, the caller retains ownership and the `Bundle` will not free the handle when it is dropped. - /// - /// # Panics - /// - /// This function panics if the provided handle is null. - pub fn from_raw_handle(b: *mut c_void, ownership: bool) -> Self { - if b.is_null() { - panic!("Bundle pointer is null"); - } - Self { handle: b, ownership } - } - - /// Gets a raw handle from the `Bundle`. - /// - /// # Returns - /// - /// A raw handle of the `Bundle`. - pub fn get_raw_handle(&self) -> *mut c_void { - self.handle - } - - /// Detaches the raw handle from the `Bundle` and returns it. - /// - /// # Returns - /// - /// Returns `Ok(*mut c_void)` on success, or an appropriate `Err(BundleError)` on failure. - /// If the `Bundle` does not own the raw handle, this function returns `Err(BundleError)`. Otherwise, - pub fn detach(&mut self) -> Result<*mut c_void, BundleError> { - if self.ownership { - let handle = self.handle; - self.handle = std::ptr::null_mut(); - self.ownership = false; - Ok(handle) - } else { - Err(BundleError::NoOwnership) - } - } - - /// Deletes a value associated with the given key. - /// - /// # Arguements - /// - /// * `key` - The key to be deleted. It must be a valid UTF-8 string. If not, this function will return an error. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failrue. - pub fn delete(&mut self, key: &str) -> Result<(), BundleError> { - let c_key = CString::new(key).unwrap(); - let result = unsafe { bundle_del(self.handle, c_key.as_ptr()) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Gets the number of elements in the `Bundle`. - /// - /// # Returns - /// - /// The number of elements. - pub fn count(&self) -> i32 { - (unsafe { bundle_get_count(self.handle) }) as i32 - } - - /// Adds a string to the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key of the element. - /// * `value` - The value of the element. This must be a valid UTF-8 encoded string. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. - pub fn add_str(&mut self, key: &str, value: &str) -> Result<(), BundleError> { - let c_key = CString::new(key).unwrap(); - let c_value = CString::new(value).unwrap(); - let result = unsafe { bundle_add_str(self.handle, c_key.as_ptr(), c_value.as_ptr()) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Gets a string with the given key from the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key to retrieve the value for. - /// - /// # Returns - /// - /// Returns `Ok(String)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn get_str(&self, key: &str) -> Result { - let c_key = CString::new(key).unwrap(); - let mut c_val: *mut c_char = ptr::null_mut(); - let result = unsafe { bundle_get_str(self.handle, c_key.as_ptr(), &mut c_val) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - let c_str = unsafe { CStr::from_ptr(c_val) }; - Ok(c_str.to_string_lossy().into_owned()) - } - } - - /// Adds a vector of strings to the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key of the element. - /// * `value` - The vector of strings. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. - pub fn add_str_vec(&mut self, key: &str, values: &[&str]) -> Result<(), BundleError> { - let c_key = CString::new(key).unwrap(); - let c_array: Vec = values.iter().map(|&s| CString::new(s).unwrap()).collect(); - let c_ptr_array: Vec<*const c_char> = c_array.iter().map(|s| s.as_ptr()).collect(); - let result = unsafe { - bundle_add_str_array( - self.handle, - c_key.as_ptr(), - c_ptr_array.as_ptr(), - c_array.len() as c_int, - ) - }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Gets a vector of strings with the given key from the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key to retrieve the value for. - /// - /// # Returns - /// - /// Returns `Ok(Vec)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn get_str_vec(&self, key: &str) -> Result, BundleError> { - let c_key = CString::new(key).unwrap(); - let mut len: c_int = 0; - let c_array_ptr = unsafe { bundle_get_str_array(self.handle, c_key.as_ptr(), &mut len) }; - if c_array_ptr.is_null() { - return Err(BundleError::from_c_int(unsafe { get_last_result() })); - } - - let mut result = Vec::with_capacity(len as usize); - for i in 0..len { - let c_str_ptr = unsafe { *c_array_ptr.add(i as usize) }; - let c_str = unsafe { CStr::from_ptr(c_str_ptr) }; - result.push(c_str.to_string_lossy().into_owned()); - } - Ok(result) - } - - /// Adds bytes to the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key of the element. - /// * `value` - The bytes of the element. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. - pub fn add_bytes(&mut self, key: &str, bytes: &[u8]) -> Result<(), BundleError> { - let c_key = CString::new(key).unwrap(); - let result = unsafe { - bundle_add_byte( - self.handle, - c_key.as_ptr(), - bytes.as_ptr(), - bytes.len() as c_uint, - ) - }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Gets bytes with the given key from the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key to retrieve the value for. - /// - /// # Returns - /// - /// Returns `Ok(Vec)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn get_bytes(&self, key: &str) -> Result, BundleError> { - let c_key = CString::new(key).unwrap(); - let mut bytes_ptr: *mut c_void = ptr::null_mut(); - let mut size: c_uint = 0; - let result = - unsafe { bundle_get_byte(self.handle, c_key.as_ptr(), &mut bytes_ptr, &mut size) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(unsafe { - std::slice::from_raw_parts(bytes_ptr as *const u8, size as usize).to_vec() - }) - } - } - - /// Adds a vector of bytes to the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key of the element. - /// * `value` - The vector of bytes. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. - pub fn add_bytes_vec(&mut self, key: &str, elements: &[&[u8]]) -> Result<(), BundleError> { - let c_key = CString::new(key).unwrap(); - let array_len = elements.len() as c_uint; - let result = unsafe { bundle_add_byte_array(self.handle, c_key.as_ptr(), array_len) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - for (idx, element) in elements.iter().enumerate() { - let result = unsafe { - bundle_set_byte_array_element( - self.handle, - c_key.as_ptr(), - idx as c_uint, - element.as_ptr() as *const c_void, - element.len() as c_uint, - ) - }; - if result != 0 { - return Err(BundleError::from_c_int(result)); - } - } - Ok(()) - } - } - - /// Gets a vector of bytes with the given key from the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key to retrieve the value for. - /// - /// # Returns - /// - /// Returns `Ok(Vec>)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn get_bytes_vec(&self, key: &str) -> Result>, BundleError> { - let c_key = CString::new(key).unwrap(); - let mut byte_array_ptr: *mut *mut c_void = ptr::null_mut(); - let mut len: c_uint = 0; - let mut array_element_size: *mut c_uint = ptr::null_mut(); - let result = unsafe { - bundle_get_byte_array( - self.handle, - c_key.as_ptr(), - &mut byte_array_ptr, - &mut len, - &mut array_element_size, - ) - }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - let byte_array = unsafe { std::slice::from_raw_parts(byte_array_ptr, len as usize) }; - let element_sizes = - unsafe { std::slice::from_raw_parts(array_element_size, len as usize) }; - let mut bytes = Vec::with_capacity(len as usize); - for i in 0..len as usize { - let element_size = element_sizes[i] as usize; - let element = - unsafe { std::slice::from_raw_parts(byte_array[i] as *const u8, element_size) }; - bytes.push(element.to_vec()); - } - - Ok(bytes) - } - } - - /// Gets the type of a given key in the `Bundle`. - /// - /// # Arguments - /// - /// * `key` - The key to retrieve the value type for. - /// - /// # Returns - /// - /// Returns `Ok(BundleType)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn get_type(&self, key: &str) -> Result { - let c_key = CString::new(key).unwrap(); - let result = unsafe { bundle_get_type(self.handle, c_key.as_ptr()) }; - if result < BUNDLE_TYPE_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(BundleType::from_c_int(result)) - } - } - - /// Encode the bundle to a string.(uses base64 format). - /// - /// # Returns - /// - /// Returns `Ok(String)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn encode(&self) -> Result { - let mut raw: *mut c_char = std::ptr::null_mut(); - let mut len: c_int = 0; - let result = unsafe { bundle_encode(self.handle, &mut raw, &mut len) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(unsafe { CStr::from_ptr(raw as *const c_char) } - .to_string_lossy() - .into_owned()) - } - } - - /// Creates a new `Bundle` from the given encoded string. - /// The string must be in the format returned by `encode`. If the string is invalid, an error will be returned. - /// - /// # Arguments - /// - /// * `raw` - The encoded string to decode. This must be in the format returned by `encode`. - /// - /// # Returns - /// - /// Returns `Ok(Bundle)` on success, or an appropriate `Err(BundleError)` on failure. - pub fn decode(raw: &str) -> Result { - let c_raw = CString::new(raw).unwrap(); - let handle = unsafe { bundle_decode(c_raw.as_ptr() as *const c_char, raw.len() as c_int) }; - if handle.is_null() { - Err(BundleError::from_c_int(unsafe { get_last_result() })) - } else { - Ok(Bundle { handle, ownership: true }) - } - } - - /// Iterates over the keys and values of the `Bundle`. - /// - /// # Returns - /// - /// An iterator over the keys and values of the `Bundle`. - pub fn iter(&self) -> BundleIter { - let mut bundle_iter = BundleIter { - bundle: self, - items: VecDeque::new(), - }; - bundle_iter.populate_items(); - bundle_iter - } -} - -#[derive(Debug)] -struct KeyInfo { - key: String, - key_type: BundleType, - handle: *mut c_void, -} - -impl KeyInfo { - fn new(key: &str, key_type: BundleType, handle: *mut c_void) -> Self { - KeyInfo { - key: key.to_string(), - key_type, - handle, - } - } - - fn get_str(&self) -> Result { - let mut val: *mut c_void = std::ptr::null_mut(); - let mut size: c_uint = 0; - let result = unsafe { bundle_keyval_get_basic_val(self.handle, &mut val, &mut size) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(unsafe { - CStr::from_ptr(val as *const c_char) - .to_string_lossy() - .into_owned() - }) - } - } - - fn get_str_vec(&self) -> Result, BundleError> { - let mut array_val: *mut *mut c_void = std::ptr::null_mut(); - let mut array_len: c_uint = 0; - let mut array_element_size: *mut c_uint = std::ptr::null_mut(); - let result = unsafe { - bundle_keyval_get_array_val( - self.handle, - &mut array_val, - &mut array_len, - &mut array_element_size, - ) - }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - let mut values = Vec::with_capacity(array_len as usize); - for i in 0..array_len { - let c_str_ptr = unsafe { *array_val.add(i as usize) }; - let c_str = unsafe { CStr::from_ptr(c_str_ptr as *const c_char) }; - values.push(c_str.to_string_lossy().into_owned()); - } - Ok(values) - } - } - - fn get_bytes(&self) -> Result, BundleError> { - let mut val: *mut c_void = std::ptr::null_mut(); - let mut size: c_uint = 0; - let result = unsafe { bundle_keyval_get_basic_val(self.handle, &mut val, &mut size) }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - Ok(unsafe { std::slice::from_raw_parts(val as *const u8, size as usize).to_vec() }) - } - } - - fn get_bytes_vec(&self) -> Result>, BundleError> { - let mut array_val: *mut *mut c_void = std::ptr::null_mut(); - let mut array_len: c_uint = 0; - let mut array_element_size: *mut c_uint = std::ptr::null_mut(); - let result = unsafe { - bundle_keyval_get_array_val( - self.handle, - &mut array_val, - &mut array_len, - &mut array_element_size, - ) - }; - if result != BUNDLE_ERROR_NONE { - Err(BundleError::from_c_int(result)) - } else { - let byte_array = unsafe { std::slice::from_raw_parts(array_val, array_len as usize) }; - let element_sizes = - unsafe { std::slice::from_raw_parts(array_element_size, array_len as usize) }; - let mut bytes_vec = Vec::with_capacity(array_len as usize); - for i in 0..array_len as usize { - let element_size = element_sizes[i] as usize; - let element = - unsafe { std::slice::from_raw_parts(byte_array[i] as *const u8, element_size) }; - bytes_vec.push(element.to_vec()); - } - Ok(bytes_vec) - } - } - - fn get_item(&self) -> Result<(String, BundleValue), BundleError> { - match self.key_type { - BundleType::String => { - let value = self.get_str(); - match value { - Ok(v) => Ok((self.key.clone(), BundleValue::String(v))), - Err(err) => Err(err), - } - } - BundleType::StringVector => { - let value = self.get_str_vec(); - match value { - Ok(v) => Ok((self.key.clone(), BundleValue::StringVector(v))), - Err(err) => Err(err), - } - } - BundleType::Bytes => { - let value = self.get_bytes(); - match value { - Ok(v) => Ok((self.key.clone(), BundleValue::Bytes(v))), - Err(err) => Err(err), - } - } - BundleType::BytesVector => { - let value = self.get_bytes_vec(); - match value { - Ok(v) => Ok((self.key.clone(), BundleValue::BytesVector(v))), - Err(err) => Err(err), - } - } - _ => Err(BundleError::KeyNotAvailable), - } - } -} - -extern "C" fn foreach_callback( - key: *const c_char, - key_type: c_int, - key_value: *const c_void, - user_data: *mut c_void, -) { - let items: &mut VecDeque<(String, BundleValue)> = - unsafe { &mut *(user_data as *mut VecDeque<(String, BundleValue)>) }; - let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap().to_string() }; - let key_info = KeyInfo::new( - &key_str, - BundleType::from_c_int(key_type), - key_value as *mut c_void, - ); - let item = key_info.get_item(); - match item { - Ok(i) => items.push_back(i), - Err(err) => println!( - "Error while creating key info: {:?}, error: {:?}", - key_info, err - ), - } -} - -/// Iterator for Bundle. Iterates over all the keys and values in a bundle. -pub struct BundleIter<'a> { - bundle: &'a Bundle, - items: VecDeque<(String, BundleValue)>, -} - -impl<'a> BundleIter<'a> { - fn populate_items(&mut self) { - let user_data: *mut VecDeque<(String, BundleValue)> = &mut self.items; - unsafe { - bundle_foreach( - self.bundle.handle, - foreach_callback, - user_data as *mut c_void, - ); - } - } -} - -impl<'a> Iterator for BundleIter<'a> { - type Item = (String, BundleValue); - - fn next(&mut self) -> Option { - self.items.pop_front() - } -} - -impl<'a> IntoIterator for &'a Bundle { - type Item = (String, BundleValue); - type IntoIter = BundleIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl IntoIterator for Bundle { - type Item = (String, BundleValue); - type IntoIter = BundleIntoIter; - - fn into_iter(self) -> Self::IntoIter { - let mut iter = BundleIntoIter { - bundle: self, - items: VecDeque::new(), - }; - iter.populate_items(); - iter - } -} - -/// IntoIterator for Bundle. -pub struct BundleIntoIter { - bundle: Bundle, - items: VecDeque<(String, BundleValue)>, -} - -impl BundleIntoIter { - fn populate_items(&mut self) { - let user_data: *mut VecDeque<(String, BundleValue)> = &mut self.items; - unsafe { - bundle_foreach( - self.bundle.handle, - foreach_callback, - user_data as *mut c_void, - ); - } - } -} - -impl Iterator for BundleIntoIter { - type Item = (String, BundleValue); - - fn next(&mut self) -> Option { - self.items.pop_front() - } -} diff --git a/src/rust-tizen-base/src/lib.rs b/src/rust-tizen-base/src/lib.rs deleted file mode 100644 index 73c768f..0000000 --- a/src/rust-tizen-base/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod parcel; -pub mod bundle; - -pub use crate::parcel::{Parcel}; -pub use crate::bundle::{Bundle}; - -mod tests; diff --git a/src/rust-tizen-base/src/parcel.rs b/src/rust-tizen-base/src/parcel.rs deleted file mode 100644 index c77e9d5..0000000 --- a/src/rust-tizen-base/src/parcel.rs +++ /dev/null @@ -1,609 +0,0 @@ -extern crate libc; - -use self::libc::{EILSEQ, EINVAL, ENODATA, ENOMEM}; -use std::ffi::{ - c_char, c_double, c_float, c_int, c_longlong, c_short, c_uchar, c_uint, c_ulonglong, c_ushort, - c_void, CString, -}; -use std::ptr; - -const PARCEL_ERROR_NONE: i32 = 0; -const PARCEL_ERROR_ILLEGAL_BYTE_SEQ: i32 = -EILSEQ; -const PARCEL_ERROR_INVALID_PARAMETER: i32 = -EINVAL; -const PARCEL_ERROR_NO_DATA: i32 = -ENODATA; -const PARCEL_ERROR_OUT_OF_MEMORY: i32 = -ENOMEM; - -#[link(name = "parcel")] -extern "C" { - fn parcel_create(parcel: *mut *mut c_void) -> c_int; - fn parcel_destroy(parcel: *mut c_void) -> c_int; - fn parcel_clone(parcel: *const c_void, clone: *mut *mut c_void) -> c_int; - fn parcel_burst_write(parcel: *mut c_void, buf: *const c_uchar, size: usize) -> c_int; - fn parcel_burst_read(parcel: *mut c_void, buf: *mut c_uchar, size: usize) -> c_int; - fn parcel_write_bool(parcel: *mut c_void, val: c_int) -> c_int; - fn parcel_write_byte(parcel: *mut c_void, val: c_char) -> c_int; - fn parcel_write_uint16(parcel: *mut c_void, val: c_ushort) -> c_int; - fn parcel_write_uint32(parcel: *mut c_void, val: c_uint) -> c_int; - fn parcel_write_uint64(parcel: *mut c_void, val: c_ulonglong) -> c_int; - fn parcel_write_int16(parcel: *mut c_void, val: c_short) -> c_int; - fn parcel_write_int32(parcel: *mut c_void, val: c_int) -> c_int; - fn parcel_write_int64(parcel: *mut c_void, val: c_longlong) -> c_int; - fn parcel_write_float(parcle: *mut c_void, val: c_float) -> c_int; - fn parcel_write_double(parcel: *mut c_void, val: c_double) -> c_int; - fn parcel_write_string(parcel: *mut c_void, val: *const c_char) -> c_int; - fn parcel_read_bool(parcel: *mut c_void, val: *mut c_int) -> c_int; - fn parcel_read_byte(parcel: *mut c_void, val: *mut c_char) -> c_int; - fn parcel_read_uint16(parcel: *mut c_void, val: *mut c_ushort) -> c_int; - fn parcel_read_uint32(parcel: *mut c_void, val: *mut c_uint) -> c_int; - fn parcel_read_uint64(parcel: *mut c_void, val: *mut c_ulonglong) -> c_int; - fn parcel_read_int16(parcel: *mut c_void, val: *mut c_short) -> c_int; - fn parcel_read_int32(parcel: *mut c_void, val: *mut c_int) -> c_int; - fn parcel_read_int64(parcel: *mut c_void, val: *mut c_longlong) -> c_int; - fn parcel_read_float(parcel: *mut c_void, val: *mut c_float) -> c_int; - fn parcel_read_double(parcel: *mut c_void, val: *mut c_double) -> c_int; - fn parcel_read_string(parcel: *mut c_void, val: *mut *mut c_char) -> c_int; - fn parcel_reset_reader(parcel: *mut c_void) -> c_int; - fn parcel_clear(parcel: *mut c_void) -> c_int; - fn parcel_reset(parcel: *mut c_void, buf: *const c_void, size: c_uint) -> c_int; - fn parcel_get_raw(parcel: *mut c_void, buf: *mut *mut c_void, size: *mut c_uint) -> c_int; -} - -/// Represents errors that can occur when working with a `Parcel`. -#[derive(Debug, PartialEq)] -pub enum ParcelError { - /// Illegal byte sequence. - /// The data in the parcel is not valid. - /// This error occurs when the data is not encoded properly or the data is corrupted. - IllegalByteSeq, - /// Invalid parameter. - /// The input parameter is invalid. This error occurs when the input parameter is out of range. - InvalidParameter, - /// No data available. - /// There is no data to read. This error occurs when there is no more data to read from the parcel. - NoData, - /// Out of memory. - /// There is not enough memory to complete the operation. This error occurs when the memory allocation fails. - OutOfMemory, -} - -impl ParcelError { - fn from_c_int(result: c_int) -> ParcelError { - match result { - PARCEL_ERROR_ILLEGAL_BYTE_SEQ => ParcelError::IllegalByteSeq, - PARCEL_ERROR_INVALID_PARAMETER => ParcelError::InvalidParameter, - PARCEL_ERROR_NO_DATA => ParcelError::NoData, - PARCEL_ERROR_OUT_OF_MEMORY => ParcelError::OutOfMemory, - _ => panic!("Unexpected error code {}", result), - } - } -} - -/// A representation of a Parcel, which is used for serializing and deserializing data. -#[derive(Debug)] -pub struct Parcel { - handle: *mut c_void, -} - -/// A trait that defines how a type can be serialized to and deserialized from a Parcel. -pub trait Parcelable { - fn to_parcel(&self) -> Parcel; - fn from_parcel(parcel: &mut Parcel) -> T; -} - -impl Clone for Parcel { - fn clone(&self) -> Self { - let mut clone_handle: *mut c_void = ptr::null_mut(); - unsafe { - let result = parcel_clone(self.handle, &mut clone_handle); - assert!(result == PARCEL_ERROR_NONE, "Failed to clone a parcel") - }; - Self { - handle: clone_handle, - } - } -} - -impl Drop for Parcel { - fn drop(&mut self) { - unsafe { - parcel_destroy(self.handle); - } - } -} - -impl Default for Parcel { - fn default() -> Self { - Self::new() - } -} - -impl Parcel { - /// Creates a new `Parcel` instance. - /// - /// # Panics - /// - /// This function will panic if the creation of a `Parcel` fails. - pub fn new() -> Self { - let mut handle: *mut c_void = ptr::null_mut(); - unsafe { - let result = parcel_create(&mut handle); - assert!(result == PARCEL_ERROR_NONE, "Failed to create a parcel"); - } - Self { handle } - } - - /// Writes a byte slice to the `Parcel`. - /// - /// # Arguments - /// - /// * `data` - A slice of bytes to be written to the `Parcel`. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write(&mut self, data: &[u8]) -> Result<(), ParcelError> { - let result = unsafe { - parcel_burst_write(self.handle, data.as_ptr(), data.len()) - }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Reads a byte slice from the `Parcel`. - /// - /// # Arguments - /// - /// * `size` - The number of bytes to read from the `Parcel`. - /// - /// # Returns - /// - /// Returns a `Vec` containing the data read on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read(&mut self, size: usize) -> Result, ParcelError> { - let mut data = vec![0; size]; - let result = unsafe { parcel_burst_read(self.handle, data.as_mut_ptr(), data.len()) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(data) - } - } - - /// Gets the raw data from the `Parcel`. - /// - /// # Returns - /// - /// Returns a `Vec` containing the raw data on success, or an appropriate `Err(ParcelError)` on failure. - pub fn get_raw_data(&self) -> Result, ParcelError> { - let mut size = 0; - let mut raw: *mut c_void = ptr::null_mut(); - let result = unsafe { parcel_get_raw(self.handle, &mut raw, &mut size) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - let mut data = vec![0; size as usize]; - unsafe { - std::ptr::copy(raw as *const u8, data.as_mut_ptr(), size as usize); - } - Ok(data) - } - } - - /// Resets the reader position of the `Parcel`. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn reset_reader(&mut self) -> Result<(), ParcelError> { - let result = unsafe { parcel_reset_reader(self.handle) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Clears the contents of the `Parcel`. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn clear(&mut self) -> Result<(), ParcelError> { - let result = unsafe { parcel_clear(self.handle) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Resets the `Parcel` with the provided data. - /// - /// # Arguments - /// - /// * `data` - The slice of bytes to reset the `Parcel`. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn reset(&mut self, data: &[u8]) -> Result<(), ParcelError> { - let result = unsafe { - parcel_reset( - self.handle, - data.as_ptr() as *const c_void, - data.len() as c_uint, - ) - }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a boolean value to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The boolean value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_bool(&mut self, val: bool) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_bool(self.handle, val as c_int) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 8-bit integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 8-bit integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_i8(&mut self, val: i8) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_byte(self.handle, val as c_char) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 16-bit integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 16-bit integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_i16(&mut self, val: i16) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_int16(self.handle, val as c_short) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 32-bit integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 32-bit integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_i32(&mut self, val: i32) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_int32(self.handle, val as c_int) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 64-bit integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 64-bit integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_i64(&mut self, val: i64) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_int64(self.handle, val as c_longlong) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 16-bit unsigned integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 16-bit unsigned integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_u16(&mut self, val: u16) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_uint16(self.handle, val as c_ushort) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 32-bit unsigned integer to the `Parcel`. - /// - /// # Arguments - /// - /// * `val` - The 32-bit unsigned integer value to be written. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_u32(&mut self, val: u32) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_uint32(self.handle, val as c_uint) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 64-bit unsigned integer to the parcel. - /// - /// # Arguments - /// - /// * `val` - The 64-bit unsigned integer value to write. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_u64(&mut self, val: u64) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_uint64(self.handle, val as c_ulonglong) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 32-bit floating point to the parcel. - /// - /// # Arguments - /// - /// * `val` - The 32-bit floating point value to write. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_f32(&mut self, val: f32) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_float(self.handle, val) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a 64-bit floating point to the parcel. - /// - /// # Arguments - /// - /// * `val` - The 64-bit floating point value to write. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_f64(&mut self, val: f64) -> Result<(), ParcelError> { - let result = unsafe { parcel_write_double(self.handle, val) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Writes a string to the parcel. - /// - /// # Arguments - /// - /// * `val` - The string value to write. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn write_string(&mut self, val: &str) -> Result<(), ParcelError> { - let ptr = CString::new(val).unwrap(); - let result = unsafe { parcel_write_string(self.handle, ptr.as_ptr() as *const c_char) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(()) - } - } - - /// Reads a boolean from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(bool)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_bool(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_bool(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value != 0) - } - } - - /// Reads a 8-bit interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(i8)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_i8(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_byte(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value as i8) - } - } - - /// Reads a 16-bit interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(i16)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_i16(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_int16(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 32-bit interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(i32)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_i32(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_int32(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 64-bit interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(i64)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_i64(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_int64(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 16-bit unsigned interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(u16)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_u16(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_uint16(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 32-bit unsigned interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(u32)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_u32(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_uint32(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 64-bit unsigned interger from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(u64)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_u64(&mut self) -> Result { - let mut value = 0; - let result = unsafe { parcel_read_uint64(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 32-bit floating point from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(f32)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_f32(&mut self) -> Result { - let mut value = 0.0; - let result = unsafe { parcel_read_float(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a 64-bit floating point from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(f64)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_f64(&mut self) -> Result { - let mut value = 0.0; - let result = unsafe { parcel_read_double(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(value) - } - } - - /// Reads a string from the parcel. - /// - /// # Returns - /// - /// Returns `Ok(String)` on success, or an appropriate `Err(ParcelError)` on failure. - pub fn read_string(&mut self) -> Result { - let mut value: *mut c_char = ptr::null_mut(); - let result = unsafe { parcel_read_string(self.handle, &mut value) }; - if result != PARCEL_ERROR_NONE { - Err(ParcelError::from_c_int(result)) - } else { - Ok(unsafe { CString::from_raw(value).into_string().unwrap() }) - } - } -} diff --git a/src/rust-tizen-base/src/tests/bundle_tests.rs b/src/rust-tizen-base/src/tests/bundle_tests.rs deleted file mode 100644 index 0b23d02..0000000 --- a/src/rust-tizen-base/src/tests/bundle_tests.rs +++ /dev/null @@ -1,191 +0,0 @@ -use bundle; - -#[warn(unused_imports)] -use bundle::{Bundle, BundleError, BundleType, BundleIter, BundleValue}; - -#[test] -fn test_bundle_new_and_get_raw_handle() { - let b = Bundle::new(); - let native = b.get_raw_handle(); - assert!(!native.is_null()); -} - -#[test] -fn test_bundle_add_str_and_get_str() { - let mut b = Bundle::new(); - b.add_str("key", "value").unwrap(); - assert_eq!(b.get_str("key").unwrap(), "value"); -} - -#[test] -fn test_bundle_add_bytes_and_get_bytes() { - let mut b = Bundle::new(); - b.add_bytes("key", &[1, 2, 3]).unwrap(); - assert_eq!(b.get_bytes("key").unwrap(), &[1, 2, 3]); -} - -#[test] -fn test_bundle_add_str_vec_and_get_str_vec() { - let mut b = Bundle::new(); - b.add_str_vec("key", &["value1", "value2"]).unwrap(); - assert_eq!(b.get_str_vec("key").unwrap(), &["value1", "value2"]); -} - -#[test] -fn test_bundle_add_bytes_vec_and_get_bytes_vec() { - let mut b = Bundle::new(); - b.add_bytes_vec("key", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); - assert_eq!(b.get_bytes_vec("key").unwrap(), &[&[1, 2, 3], &[4, 5, 6]]); -} - -#[test] -fn test_bundle_count() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - b.add_str("key2", "value2").unwrap(); - assert_eq!(b.count(), 2); - b.add_str("key3", "value3").unwrap(); - assert_eq!(b.count(), 3); -} - -#[test] -fn test_bundle_get_type() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - assert_eq!(b.get_type("key1").unwrap(), BundleType::String); - b.add_str_vec("key2", &["value1", "value2"]).unwrap(); - assert_eq!(b.get_type("key2").unwrap(), BundleType::StringVector); - b.add_bytes("key3", &[1, 2, 3]).unwrap(); - assert_eq!(b.get_type("key3").unwrap(), BundleType::Bytes); - b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); - assert_eq!(b.get_type("key4").unwrap(), BundleType::BytesVector); -} - -#[test] -fn test_bundle_clone() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - b.add_str_vec("key2", &["value1", "value2"]).unwrap(); - let mut cloned_b = b.clone(); - assert_eq!(b.get_str("key1").unwrap(), cloned_b.get_str("key1").unwrap()); - assert_eq!(b.get_str_vec("key2").unwrap(), cloned_b.get_str_vec("key2").unwrap()); -} - -#[test] -fn test_bundle_default() { - let mut b = Bundle::default(); - b.add_str("key1", "value1").unwrap(); - assert_eq!(b.get_str("key1").unwrap(), "value1"); -} - -#[test] -fn test_bundle_delete() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - assert_eq!(b.get_str("key1").unwrap(), "value1"); - b.delete("key1").unwrap(); - let ret = b.get_str("key1"); - match (ret) { - Err(err) => assert_eq!(err, BundleError::KeyNotAvailable), - _ => panic!("Unexpected error"), - }; -} - -#[test] -fn test_bundle_iter() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - b.add_str_vec("key2", &["value1", "value2"]).unwrap(); - b.add_bytes("key3", &[1, 2, 3]).unwrap(); - b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); - - for (key, val) in b.iter() { - match val { - BundleValue::String(value) => { - assert_eq!(key, "key1"); - assert_eq!(value, "value1"); - } - BundleValue::StringVector(value) => { - assert_eq!(key, "key2"); - assert_eq!(value, &["value1", "value2"]); - } - BundleValue::Bytes(value) => { - assert_eq!(key, "key3"); - assert_eq!(value, &[1, 2, 3]); - } - BundleValue::BytesVector(value) => { - assert_eq!(key, "key4"); - assert_eq!(value, &[&[1, 2, 3], &[4, 5, 6]]); - } - _ => assert!(false), - } - } -} - -#[test] -fn test_bundle_into_iter() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - b.add_str_vec("key2", &["value1", "value2"]).unwrap(); - b.add_bytes("key3", &[1, 2, 3]).unwrap(); - b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); - - for (key, val) in b { - match val { - BundleValue::String(value) => { - assert_eq!(key, "key1"); - assert_eq!(value, "value1"); - } - BundleValue::StringVector(value) => { - assert_eq!(key, "key2"); - assert_eq!(value, &["value1", "value2"]); - } - BundleValue::Bytes(value) => { - assert_eq!(key, "key3"); - assert_eq!(value, &[1, 2, 3]); - } - BundleValue::BytesVector(value) => { - assert_eq!(key, "key4"); - assert_eq!(value, &[&[1, 2, 3], &[4, 5, 6]]); - } - _ => assert!(false), - } - } -} - -#[test] -fn test_bundle_encode_and_decode() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - let mut encoded_str = b.encode().unwrap(); - let mut decoded_b = Bundle::decode(&encoded_str).unwrap(); - assert_eq!(b.get_str("key1").unwrap(), decoded_b.get_str("key1").unwrap()); -} - -#[test] -fn test_bundle_detach() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - let result = b.detach(); - match result { - Ok(handle) => assert!(!handle.is_null()), - Err(err) => panic!("Failed to detach bundle. err: {:?}", err), - } - let handle = b.get_raw_handle(); - assert!(handle.is_null()); -} - -#[test] -fn test_bundle_from_raw_handle() { - let mut b = Bundle::new(); - b.add_str("key1", "value1").unwrap(); - let result = b.detach(); - match result { - Ok(handle) => { - assert!(!handle.is_null()); - let mut b2 = Bundle::from_raw_handle(handle, true); - assert_eq!(b2.get_str("key1").unwrap(), "value1"); - }, - Err(err) => panic!("Failed to detach bundle. err: {:?}", err), - } -} diff --git a/src/rust-tizen-base/src/tests/mod.rs b/src/rust-tizen-base/src/tests/mod.rs deleted file mode 100644 index c4146b8..0000000 --- a/src/rust-tizen-base/src/tests/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg(test)] -pub mod parcel_tests; -#[cfg(test)] -pub mod bundle_tests; diff --git a/src/rust-tizen-base/src/tests/parcel_tests.rs b/src/rust-tizen-base/src/tests/parcel_tests.rs deleted file mode 100644 index 2801a12..0000000 --- a/src/rust-tizen-base/src/tests/parcel_tests.rs +++ /dev/null @@ -1,134 +0,0 @@ -use parcel; - -#[warn(unused_imports)] -use parcel::{Parcel, ParcelError}; - -#[test] -fn test_parcel_write_bool_and_read_bool() { - let mut parcel = Parcel::new(); - parcel.write_bool(true); - let result = parcel.read_bool().unwrap(); - assert_eq!(result, true); -} - -#[test] -fn test_parcel_write_i8_and_read_i8() { - let mut parcel = Parcel::new(); - parcel.write_i8(1); - let result = parcel.read_i8().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_i16_and_read_i16() { - let mut parcel = Parcel::new(); - parcel.write_i16(1); - let result = parcel.read_i16().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_i32_and_read_i32() { - let mut parcel = Parcel::new(); - parcel.write_i32(1); - let result = parcel.read_i32().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_i64_and_read_i64() { - let mut parcel = Parcel::new(); - parcel.write_i64(1); - let result = parcel.read_i64().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_u16_and_read_u16() { - let mut parcel = Parcel::new(); - parcel.write_u16(1); - let result = parcel.read_u16().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_u32_and_read_u32() { - let mut parcel = Parcel::new(); - parcel.write_u32(1); - let result = parcel.read_u32().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_u64_and_read_u64() { - let mut parcel = Parcel::new(); - parcel.write_u64(1); - let result = parcel.read_u64().unwrap(); - assert_eq!(result, 1); -} - -#[test] -fn test_parcel_write_f32_and_read_f32() { - let mut parcel = Parcel::new(); - parcel.write_f32(1.0); - let result = parcel.read_f32().unwrap(); - assert_eq!(result, 1.0); -} - -#[test] -fn test_parcel_write_f64_and_read_f64() { - let mut parcel = Parcel::new(); - parcel.write_f64(1.0); - let result = parcel.read_f64().unwrap(); - assert_eq!(result, 1.0); -} - -#[test] -fn test_parcel_write_string_and_read_string() { - let mut parcel = Parcel::new(); - parcel.write_string("test"); - let result = parcel.read_string().unwrap(); - assert_eq!(result, "test"); -} - -#[test] -fn test_parcel_reset_reader() { - let mut parcel = Parcel::new(); - parcel.write_i32(1); - parcel.write_i32(2); - assert_eq!(parcel.read_i32().unwrap(), 1); - parcel.reset_reader(); - assert_eq!(parcel.read_i32().unwrap(), 1); - assert_eq!(parcel.read_i32().unwrap(), 2); -} - -#[test] -fn test_parcel_clear() { - let mut parcel = Parcel::new(); - parcel.write_i32(1); - parcel.clear(); - match parcel.read_i32() { - Err(err) => { - assert_eq!(err, ParcelError::NoData); - }, - _ => panic!("Expected error"), - }; -} - -#[test] -fn test_parcel_reset() { - let mut parcel = Parcel::new(); - parcel.reset(&[b'P']); - let res = parcel.read(1).unwrap(); - assert_eq!(res, [b'P']); -} - -#[test] -fn test_parcel_get_raw_data() { - let mut parcel = Parcel::new(); - parcel.write_i32(1); - parcel.write_i32(2); - let data = parcel.get_raw_data().unwrap(); - assert_ne!(data.len(), 0); - assert_eq!(data, vec![1, 0, 0, 0, 2, 0, 0, 0]); -} diff --git a/src/rust-tizen-bundle/Cargo.toml b/src/rust-tizen-bundle/Cargo.toml new file mode 100644 index 0000000..cdfc463 --- /dev/null +++ b/src/rust-tizen-bundle/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust-tizen-bundle" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = [ "dylib" ] +crate-name = [ "tizen_bundle" ] \ No newline at end of file diff --git a/src/rust-tizen-bundle/src/lib.rs b/src/rust-tizen-bundle/src/lib.rs new file mode 100644 index 0000000..f81cac0 --- /dev/null +++ b/src/rust-tizen-bundle/src/lib.rs @@ -0,0 +1,5 @@ +pub mod tizen_bundle; + +pub use crate::tizen_bundle::{Bundle}; + +mod tests; diff --git a/src/rust-tizen-bundle/src/tests/mod.rs b/src/rust-tizen-bundle/src/tests/mod.rs new file mode 100644 index 0000000..3c658f7 --- /dev/null +++ b/src/rust-tizen-bundle/src/tests/mod.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +pub mod tizen_bundle_tests; diff --git a/src/rust-tizen-bundle/src/tests/tizen_bundle_tests.rs b/src/rust-tizen-bundle/src/tests/tizen_bundle_tests.rs new file mode 100644 index 0000000..8d06b28 --- /dev/null +++ b/src/rust-tizen-bundle/src/tests/tizen_bundle_tests.rs @@ -0,0 +1,191 @@ +use tizen_bundle; + +#[warn(unused_imports)] +use tizen_bundle::{Bundle, BundleError, BundleType, BundleIter, BundleValue}; + +#[test] +fn test_bundle_new_and_get_raw_handle() { + let b = Bundle::new(); + let native = b.get_raw_handle(); + assert!(!native.is_null()); +} + +#[test] +fn test_bundle_add_str_and_get_str() { + let mut b = Bundle::new(); + b.add_str("key", "value").unwrap(); + assert_eq!(b.get_str("key").unwrap(), "value"); +} + +#[test] +fn test_bundle_add_bytes_and_get_bytes() { + let mut b = Bundle::new(); + b.add_bytes("key", &[1, 2, 3]).unwrap(); + assert_eq!(b.get_bytes("key").unwrap(), &[1, 2, 3]); +} + +#[test] +fn test_bundle_add_str_vec_and_get_str_vec() { + let mut b = Bundle::new(); + b.add_str_vec("key", &["value1", "value2"]).unwrap(); + assert_eq!(b.get_str_vec("key").unwrap(), &["value1", "value2"]); +} + +#[test] +fn test_bundle_add_bytes_vec_and_get_bytes_vec() { + let mut b = Bundle::new(); + b.add_bytes_vec("key", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); + assert_eq!(b.get_bytes_vec("key").unwrap(), &[&[1, 2, 3], &[4, 5, 6]]); +} + +#[test] +fn test_bundle_count() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + b.add_str("key2", "value2").unwrap(); + assert_eq!(b.count(), 2); + b.add_str("key3", "value3").unwrap(); + assert_eq!(b.count(), 3); +} + +#[test] +fn test_bundle_get_type() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + assert_eq!(b.get_type("key1").unwrap(), BundleType::String); + b.add_str_vec("key2", &["value1", "value2"]).unwrap(); + assert_eq!(b.get_type("key2").unwrap(), BundleType::StringVector); + b.add_bytes("key3", &[1, 2, 3]).unwrap(); + assert_eq!(b.get_type("key3").unwrap(), BundleType::Bytes); + b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); + assert_eq!(b.get_type("key4").unwrap(), BundleType::BytesVector); +} + +#[test] +fn test_bundle_clone() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + b.add_str_vec("key2", &["value1", "value2"]).unwrap(); + let mut cloned_b = b.clone(); + assert_eq!(b.get_str("key1").unwrap(), cloned_b.get_str("key1").unwrap()); + assert_eq!(b.get_str_vec("key2").unwrap(), cloned_b.get_str_vec("key2").unwrap()); +} + +#[test] +fn test_bundle_default() { + let mut b = Bundle::default(); + b.add_str("key1", "value1").unwrap(); + assert_eq!(b.get_str("key1").unwrap(), "value1"); +} + +#[test] +fn test_bundle_delete() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + assert_eq!(b.get_str("key1").unwrap(), "value1"); + b.delete("key1").unwrap(); + let ret = b.get_str("key1"); + match (ret) { + Err(err) => assert_eq!(err, BundleError::KeyNotAvailable), + _ => panic!("Unexpected error"), + }; +} + +#[test] +fn test_bundle_iter() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + b.add_str_vec("key2", &["value1", "value2"]).unwrap(); + b.add_bytes("key3", &[1, 2, 3]).unwrap(); + b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); + + for (key, val) in b.iter() { + match val { + BundleValue::String(value) => { + assert_eq!(key, "key1"); + assert_eq!(value, "value1"); + } + BundleValue::StringVector(value) => { + assert_eq!(key, "key2"); + assert_eq!(value, &["value1", "value2"]); + } + BundleValue::Bytes(value) => { + assert_eq!(key, "key3"); + assert_eq!(value, &[1, 2, 3]); + } + BundleValue::BytesVector(value) => { + assert_eq!(key, "key4"); + assert_eq!(value, &[&[1, 2, 3], &[4, 5, 6]]); + } + _ => assert!(false), + } + } +} + +#[test] +fn test_bundle_into_iter() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + b.add_str_vec("key2", &["value1", "value2"]).unwrap(); + b.add_bytes("key3", &[1, 2, 3]).unwrap(); + b.add_bytes_vec("key4", &[&[1, 2, 3], &[4, 5, 6]]).unwrap(); + + for (key, val) in b { + match val { + BundleValue::String(value) => { + assert_eq!(key, "key1"); + assert_eq!(value, "value1"); + } + BundleValue::StringVector(value) => { + assert_eq!(key, "key2"); + assert_eq!(value, &["value1", "value2"]); + } + BundleValue::Bytes(value) => { + assert_eq!(key, "key3"); + assert_eq!(value, &[1, 2, 3]); + } + BundleValue::BytesVector(value) => { + assert_eq!(key, "key4"); + assert_eq!(value, &[&[1, 2, 3], &[4, 5, 6]]); + } + _ => assert!(false), + } + } +} + +#[test] +fn test_bundle_encode_and_decode() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + let mut encoded_str = b.encode().unwrap(); + let mut decoded_b = Bundle::decode(&encoded_str).unwrap(); + assert_eq!(b.get_str("key1").unwrap(), decoded_b.get_str("key1").unwrap()); +} + +#[test] +fn test_bundle_detach() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + let result = b.detach(); + match result { + Ok(handle) => assert!(!handle.is_null()), + Err(err) => panic!("Failed to detach bundle. err: {:?}", err), + } + let handle = b.get_raw_handle(); + assert!(handle.is_null()); +} + +#[test] +fn test_bundle_from_raw_handle() { + let mut b = Bundle::new(); + b.add_str("key1", "value1").unwrap(); + let result = b.detach(); + match result { + Ok(handle) => { + assert!(!handle.is_null()); + let mut b2 = Bundle::from_raw_handle(handle, true); + assert_eq!(b2.get_str("key1").unwrap(), "value1"); + }, + Err(err) => panic!("Failed to detach bundle. err: {:?}", err), + } +} diff --git a/src/rust-tizen-bundle/src/tizen_bundle.rs b/src/rust-tizen-bundle/src/tizen_bundle.rs new file mode 100644 index 0000000..0e62aea --- /dev/null +++ b/src/rust-tizen-bundle/src/tizen_bundle.rs @@ -0,0 +1,818 @@ +extern crate libc; + +use self::libc::{EINVAL, ENOKEY, ENOMEM}; +use std::collections::VecDeque; +use std::ffi::{c_char, c_int, c_uchar, c_uint, c_void, CStr, CString}; +use std::ptr; + +const TIZEN_ERROR_BUNDLE: i32 = -0x01180000; +const BUNDLE_ERROR_NONE: i32 = 0; +const BUNDLE_ERROR_OUT_OF_MEMORY: i32 = -ENOMEM; +const BUNDLE_ERROR_INVALID_PARAMETER: i32 = -EINVAL; +const BUNDLE_ERROR_KEY_NOT_AVAILABLE: i32 = -ENOKEY; +const BUNDLE_ERROR_KEY_EXISTS: i32 = TIZEN_ERROR_BUNDLE | 0x01; +const BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS: i32 = TIZEN_ERROR_BUNDLE | 0x02; + +const BUNDLE_TYPE_ARRAY: i32 = 0x0100; +const BUNDLE_TYPE_MEASURABLE: i32 = 0x0400; +const BUNDLE_TYPE_NONE: i32 = -1; +const BUNDLE_TYPE_ANY: i32 = 0; +const BUNDLE_TYPE_STR: i32 = 1 | BUNDLE_TYPE_MEASURABLE; +const BUNDLE_TYPE_STR_ARRAY: i32 = BUNDLE_TYPE_STR | BUNDLE_TYPE_ARRAY | BUNDLE_TYPE_MEASURABLE; +const BUNDLE_TYPE_BYTE: i32 = 2; +const BUNDLE_TYPE_BYTE_ARRAY: i32 = BUNDLE_TYPE_BYTE | BUNDLE_TYPE_ARRAY; + +#[link(name = "bundle")] +extern "C" { + fn bundle_create() -> *mut c_void; + fn bundle_free(b: *mut c_void) -> c_int; + fn bundle_add_str_array( + b: *mut c_void, + key: *const c_char, + array: *const *const c_char, + len: c_int, + ) -> c_int; + fn bundle_del(b: *mut c_void, key: *const c_char) -> c_int; + fn bundle_get_str_array( + b: *mut c_void, + key: *const c_char, + len: *mut c_int, + ) -> *const *const c_char; + fn bundle_get_count(b: *mut c_void) -> c_int; + fn bundle_get_type(b: *mut c_void, key: *const c_char) -> c_int; + fn bundle_dup(b: *mut c_void) -> *mut c_void; + fn bundle_foreach( + b: *mut c_void, + callback: extern "C" fn(*const c_char, c_int, *const c_void, *mut c_void), + user_data: *mut c_void, + ) -> c_int; + fn bundle_encode(b: *mut c_void, r: *mut *mut c_char, len: *mut c_int) -> c_int; + fn bundle_decode(r: *const c_char, len: c_int) -> *mut c_void; + fn bundle_add_str(b: *mut c_void, key: *const c_char, value: *const c_char) -> c_int; + fn bundle_add_byte( + b: *mut c_void, + key: *const c_char, + bytes: *const c_uchar, + size: c_uint, + ) -> c_int; + fn bundle_get_str(b: *mut c_void, key: *const c_char, val: *mut *mut c_char) -> c_int; + fn bundle_get_byte( + b: *mut c_void, + key: *const c_char, + bytes: *mut *mut c_void, + size: *mut c_uint, + ) -> c_int; + fn bundle_add_byte_array(b: *mut c_void, key: *const c_char, len: c_uint) -> c_int; + fn bundle_set_byte_array_element( + b: *mut c_void, + key: *const c_char, + idx: c_uint, + bytes: *const c_void, + size: c_uint, + ) -> c_int; + fn bundle_get_byte_array( + b: *mut c_void, + key: *const c_char, + byte_array: *mut *mut *mut c_void, + len: *mut c_uint, + array_element_size: *mut *mut c_uint, + ) -> c_int; + fn bundle_keyval_get_basic_val( + kv: *mut c_void, + val: *mut *mut c_void, + size: *mut c_uint, + ) -> c_int; + fn bundle_keyval_get_array_val( + kv: *mut c_void, + array_val: *mut *mut *mut c_void, + array_len: *mut c_uint, + array_element_size: *mut *mut c_uint, + ) -> c_int; +} + +#[link(name = "capi-base-common")] +extern "C" { + fn get_last_result() -> c_int; +} + +/// Represents a value of a bundle. +#[derive(Debug)] +pub enum BundleValue { + /// A string value. + String(String), + /// A vector of strings. + StringVector(Vec), + /// A byte vector. + Bytes(Vec), + /// A vector of byte vectors. + BytesVector(Vec>), +} + +/// Represents an error that can occur when working with a `Bundle`. +#[derive(Debug, PartialEq)] +pub enum BundleError { + /// Out of memory. + /// There is not enough memory to complete the operation. This error occurs when the memory allocation fails. + OutOfMemory, + /// Invalid parameter. + /// The input parameter is invalid. This error occurs when the input parameter is out of range. + InvalidParameter, + /// Key not available. + /// The key does not exist in the bundle. This error occurs when you try to get a value with a non-existent key. + KeyNotAvailable, + /// Key exists. + /// The key already exists in the bundle. This error occurs when you try to add a key that already exists. + KeyExists, + /// The index is out of bounds of the array. + ArrayIndexOutOfBounds, + /// No ownership. + /// The bundle does not own the data. This error occurs when you try to detach the data that was not allocated by the bundle. + NoOwnership, +} + +impl BundleError { + fn from_c_int(result: c_int) -> BundleError { + match result { + BUNDLE_ERROR_OUT_OF_MEMORY => BundleError::OutOfMemory, + BUNDLE_ERROR_INVALID_PARAMETER => BundleError::InvalidParameter, + BUNDLE_ERROR_KEY_NOT_AVAILABLE => BundleError::KeyNotAvailable, + BUNDLE_ERROR_KEY_EXISTS => BundleError::KeyExists, + BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS => BundleError::ArrayIndexOutOfBounds, + _ => panic!("Unexpected error code {}", result), + } + } +} + +/// Represents a type of a bundle key. +#[derive(Debug, PartialEq)] +pub enum BundleType { + /// None. + None, + /// Any type. + Any, + /// A string type. + String, + /// A vector of strings. + StringVector, + /// Bytes type. + Bytes, + /// A vector of bytes. + BytesVector, +} + +impl BundleType { + fn from_c_int(key_type: c_int) -> BundleType { + match key_type { + BUNDLE_TYPE_NONE => BundleType::None, + BUNDLE_TYPE_ANY => BundleType::Any, + BUNDLE_TYPE_STR => BundleType::String, + BUNDLE_TYPE_STR_ARRAY => BundleType::StringVector, + BUNDLE_TYPE_BYTE => BundleType::Bytes, + BUNDLE_TYPE_BYTE_ARRAY => BundleType::BytesVector, + _ => panic!("Unexpected type code: {}", key_type), + } + } +} + +/// A representation of a Bundle, which is a key-value pair container. +#[derive(Debug)] +pub struct Bundle { + handle: *mut c_void, + ownership: bool, +} + +impl Clone for Bundle { + fn clone(&self) -> Self { + let handle = unsafe { bundle_dup(self.handle) }; + Self { handle, ownership: true } + } +} + +impl Drop for Bundle { + fn drop(&mut self) { + if self.ownership && !self.handle.is_null() { + unsafe { + bundle_free(self.handle); + } + } + } +} + +impl Default for Bundle { + fn default() -> Self { + Self::new() + } +} + +impl Bundle { + /// Creates a new `Bundle` instance. + /// + /// # Panics + /// + /// This function will panic if the creation of a `Bundle` fails. + pub fn new() -> Self { + let handle = unsafe { bundle_create() }; + if handle.is_null() { + panic!("Failed to create bundle"); + } + Self { handle, ownership: true } + } + + /// Creates a new `Bundle` instance from a raw handle. + /// + /// # Arguments + /// + /// * `b`: The raw handle to the bundle. + /// * `ownership`: Whether or not the `Bundle` should take ownership of the raw handle. If `false`, the caller retains ownership and the `Bundle` will not free the handle when it is dropped. + /// + /// # Panics + /// + /// This function panics if the provided handle is null. + pub fn from_raw_handle(b: *mut c_void, ownership: bool) -> Self { + if b.is_null() { + panic!("Bundle pointer is null"); + } + Self { handle: b, ownership } + } + + /// Gets a raw handle from the `Bundle`. + /// + /// # Returns + /// + /// A raw handle of the `Bundle`. + pub fn get_raw_handle(&self) -> *mut c_void { + self.handle + } + + /// Detaches the raw handle from the `Bundle` and returns it. + /// + /// # Returns + /// + /// Returns `Ok(*mut c_void)` on success, or an appropriate `Err(BundleError)` on failure. + /// If the `Bundle` does not own the raw handle, this function returns `Err(BundleError)`. Otherwise, + pub fn detach(&mut self) -> Result<*mut c_void, BundleError> { + if self.ownership { + let handle = self.handle; + self.handle = std::ptr::null_mut(); + self.ownership = false; + Ok(handle) + } else { + Err(BundleError::NoOwnership) + } + } + + /// Deletes a value associated with the given key. + /// + /// # Arguements + /// + /// * `key` - The key to be deleted. It must be a valid UTF-8 string. If not, this function will return an error. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failrue. + pub fn delete(&mut self, key: &str) -> Result<(), BundleError> { + let c_key = CString::new(key).unwrap(); + let result = unsafe { bundle_del(self.handle, c_key.as_ptr()) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Gets the number of elements in the `Bundle`. + /// + /// # Returns + /// + /// The number of elements. + pub fn count(&self) -> i32 { + (unsafe { bundle_get_count(self.handle) }) as i32 + } + + /// Adds a string to the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key of the element. + /// * `value` - The value of the element. This must be a valid UTF-8 encoded string. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. + pub fn add_str(&mut self, key: &str, value: &str) -> Result<(), BundleError> { + let c_key = CString::new(key).unwrap(); + let c_value = CString::new(value).unwrap(); + let result = unsafe { bundle_add_str(self.handle, c_key.as_ptr(), c_value.as_ptr()) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Gets a string with the given key from the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key to retrieve the value for. + /// + /// # Returns + /// + /// Returns `Ok(String)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn get_str(&self, key: &str) -> Result { + let c_key = CString::new(key).unwrap(); + let mut c_val: *mut c_char = ptr::null_mut(); + let result = unsafe { bundle_get_str(self.handle, c_key.as_ptr(), &mut c_val) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + let c_str = unsafe { CStr::from_ptr(c_val) }; + Ok(c_str.to_string_lossy().into_owned()) + } + } + + /// Adds a vector of strings to the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key of the element. + /// * `value` - The vector of strings. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. + pub fn add_str_vec(&mut self, key: &str, values: &[&str]) -> Result<(), BundleError> { + let c_key = CString::new(key).unwrap(); + let c_array: Vec = values.iter().map(|&s| CString::new(s).unwrap()).collect(); + let c_ptr_array: Vec<*const c_char> = c_array.iter().map(|s| s.as_ptr()).collect(); + let result = unsafe { + bundle_add_str_array( + self.handle, + c_key.as_ptr(), + c_ptr_array.as_ptr(), + c_array.len() as c_int, + ) + }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Gets a vector of strings with the given key from the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key to retrieve the value for. + /// + /// # Returns + /// + /// Returns `Ok(Vec)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn get_str_vec(&self, key: &str) -> Result, BundleError> { + let c_key = CString::new(key).unwrap(); + let mut len: c_int = 0; + let c_array_ptr = unsafe { bundle_get_str_array(self.handle, c_key.as_ptr(), &mut len) }; + if c_array_ptr.is_null() { + return Err(BundleError::from_c_int(unsafe { get_last_result() })); + } + + let mut result = Vec::with_capacity(len as usize); + for i in 0..len { + let c_str_ptr = unsafe { *c_array_ptr.add(i as usize) }; + let c_str = unsafe { CStr::from_ptr(c_str_ptr) }; + result.push(c_str.to_string_lossy().into_owned()); + } + Ok(result) + } + + /// Adds bytes to the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key of the element. + /// * `value` - The bytes of the element. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. + pub fn add_bytes(&mut self, key: &str, bytes: &[u8]) -> Result<(), BundleError> { + let c_key = CString::new(key).unwrap(); + let result = unsafe { + bundle_add_byte( + self.handle, + c_key.as_ptr(), + bytes.as_ptr(), + bytes.len() as c_uint, + ) + }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Gets bytes with the given key from the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key to retrieve the value for. + /// + /// # Returns + /// + /// Returns `Ok(Vec)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn get_bytes(&self, key: &str) -> Result, BundleError> { + let c_key = CString::new(key).unwrap(); + let mut bytes_ptr: *mut c_void = ptr::null_mut(); + let mut size: c_uint = 0; + let result = + unsafe { bundle_get_byte(self.handle, c_key.as_ptr(), &mut bytes_ptr, &mut size) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(unsafe { + std::slice::from_raw_parts(bytes_ptr as *const u8, size as usize).to_vec() + }) + } + } + + /// Adds a vector of bytes to the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key of the element. + /// * `value` - The vector of bytes. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(BundleError)` on failure. + pub fn add_bytes_vec(&mut self, key: &str, elements: &[&[u8]]) -> Result<(), BundleError> { + let c_key = CString::new(key).unwrap(); + let array_len = elements.len() as c_uint; + let result = unsafe { bundle_add_byte_array(self.handle, c_key.as_ptr(), array_len) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + for (idx, element) in elements.iter().enumerate() { + let result = unsafe { + bundle_set_byte_array_element( + self.handle, + c_key.as_ptr(), + idx as c_uint, + element.as_ptr() as *const c_void, + element.len() as c_uint, + ) + }; + if result != 0 { + return Err(BundleError::from_c_int(result)); + } + } + Ok(()) + } + } + + /// Gets a vector of bytes with the given key from the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key to retrieve the value for. + /// + /// # Returns + /// + /// Returns `Ok(Vec>)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn get_bytes_vec(&self, key: &str) -> Result>, BundleError> { + let c_key = CString::new(key).unwrap(); + let mut byte_array_ptr: *mut *mut c_void = ptr::null_mut(); + let mut len: c_uint = 0; + let mut array_element_size: *mut c_uint = ptr::null_mut(); + let result = unsafe { + bundle_get_byte_array( + self.handle, + c_key.as_ptr(), + &mut byte_array_ptr, + &mut len, + &mut array_element_size, + ) + }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + let byte_array = unsafe { std::slice::from_raw_parts(byte_array_ptr, len as usize) }; + let element_sizes = + unsafe { std::slice::from_raw_parts(array_element_size, len as usize) }; + let mut bytes = Vec::with_capacity(len as usize); + for i in 0..len as usize { + let element_size = element_sizes[i] as usize; + let element = + unsafe { std::slice::from_raw_parts(byte_array[i] as *const u8, element_size) }; + bytes.push(element.to_vec()); + } + + Ok(bytes) + } + } + + /// Gets the type of a given key in the `Bundle`. + /// + /// # Arguments + /// + /// * `key` - The key to retrieve the value type for. + /// + /// # Returns + /// + /// Returns `Ok(BundleType)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn get_type(&self, key: &str) -> Result { + let c_key = CString::new(key).unwrap(); + let result = unsafe { bundle_get_type(self.handle, c_key.as_ptr()) }; + if result < BUNDLE_TYPE_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(BundleType::from_c_int(result)) + } + } + + /// Encode the bundle to a string.(uses base64 format). + /// + /// # Returns + /// + /// Returns `Ok(String)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn encode(&self) -> Result { + let mut raw: *mut c_char = std::ptr::null_mut(); + let mut len: c_int = 0; + let result = unsafe { bundle_encode(self.handle, &mut raw, &mut len) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(unsafe { CStr::from_ptr(raw as *const c_char) } + .to_string_lossy() + .into_owned()) + } + } + + /// Creates a new `Bundle` from the given encoded string. + /// The string must be in the format returned by `encode`. If the string is invalid, an error will be returned. + /// + /// # Arguments + /// + /// * `raw` - The encoded string to decode. This must be in the format returned by `encode`. + /// + /// # Returns + /// + /// Returns `Ok(Bundle)` on success, or an appropriate `Err(BundleError)` on failure. + pub fn decode(raw: &str) -> Result { + let c_raw = CString::new(raw).unwrap(); + let handle = unsafe { bundle_decode(c_raw.as_ptr() as *const c_char, raw.len() as c_int) }; + if handle.is_null() { + Err(BundleError::from_c_int(unsafe { get_last_result() })) + } else { + Ok(Bundle { handle, ownership: true }) + } + } + + /// Iterates over the keys and values of the `Bundle`. + /// + /// # Returns + /// + /// An iterator over the keys and values of the `Bundle`. + pub fn iter(&self) -> BundleIter { + let mut bundle_iter = BundleIter { + bundle: self, + items: VecDeque::new(), + }; + bundle_iter.populate_items(); + bundle_iter + } +} + +#[derive(Debug)] +struct KeyInfo { + key: String, + key_type: BundleType, + handle: *mut c_void, +} + +impl KeyInfo { + fn new(key: &str, key_type: BundleType, handle: *mut c_void) -> Self { + KeyInfo { + key: key.to_string(), + key_type, + handle, + } + } + + fn get_str(&self) -> Result { + let mut val: *mut c_void = std::ptr::null_mut(); + let mut size: c_uint = 0; + let result = unsafe { bundle_keyval_get_basic_val(self.handle, &mut val, &mut size) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(unsafe { + CStr::from_ptr(val as *const c_char) + .to_string_lossy() + .into_owned() + }) + } + } + + fn get_str_vec(&self) -> Result, BundleError> { + let mut array_val: *mut *mut c_void = std::ptr::null_mut(); + let mut array_len: c_uint = 0; + let mut array_element_size: *mut c_uint = std::ptr::null_mut(); + let result = unsafe { + bundle_keyval_get_array_val( + self.handle, + &mut array_val, + &mut array_len, + &mut array_element_size, + ) + }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + let mut values = Vec::with_capacity(array_len as usize); + for i in 0..array_len { + let c_str_ptr = unsafe { *array_val.add(i as usize) }; + let c_str = unsafe { CStr::from_ptr(c_str_ptr as *const c_char) }; + values.push(c_str.to_string_lossy().into_owned()); + } + Ok(values) + } + } + + fn get_bytes(&self) -> Result, BundleError> { + let mut val: *mut c_void = std::ptr::null_mut(); + let mut size: c_uint = 0; + let result = unsafe { bundle_keyval_get_basic_val(self.handle, &mut val, &mut size) }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + Ok(unsafe { std::slice::from_raw_parts(val as *const u8, size as usize).to_vec() }) + } + } + + fn get_bytes_vec(&self) -> Result>, BundleError> { + let mut array_val: *mut *mut c_void = std::ptr::null_mut(); + let mut array_len: c_uint = 0; + let mut array_element_size: *mut c_uint = std::ptr::null_mut(); + let result = unsafe { + bundle_keyval_get_array_val( + self.handle, + &mut array_val, + &mut array_len, + &mut array_element_size, + ) + }; + if result != BUNDLE_ERROR_NONE { + Err(BundleError::from_c_int(result)) + } else { + let byte_array = unsafe { std::slice::from_raw_parts(array_val, array_len as usize) }; + let element_sizes = + unsafe { std::slice::from_raw_parts(array_element_size, array_len as usize) }; + let mut bytes_vec = Vec::with_capacity(array_len as usize); + for i in 0..array_len as usize { + let element_size = element_sizes[i] as usize; + let element = + unsafe { std::slice::from_raw_parts(byte_array[i] as *const u8, element_size) }; + bytes_vec.push(element.to_vec()); + } + Ok(bytes_vec) + } + } + + fn get_item(&self) -> Result<(String, BundleValue), BundleError> { + match self.key_type { + BundleType::String => { + let value = self.get_str(); + match value { + Ok(v) => Ok((self.key.clone(), BundleValue::String(v))), + Err(err) => Err(err), + } + } + BundleType::StringVector => { + let value = self.get_str_vec(); + match value { + Ok(v) => Ok((self.key.clone(), BundleValue::StringVector(v))), + Err(err) => Err(err), + } + } + BundleType::Bytes => { + let value = self.get_bytes(); + match value { + Ok(v) => Ok((self.key.clone(), BundleValue::Bytes(v))), + Err(err) => Err(err), + } + } + BundleType::BytesVector => { + let value = self.get_bytes_vec(); + match value { + Ok(v) => Ok((self.key.clone(), BundleValue::BytesVector(v))), + Err(err) => Err(err), + } + } + _ => Err(BundleError::KeyNotAvailable), + } + } +} + +extern "C" fn foreach_callback( + key: *const c_char, + key_type: c_int, + key_value: *const c_void, + user_data: *mut c_void, +) { + let items: &mut VecDeque<(String, BundleValue)> = + unsafe { &mut *(user_data as *mut VecDeque<(String, BundleValue)>) }; + let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap().to_string() }; + let key_info = KeyInfo::new( + &key_str, + BundleType::from_c_int(key_type), + key_value as *mut c_void, + ); + let item = key_info.get_item(); + match item { + Ok(i) => items.push_back(i), + Err(err) => println!( + "Error while creating key info: {:?}, error: {:?}", + key_info, err + ), + } +} + +/// Iterator for Bundle. Iterates over all the keys and values in a bundle. +pub struct BundleIter<'a> { + bundle: &'a Bundle, + items: VecDeque<(String, BundleValue)>, +} + +impl<'a> BundleIter<'a> { + fn populate_items(&mut self) { + let user_data: *mut VecDeque<(String, BundleValue)> = &mut self.items; + unsafe { + bundle_foreach( + self.bundle.handle, + foreach_callback, + user_data as *mut c_void, + ); + } + } +} + +impl<'a> Iterator for BundleIter<'a> { + type Item = (String, BundleValue); + + fn next(&mut self) -> Option { + self.items.pop_front() + } +} + +impl<'a> IntoIterator for &'a Bundle { + type Item = (String, BundleValue); + type IntoIter = BundleIter<'a>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl IntoIterator for Bundle { + type Item = (String, BundleValue); + type IntoIter = BundleIntoIter; + + fn into_iter(self) -> Self::IntoIter { + let mut iter = BundleIntoIter { + bundle: self, + items: VecDeque::new(), + }; + iter.populate_items(); + iter + } +} + +/// IntoIterator for Bundle. +pub struct BundleIntoIter { + bundle: Bundle, + items: VecDeque<(String, BundleValue)>, +} + +impl BundleIntoIter { + fn populate_items(&mut self) { + let user_data: *mut VecDeque<(String, BundleValue)> = &mut self.items; + unsafe { + bundle_foreach( + self.bundle.handle, + foreach_callback, + user_data as *mut c_void, + ); + } + } +} + +impl Iterator for BundleIntoIter { + type Item = (String, BundleValue); + + fn next(&mut self) -> Option { + self.items.pop_front() + } +} diff --git a/src/rust-tizen-parcel/Cargo.toml b/src/rust-tizen-parcel/Cargo.toml new file mode 100644 index 0000000..e04c86a --- /dev/null +++ b/src/rust-tizen-parcel/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust-parcel" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = [ "dylib" ] +crate-name = [ "parcel" ] diff --git a/src/rust-tizen-parcel/src/lib.rs b/src/rust-tizen-parcel/src/lib.rs new file mode 100644 index 0000000..6d74dea --- /dev/null +++ b/src/rust-tizen-parcel/src/lib.rs @@ -0,0 +1,5 @@ +pub mod tizen_parcel; + +pub use crate::tizen_parcel::{Parcel}; + +mod tests; diff --git a/src/rust-tizen-parcel/src/tests/mod.rs b/src/rust-tizen-parcel/src/tests/mod.rs new file mode 100644 index 0000000..efee9e7 --- /dev/null +++ b/src/rust-tizen-parcel/src/tests/mod.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +pub mod tizen_parcel_tests; diff --git a/src/rust-tizen-parcel/src/tests/tizen_parcel_tests.rs b/src/rust-tizen-parcel/src/tests/tizen_parcel_tests.rs new file mode 100644 index 0000000..f172b89 --- /dev/null +++ b/src/rust-tizen-parcel/src/tests/tizen_parcel_tests.rs @@ -0,0 +1,134 @@ +use tizen_parcel; + +#[warn(unused_imports)] +use tizen_parcel::{Parcel, ParcelError}; + +#[test] +fn test_parcel_write_bool_and_read_bool() { + let mut parcel = Parcel::new(); + parcel.write_bool(true); + let result = parcel.read_bool().unwrap(); + assert_eq!(result, true); +} + +#[test] +fn test_parcel_write_i8_and_read_i8() { + let mut parcel = Parcel::new(); + parcel.write_i8(1); + let result = parcel.read_i8().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_i16_and_read_i16() { + let mut parcel = Parcel::new(); + parcel.write_i16(1); + let result = parcel.read_i16().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_i32_and_read_i32() { + let mut parcel = Parcel::new(); + parcel.write_i32(1); + let result = parcel.read_i32().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_i64_and_read_i64() { + let mut parcel = Parcel::new(); + parcel.write_i64(1); + let result = parcel.read_i64().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_u16_and_read_u16() { + let mut parcel = Parcel::new(); + parcel.write_u16(1); + let result = parcel.read_u16().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_u32_and_read_u32() { + let mut parcel = Parcel::new(); + parcel.write_u32(1); + let result = parcel.read_u32().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_u64_and_read_u64() { + let mut parcel = Parcel::new(); + parcel.write_u64(1); + let result = parcel.read_u64().unwrap(); + assert_eq!(result, 1); +} + +#[test] +fn test_parcel_write_f32_and_read_f32() { + let mut parcel = Parcel::new(); + parcel.write_f32(1.0); + let result = parcel.read_f32().unwrap(); + assert_eq!(result, 1.0); +} + +#[test] +fn test_parcel_write_f64_and_read_f64() { + let mut parcel = Parcel::new(); + parcel.write_f64(1.0); + let result = parcel.read_f64().unwrap(); + assert_eq!(result, 1.0); +} + +#[test] +fn test_parcel_write_string_and_read_string() { + let mut parcel = Parcel::new(); + parcel.write_string("test"); + let result = parcel.read_string().unwrap(); + assert_eq!(result, "test"); +} + +#[test] +fn test_parcel_reset_reader() { + let mut parcel = Parcel::new(); + parcel.write_i32(1); + parcel.write_i32(2); + assert_eq!(parcel.read_i32().unwrap(), 1); + parcel.reset_reader(); + assert_eq!(parcel.read_i32().unwrap(), 1); + assert_eq!(parcel.read_i32().unwrap(), 2); +} + +#[test] +fn test_parcel_clear() { + let mut parcel = Parcel::new(); + parcel.write_i32(1); + parcel.clear(); + match parcel.read_i32() { + Err(err) => { + assert_eq!(err, ParcelError::NoData); + }, + _ => panic!("Expected error"), + }; +} + +#[test] +fn test_parcel_reset() { + let mut parcel = Parcel::new(); + parcel.reset(&[b'P']); + let res = parcel.read(1).unwrap(); + assert_eq!(res, [b'P']); +} + +#[test] +fn test_parcel_get_raw_data() { + let mut parcel = Parcel::new(); + parcel.write_i32(1); + parcel.write_i32(2); + let data = parcel.get_raw_data().unwrap(); + assert_ne!(data.len(), 0); + assert_eq!(data, vec![1, 0, 0, 0, 2, 0, 0, 0]); +} diff --git a/src/rust-tizen-parcel/src/tizen_parcel.rs b/src/rust-tizen-parcel/src/tizen_parcel.rs new file mode 100644 index 0000000..c77e9d5 --- /dev/null +++ b/src/rust-tizen-parcel/src/tizen_parcel.rs @@ -0,0 +1,609 @@ +extern crate libc; + +use self::libc::{EILSEQ, EINVAL, ENODATA, ENOMEM}; +use std::ffi::{ + c_char, c_double, c_float, c_int, c_longlong, c_short, c_uchar, c_uint, c_ulonglong, c_ushort, + c_void, CString, +}; +use std::ptr; + +const PARCEL_ERROR_NONE: i32 = 0; +const PARCEL_ERROR_ILLEGAL_BYTE_SEQ: i32 = -EILSEQ; +const PARCEL_ERROR_INVALID_PARAMETER: i32 = -EINVAL; +const PARCEL_ERROR_NO_DATA: i32 = -ENODATA; +const PARCEL_ERROR_OUT_OF_MEMORY: i32 = -ENOMEM; + +#[link(name = "parcel")] +extern "C" { + fn parcel_create(parcel: *mut *mut c_void) -> c_int; + fn parcel_destroy(parcel: *mut c_void) -> c_int; + fn parcel_clone(parcel: *const c_void, clone: *mut *mut c_void) -> c_int; + fn parcel_burst_write(parcel: *mut c_void, buf: *const c_uchar, size: usize) -> c_int; + fn parcel_burst_read(parcel: *mut c_void, buf: *mut c_uchar, size: usize) -> c_int; + fn parcel_write_bool(parcel: *mut c_void, val: c_int) -> c_int; + fn parcel_write_byte(parcel: *mut c_void, val: c_char) -> c_int; + fn parcel_write_uint16(parcel: *mut c_void, val: c_ushort) -> c_int; + fn parcel_write_uint32(parcel: *mut c_void, val: c_uint) -> c_int; + fn parcel_write_uint64(parcel: *mut c_void, val: c_ulonglong) -> c_int; + fn parcel_write_int16(parcel: *mut c_void, val: c_short) -> c_int; + fn parcel_write_int32(parcel: *mut c_void, val: c_int) -> c_int; + fn parcel_write_int64(parcel: *mut c_void, val: c_longlong) -> c_int; + fn parcel_write_float(parcle: *mut c_void, val: c_float) -> c_int; + fn parcel_write_double(parcel: *mut c_void, val: c_double) -> c_int; + fn parcel_write_string(parcel: *mut c_void, val: *const c_char) -> c_int; + fn parcel_read_bool(parcel: *mut c_void, val: *mut c_int) -> c_int; + fn parcel_read_byte(parcel: *mut c_void, val: *mut c_char) -> c_int; + fn parcel_read_uint16(parcel: *mut c_void, val: *mut c_ushort) -> c_int; + fn parcel_read_uint32(parcel: *mut c_void, val: *mut c_uint) -> c_int; + fn parcel_read_uint64(parcel: *mut c_void, val: *mut c_ulonglong) -> c_int; + fn parcel_read_int16(parcel: *mut c_void, val: *mut c_short) -> c_int; + fn parcel_read_int32(parcel: *mut c_void, val: *mut c_int) -> c_int; + fn parcel_read_int64(parcel: *mut c_void, val: *mut c_longlong) -> c_int; + fn parcel_read_float(parcel: *mut c_void, val: *mut c_float) -> c_int; + fn parcel_read_double(parcel: *mut c_void, val: *mut c_double) -> c_int; + fn parcel_read_string(parcel: *mut c_void, val: *mut *mut c_char) -> c_int; + fn parcel_reset_reader(parcel: *mut c_void) -> c_int; + fn parcel_clear(parcel: *mut c_void) -> c_int; + fn parcel_reset(parcel: *mut c_void, buf: *const c_void, size: c_uint) -> c_int; + fn parcel_get_raw(parcel: *mut c_void, buf: *mut *mut c_void, size: *mut c_uint) -> c_int; +} + +/// Represents errors that can occur when working with a `Parcel`. +#[derive(Debug, PartialEq)] +pub enum ParcelError { + /// Illegal byte sequence. + /// The data in the parcel is not valid. + /// This error occurs when the data is not encoded properly or the data is corrupted. + IllegalByteSeq, + /// Invalid parameter. + /// The input parameter is invalid. This error occurs when the input parameter is out of range. + InvalidParameter, + /// No data available. + /// There is no data to read. This error occurs when there is no more data to read from the parcel. + NoData, + /// Out of memory. + /// There is not enough memory to complete the operation. This error occurs when the memory allocation fails. + OutOfMemory, +} + +impl ParcelError { + fn from_c_int(result: c_int) -> ParcelError { + match result { + PARCEL_ERROR_ILLEGAL_BYTE_SEQ => ParcelError::IllegalByteSeq, + PARCEL_ERROR_INVALID_PARAMETER => ParcelError::InvalidParameter, + PARCEL_ERROR_NO_DATA => ParcelError::NoData, + PARCEL_ERROR_OUT_OF_MEMORY => ParcelError::OutOfMemory, + _ => panic!("Unexpected error code {}", result), + } + } +} + +/// A representation of a Parcel, which is used for serializing and deserializing data. +#[derive(Debug)] +pub struct Parcel { + handle: *mut c_void, +} + +/// A trait that defines how a type can be serialized to and deserialized from a Parcel. +pub trait Parcelable { + fn to_parcel(&self) -> Parcel; + fn from_parcel(parcel: &mut Parcel) -> T; +} + +impl Clone for Parcel { + fn clone(&self) -> Self { + let mut clone_handle: *mut c_void = ptr::null_mut(); + unsafe { + let result = parcel_clone(self.handle, &mut clone_handle); + assert!(result == PARCEL_ERROR_NONE, "Failed to clone a parcel") + }; + Self { + handle: clone_handle, + } + } +} + +impl Drop for Parcel { + fn drop(&mut self) { + unsafe { + parcel_destroy(self.handle); + } + } +} + +impl Default for Parcel { + fn default() -> Self { + Self::new() + } +} + +impl Parcel { + /// Creates a new `Parcel` instance. + /// + /// # Panics + /// + /// This function will panic if the creation of a `Parcel` fails. + pub fn new() -> Self { + let mut handle: *mut c_void = ptr::null_mut(); + unsafe { + let result = parcel_create(&mut handle); + assert!(result == PARCEL_ERROR_NONE, "Failed to create a parcel"); + } + Self { handle } + } + + /// Writes a byte slice to the `Parcel`. + /// + /// # Arguments + /// + /// * `data` - A slice of bytes to be written to the `Parcel`. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write(&mut self, data: &[u8]) -> Result<(), ParcelError> { + let result = unsafe { + parcel_burst_write(self.handle, data.as_ptr(), data.len()) + }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Reads a byte slice from the `Parcel`. + /// + /// # Arguments + /// + /// * `size` - The number of bytes to read from the `Parcel`. + /// + /// # Returns + /// + /// Returns a `Vec` containing the data read on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read(&mut self, size: usize) -> Result, ParcelError> { + let mut data = vec![0; size]; + let result = unsafe { parcel_burst_read(self.handle, data.as_mut_ptr(), data.len()) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(data) + } + } + + /// Gets the raw data from the `Parcel`. + /// + /// # Returns + /// + /// Returns a `Vec` containing the raw data on success, or an appropriate `Err(ParcelError)` on failure. + pub fn get_raw_data(&self) -> Result, ParcelError> { + let mut size = 0; + let mut raw: *mut c_void = ptr::null_mut(); + let result = unsafe { parcel_get_raw(self.handle, &mut raw, &mut size) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + let mut data = vec![0; size as usize]; + unsafe { + std::ptr::copy(raw as *const u8, data.as_mut_ptr(), size as usize); + } + Ok(data) + } + } + + /// Resets the reader position of the `Parcel`. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn reset_reader(&mut self) -> Result<(), ParcelError> { + let result = unsafe { parcel_reset_reader(self.handle) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Clears the contents of the `Parcel`. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn clear(&mut self) -> Result<(), ParcelError> { + let result = unsafe { parcel_clear(self.handle) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Resets the `Parcel` with the provided data. + /// + /// # Arguments + /// + /// * `data` - The slice of bytes to reset the `Parcel`. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn reset(&mut self, data: &[u8]) -> Result<(), ParcelError> { + let result = unsafe { + parcel_reset( + self.handle, + data.as_ptr() as *const c_void, + data.len() as c_uint, + ) + }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a boolean value to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The boolean value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_bool(&mut self, val: bool) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_bool(self.handle, val as c_int) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 8-bit integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 8-bit integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_i8(&mut self, val: i8) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_byte(self.handle, val as c_char) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 16-bit integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 16-bit integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_i16(&mut self, val: i16) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_int16(self.handle, val as c_short) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 32-bit integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 32-bit integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_i32(&mut self, val: i32) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_int32(self.handle, val as c_int) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 64-bit integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 64-bit integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_i64(&mut self, val: i64) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_int64(self.handle, val as c_longlong) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 16-bit unsigned integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 16-bit unsigned integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_u16(&mut self, val: u16) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_uint16(self.handle, val as c_ushort) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 32-bit unsigned integer to the `Parcel`. + /// + /// # Arguments + /// + /// * `val` - The 32-bit unsigned integer value to be written. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_u32(&mut self, val: u32) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_uint32(self.handle, val as c_uint) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 64-bit unsigned integer to the parcel. + /// + /// # Arguments + /// + /// * `val` - The 64-bit unsigned integer value to write. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_u64(&mut self, val: u64) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_uint64(self.handle, val as c_ulonglong) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 32-bit floating point to the parcel. + /// + /// # Arguments + /// + /// * `val` - The 32-bit floating point value to write. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_f32(&mut self, val: f32) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_float(self.handle, val) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a 64-bit floating point to the parcel. + /// + /// # Arguments + /// + /// * `val` - The 64-bit floating point value to write. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_f64(&mut self, val: f64) -> Result<(), ParcelError> { + let result = unsafe { parcel_write_double(self.handle, val) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Writes a string to the parcel. + /// + /// # Arguments + /// + /// * `val` - The string value to write. + /// + /// # Returns + /// + /// Returns `Ok(())` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn write_string(&mut self, val: &str) -> Result<(), ParcelError> { + let ptr = CString::new(val).unwrap(); + let result = unsafe { parcel_write_string(self.handle, ptr.as_ptr() as *const c_char) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(()) + } + } + + /// Reads a boolean from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(bool)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_bool(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_bool(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value != 0) + } + } + + /// Reads a 8-bit interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(i8)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_i8(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_byte(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value as i8) + } + } + + /// Reads a 16-bit interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(i16)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_i16(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_int16(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 32-bit interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(i32)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_i32(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_int32(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 64-bit interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(i64)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_i64(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_int64(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 16-bit unsigned interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(u16)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_u16(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_uint16(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 32-bit unsigned interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(u32)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_u32(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_uint32(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 64-bit unsigned interger from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(u64)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_u64(&mut self) -> Result { + let mut value = 0; + let result = unsafe { parcel_read_uint64(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 32-bit floating point from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(f32)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_f32(&mut self) -> Result { + let mut value = 0.0; + let result = unsafe { parcel_read_float(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a 64-bit floating point from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(f64)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_f64(&mut self) -> Result { + let mut value = 0.0; + let result = unsafe { parcel_read_double(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(value) + } + } + + /// Reads a string from the parcel. + /// + /// # Returns + /// + /// Returns `Ok(String)` on success, or an appropriate `Err(ParcelError)` on failure. + pub fn read_string(&mut self) -> Result { + let mut value: *mut c_char = ptr::null_mut(); + let result = unsafe { parcel_read_string(self.handle, &mut value) }; + if result != PARCEL_ERROR_NONE { + Err(ParcelError::from_c_int(result)) + } else { + Ok(unsafe { CString::from_raw(value).into_string().unwrap() }) + } + } +}