BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(gmock)
+BuildRequires: rust
+BuildRequires: rust-libc
+BuildRequires: rust-glib-sys
+BuildRequires: rust-mockall
+BuildRequires: rust-mockall_double
+BuildRequires: zip
+BuildRequires: cargo
+
%if 0%{?gcov:1}
BuildRequires: lcov
-BuildRequires: zip
%endif
%description
%description -n tizen-shared-queue-unittests
GTest for tizen-shared-queue
+#################################################
+# rust-tizen-base
+#################################################
+%package -n rust-tizen-base
+Summary: Library for Tizen rust applications
+Group: Development/Libraries
+
+%description -n rust-tizen-base
+Libraries for Tizen rust applications
+
%prep
%setup -q -n %{name}-%{version}
cp %{SOURCE1001} .
cp %{SOURCE1002} .
+cp %{SOURCE1001} ./rust-tizen-base.manifest
%build
%if 0%{?gcov:1}
%endif
MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
-%cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+%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" \
+ -L native="./src/bundle" \
+ %{?rustc_edition:--edition=%{rustc_edition}} \
+ %rust_dylib_extern libc \
+ src/rust-tizen-base/src/lib.rs
+
+%{rustc_std_build} --test --crate-type=bin \
+ --crate-name=tizen_base_unittests \
+ -L native="./src/parcel" \
+ -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
+
%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
+
%if 0%{?gcov:1}
lcov -c --ignore-errors mismatch,graph,unused --no-external -b . -d . -o %{name}.info
genhtml %{name}.info -o out --legend --show-details
install -m 0755 run-unittest.sh %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue/
sed -i -e 's/<NAME>/tizen-shared-queue/g' %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue/run-unittest.sh
+zip libtizen_base.zip libtizen_base.so
+install -d -m 0755 %{buildroot}%{_rust_dylibdir}
+install -m 0644 libtizen_base.zip %{buildroot}/%{_rust_dylibdir}/libtizen_base.zip
+
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%{_bindir}/bundle_unittests
%endif
+%post -n rust-tizen-base
+/sbin/ldconfig
+
+unzip %{_rust_dylibdir}/libtizen_base.zip -d %{_rust_dylibdir}/
+rm %{_rust_dylibdir}/libtizen_base.zip
+
+%postun -n rust-tizen-base
+/sbin/ldconfig
+
%files
%manifest %{name}.manifest
%defattr(-,root,root,-)
%files -n tizen-shared-queue-unittests
%{_bindir}/tizen-shared-queue_unittests
%{_bindir}/tizen-unittests/tizen-shared-queue/run-unittest.sh
+
+#################################################
+# rust-tizen-base
+#################################################
+%files -n rust-tizen-base
+%manifest rust-tizen-base.manifest
+%license LICENSE
+%{_rust_dylibdir}/libtizen_base.zip
#include <glib.h>
+#include <iostream>
#include <exception>
#include <mutex>
template <typename T>
int Parcel::Impl::Read(T* d) {
+ if (data_size_ == 0)
+ return TIZEN_ERROR_NO_DATA;
+
uint32_t size = static_cast<uint32_t>(sizeof(T));
if (reader_ + size > data_size_)
return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
data_ = nullptr;
data_capacity_ = 0;
data_size_ = 0;
- reader_= 0;
+ reader_ = 0;
return data;
}
impl_->Write(buf, size);
}
-Parcel::~Parcel() {};
+Parcel::~Parcel() {}
Parcel::Parcel(const Parcel& p)
: impl_(new Impl(this, kDataCapacity)) {
--- /dev/null
+[package]
+name = "rust-tizen-base"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = [ "dylib" ]
+crate-name = [ "tizen_base" ]
--- /dev/null
+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<String>),
+ /// A byte vector.
+ Bytes(Vec<u8>),
+ /// A vector of byte vectors.
+ BytesVector(Vec<Vec<u8>>),
+}
+
+/// 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<String, BundleError> {
+ 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<CString> = 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<String>)` on success, or an appropriate `Err(BundleError)` on failure.
+ pub fn get_str_vec(&self, key: &str) -> Result<Vec<String>, 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<u8>)` on success, or an appropriate `Err(BundleError)` on failure.
+ pub fn get_bytes(&self, key: &str) -> Result<Vec<u8>, 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<Vec<u8>>)` on success, or an appropriate `Err(BundleError)` on failure.
+ pub fn get_bytes_vec(&self, key: &str) -> Result<Vec<Vec<u8>>, 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<BundleType, BundleError> {
+ 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<String, BundleError> {
+ 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<Bundle, BundleError> {
+ 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<String, 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 {
+ CStr::from_ptr(val as *const c_char)
+ .to_string_lossy()
+ .into_owned()
+ })
+ }
+ }
+
+ fn get_str_vec(&self) -> Result<Vec<String>, 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<Vec<u8>, 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<Vec<Vec<u8>>, 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::Item> {
+ 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::Item> {
+ self.items.pop_front()
+ }
+}
--- /dev/null
+pub mod parcel;
+pub mod bundle;
+
+pub use crate::parcel::{Parcel};
+pub use crate::bundle::{Bundle};
+
+mod tests;
--- /dev/null
+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<T> {
+ 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<u8>` containing the data read on success, or an appropriate `Err(ParcelError)` on failure.
+ pub fn read(&mut self, size: usize) -> Result<Vec<u8>, 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<u8>` containing the raw data on success, or an appropriate `Err(ParcelError)` on failure.
+ pub fn get_raw_data(&self) -> Result<Vec<u8>, 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<bool, ParcelError> {
+ 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<i8, ParcelError> {
+ 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<i16, ParcelError> {
+ 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<i32, ParcelError> {
+ 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<i64, ParcelError> {
+ 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<u16, ParcelError> {
+ 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<u32, ParcelError> {
+ 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<u64, ParcelError> {
+ 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<f32, ParcelError> {
+ 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<f64, ParcelError> {
+ 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<String, ParcelError> {
+ 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() })
+ }
+ }
+}
--- /dev/null
+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),
+ }
+}
--- /dev/null
+#[cfg(test)]
+pub mod parcel_tests;
+#[cfg(test)]
+pub mod bundle_tests;
--- /dev/null
+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]);
+}