Add tizen-base library for rust lang 14/312214/50
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 5 Jun 2024 06:28:13 +0000 (15:28 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 12 Aug 2024 01:56:20 +0000 (10:56 +0900)
Adds:
 - parcel::Parcel
 - bundle::Bundle

Change-Id: Idfa4724960dd4b823cdaee20753929a04f1aad43
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
packaging/bundle.spec
src/parcel/parcel.cc
src/rust-tizen-base/Cargo.toml [new file with mode: 0644]
src/rust-tizen-base/src/bundle.rs [new file with mode: 0644]
src/rust-tizen-base/src/lib.rs [new file with mode: 0644]
src/rust-tizen-base/src/parcel.rs [new file with mode: 0644]
src/rust-tizen-base/src/tests/bundle_tests.rs [new file with mode: 0644]
src/rust-tizen-base/src/tests/mod.rs [new file with mode: 0644]
src/rust-tizen-base/src/tests/parcel_tests.rs [new file with mode: 0644]

index 72120ac93f59813f4672f56ff40d6aa1467a4394..5b9ebc2e96c72a298f54b79d35453023beb68694 100644 (file)
@@ -15,9 +15,16 @@ BuildRequires:  pkgconfig(json-glib-1.0)
 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
@@ -121,10 +128,21 @@ Group:      Development/Libraries
 %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}
@@ -135,12 +153,40 @@ export LDFLAGS+=" -lgcov"
 %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
@@ -210,6 +256,10 @@ mkdir -p %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue
 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
@@ -225,6 +275,15 @@ sed -i -e 's/<NAME>/tizen-shared-queue/g' %{buildroot}%{_bindir}/tizen-unittests
 %{_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,-)
@@ -292,3 +351,11 @@ sed -i -e 's/<NAME>/tizen-shared-queue/g' %{buildroot}%{_bindir}/tizen-unittests
 %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
index 1f266c06f740d3514d4c3ed919221788f6e5b8aa..ca54911ed12f309bae15bae0522187b8763ec698 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <glib.h>
 
+#include <iostream>
 #include <exception>
 #include <mutex>
 
@@ -130,6 +131,9 @@ int Parcel::Impl::ReadSize(uint32_t* size) {
 
 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;
@@ -175,7 +179,7 @@ uint8_t* Parcel::Impl::Detach(size_t* size) {
   data_ = nullptr;
   data_capacity_ = 0;
   data_size_ = 0;
-  reader_= 0;
+  reader_ = 0;
   return data;
 }
 
@@ -203,7 +207,7 @@ Parcel::Parcel(const void* buf, uint32_t size, bool copy)
     impl_->Write(buf, size);
 }
 
-Parcel::~Parcel() {};
+Parcel::~Parcel() {}
 
 Parcel::Parcel(const Parcel& p)
   : impl_(new Impl(this, kDataCapacity)) {
diff --git a/src/rust-tizen-base/Cargo.toml b/src/rust-tizen-base/Cargo.toml
new file mode 100644 (file)
index 0000000..46e9148
--- /dev/null
@@ -0,0 +1,8 @@
+[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
new file mode 100644 (file)
index 0000000..6b54656
--- /dev/null
@@ -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<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()
+    }
+}
diff --git a/src/rust-tizen-base/src/lib.rs b/src/rust-tizen-base/src/lib.rs
new file mode 100644 (file)
index 0000000..73c768f
--- /dev/null
@@ -0,0 +1,7 @@
+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
new file mode 100644 (file)
index 0000000..c77e9d5
--- /dev/null
@@ -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<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() })
+        }
+    }
+}
diff --git a/src/rust-tizen-base/src/tests/bundle_tests.rs b/src/rust-tizen-base/src/tests/bundle_tests.rs
new file mode 100644 (file)
index 0000000..0b23d02
--- /dev/null
@@ -0,0 +1,191 @@
+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
new file mode 100644 (file)
index 0000000..c4146b8
--- /dev/null
@@ -0,0 +1,4 @@
+#[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
new file mode 100644 (file)
index 0000000..2801a12
--- /dev/null
@@ -0,0 +1,134 @@
+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]);
+}