Skip to content

Commit

Permalink
Merge pull request #16 from ohos-rs/feat-build
Browse files Browse the repository at this point in the history
feat: add error and result
  • Loading branch information
richerfu authored Nov 7, 2024
2 parents 69a8993 + 4a110f9 commit 1a1e80b
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 122 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,3 @@ quote = { version = "1.0" }
proc-macro2 = { version = "1.0" }
convert_case = { version = "0.6" }
regex = { version = "1.0" }
thiserror = { version = "2.0" }
10 changes: 6 additions & 4 deletions crates/arkui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ edition = "2021"

[dependencies]
ohos-arkui-sys = { workspace = true }
napi-sys-ohos = { workspace = true }
napi-ohos = { workspace = true }
napi-sys-ohos = { workspace = true, optional = true }
napi-ohos = { workspace = true, optional = true }
enum_macro = { workspace = true }
thiserror = { workspace = true }

ohos-hilog-binding = {workspace = true}

[features]
default = ["napi"]
napi = ["dep:napi-ohos", "dep:napi-sys-ohos"]
104 changes: 83 additions & 21 deletions crates/arkui/src/common/error.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,100 @@
use thiserror::Error;
use enum_macro::EnumFrom;
#[cfg(feature = "napi")]
use napi_ohos::{Error, Result};
use ohos_arkui_sys::*;

#[derive(Error, Debug)]
pub enum ArkUIError {
#[error("ArkUI call `{0}` failed with params invalid")]
ParamsInvalid(String),
#[derive(Debug, EnumFrom)]
#[enum_from_config(ArkUI_ErrorCode, "ArkUI_ErrorCode_ARKUI_ERROR_CODE_")]
pub enum ArkUIErrorCode {
ParamInvalid,
AttributeOrEventNotSupported,
ArkTSNodeNotSupported,
AdapterNotBound,
AdapterExist,
ChildNodeExist,
NodeEventParamIndexOutOfRange,
NodeEventParamInvalid,
NodeIndexInvalid,
BufferSizeError,
NonScrollableContainer,
BufferSizeNotEnough,
}

#[cfg(not(feature = "napi"))]
pub struct ArkUIError {
pub code: ArkUIErrorCode,
pub message: Option<String>,
}

#[cfg(not(feature = "napi"))]
impl ArkUIError {
pub fn new<T: AsRef<str>>(code: ArkUIErrorCode, message: T) -> Self {
Self {
code,
message: Some(message.as_ref().to_string()),
}
}

pub fn from_status(code: ArkUIErrorCode) -> Self {
Self {
code,
message: None,
}
}

pub fn from_reason<T: AsRef<str>>(message: T) -> Self {
Self {
code: ArkUIErrorCode::ParamInvalid,
message: Some(message.as_ref().to_string()),
}
}
}

impl AsRef<str> for ArkUIErrorCode {
fn as_ref(&self) -> &str {
match self {
ArkUIErrorCode::AdapterExist => "AdapterExist",
ArkUIErrorCode::AdapterNotBound => "AdapterNotBound",
ArkUIErrorCode::ArkTSNodeNotSupported => "ArkTSNodeNotSupported",
ArkUIErrorCode::AttributeOrEventNotSupported => "AttributeOrEventNotSupported",
ArkUIErrorCode::BufferSizeError => "BufferSizeError",
ArkUIErrorCode::BufferSizeNotEnough => "BufferSizeNotEnough",
ArkUIErrorCode::ChildNodeExist => "ChildNodeExist",
ArkUIErrorCode::NonScrollableContainer => "NonScrollableContainer",
ArkUIErrorCode::NodeEventParamIndexOutOfRange => "NodeEventParamIndexOutOfRange",
ArkUIErrorCode::NodeEventParamInvalid => "NodeEventParamInvalid",
ArkUIErrorCode::NodeIndexInvalid => "NodeIndexInvalid",
ArkUIErrorCode::ParamInvalid => "ParamInvalid",
}
}
}

#[cfg(not(feature = "napi"))]
/// This type is used for ArkUI result.
pub type ArkUIResult = Result<(), ArkUIError>;
pub type ArkUIResult<T> = Result<T, ArkUIError>;

#[cfg(feature = "napi")]
pub type ArkUIResult<T> = Result<T, ArkUIErrorCode>;

#[cfg(feature = "napi")]
pub type ArkUIError = Error<ArkUIErrorCode>;

#[doc(hidden)]
#[macro_export]
macro_rules! check_arkui_status {
($code:expr) => {{
let c = $code;
let c = $code as u32;
match c {
$crate::sys::Status::napi_ok => Ok(()),
_ => Err($crate::Error::new($crate::Status::from(c), "".to_owned())),
ohos_arkui_sys::ArkUI_ErrorCode_ARKUI_ERROR_CODE_NO_ERROR => Ok(()),
_ => Err($crate::ArkUIError::new(c.into(), "".to_owned())),
}
}};

($code:expr, $($msg:tt)*) => {{
let c = $code;
let c = $code as u32;
match c {
$crate::sys::Status::napi_ok => Ok(()),
_ => Err($crate::Error::new($crate::Status::from(c), format!($($msg)*))),
ohos_arkui_sys::ArkUI_ErrorCode_ARKUI_ERROR_CODE_NO_ERROR => Ok(()),
_ => Err($crate::ArkUIError::new(c.into(), format!($($msg)*))),
}
}};

($code:expr, $msg:expr, $env:expr, $val:expr) => {{
let c = $code;
match c {
$crate::sys::Status::napi_ok => Ok(()),
_ => Err($crate::Error::new($crate::Status::from(c), format!($msg, $crate::type_of!($env, $val)?))),
}
}};
}
}
2 changes: 2 additions & 0 deletions crates/arkui/src/common/handle.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg(feature = "napi")]

use napi_ohos::bindgen_prelude::{check_status, FromNapiValue, TypeName, ValidateNapiValue};
use napi_sys_ohos as sys;
use ohos_arkui_sys::{ArkUI_NodeContentHandle, OH_ArkUI_GetNodeContentFromNapiValue};
Expand Down
2 changes: 2 additions & 0 deletions crates/arkui/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod attribute;
mod error;
#[cfg(feature = "napi")]
mod handle;
mod native_node_api;
mod node;

pub use attribute::*;
pub use error::*;
#[cfg(feature = "napi")]
pub use handle::*;
pub use native_node_api::*;
pub use node::*;
61 changes: 38 additions & 23 deletions crates/arkui/src/common/native_node_api.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use std::{cell::LazyCell, ffi::CString};

use napi_ohos::{Error, Result};
use ohos_arkui_sys::{
ArkUI_NativeAPIVariantKind_ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, ArkUI_NodeHandle,
OH_ArkUI_QueryModuleInterfaceByName,
};

use crate::{ArkUINodeAttributeType, ArkUINodeType};
use crate::{check_arkui_status, ArkUINodeAttributeType, ArkUINodeType};

use super::{ArkUINode, ArkUINodeAttributeItem};
use super::{ArkUIError, ArkUIErrorCode, ArkUINode, ArkUINodeAttributeItem, ArkUIResult};

/// ArkUI_NativeNodeAPI_1 struct
/// Only can be used in main thread
Expand All @@ -26,6 +25,7 @@ impl ArkUINativeNodeAPI1 {
}

pub fn new() -> Self {
#[allow(unused_assignments)]
let mut api: *mut ArkUI_NativeNodeAPI_1 = std::ptr::null_mut();
let struct_name = CString::new("ArkUI_NativeNodeAPI_1").unwrap();
let raw_ptr = unsafe {
Expand All @@ -40,13 +40,20 @@ impl ArkUINativeNodeAPI1 {
Self(api)
}

pub fn create_node(&self, node_type: ArkUINodeType) -> Result<ArkUI_NodeHandle> {
pub fn create_node(&self, node_type: ArkUINodeType) -> ArkUIResult<ArkUI_NodeHandle> {
unsafe {
if let Some(create_node) = (*self.0).createNode {
let handle = create_node(node_type.into());
if handle.is_null() {
return Err(ArkUIError::new(
super::ArkUIErrorCode::ArkTSNodeNotSupported,
"Create node failed",
));
}
Ok(handle)
} else {
Err(Error::from_reason(
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::createNode is None",
))
}
Expand All @@ -58,65 +65,73 @@ impl ArkUINativeNodeAPI1 {
node: &ArkUINode,
attr: ArkUINodeAttributeType,
value: ArkUINodeAttributeItem,
) -> Result<()> {
) -> ArkUIResult<()> {
unsafe {
if let Some(set_attribute) = (*self.0).setAttribute {
set_attribute(node.raw(), attr.into(), &value.into());
Ok(())
check_arkui_status!(set_attribute(node.raw(), attr.into(), &value.into()))
} else {
Err(Error::from_reason(
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::setAttribute is None",
))
}
}
}

pub fn add_child(&self, parent: &ArkUINode, child: &ArkUINode) -> Result<()> {
pub fn add_child(&self, parent: &ArkUINode, child: &ArkUINode) -> ArkUIResult<()> {
unsafe {
if let Some(add_child) = (*self.0).addChild {
add_child(parent.raw(), child.raw());
Ok(())
check_arkui_status!(add_child(parent.raw(), child.raw()))
} else {
Err(Error::from_reason(
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::addChild is None",
))
}
}
}

pub fn remove_child(&self, parent: &ArkUINode, child: &ArkUINode) -> Result<()> {
pub fn remove_child(&self, parent: &ArkUINode, child: &ArkUINode) -> ArkUIResult<()> {
unsafe {
if let Some(remove_child) = (*self.0).removeChild {
remove_child(parent.raw(), child.raw());
Ok(())
check_arkui_status!(remove_child(parent.raw(), child.raw()))
} else {
Err(Error::from_reason(
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::removeChild is None",
))
}
}
}

pub fn insert_child(&self, parent: &ArkUINode, child: &ArkUINode, index: i32) -> Result<()> {
pub fn insert_child(
&self,
parent: &ArkUINode,
child: &ArkUINode,
index: i32,
) -> ArkUIResult<()> {
unsafe {
if let Some(insert_child_at) = (*self.0).insertChildAt {
insert_child_at(parent.raw(), child.raw(), index);
Ok(())
check_arkui_status!(insert_child_at(parent.raw(), child.raw(), index))
} else {
Err(Error::from_reason(
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::insertChild is None",
))
}
}
}

pub fn dispose(&self, node: &ArkUINode) -> Result<()> {
pub fn dispose(&self, node: &ArkUINode) -> ArkUIResult<()> {
unsafe {
if let Some(dispose_node) = (*self.0).disposeNode {
dispose_node(node.raw());
Ok(())
} else {
Err(Error::from_reason("ArkUI_NativeNodeAPI_1::dispose is None"))
Err(ArkUIError::new(
ArkUIErrorCode::AttributeOrEventNotSupported,
"ArkUI_NativeNodeAPI_1::dispose is None",
))
}
}
}
Expand Down
26 changes: 18 additions & 8 deletions crates/arkui/src/common/node.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#[cfg(feature = "napi")]
use napi_ohos::bindgen_prelude::{check_status, FromNapiValue, TypeName, ValidateNapiValue};
#[cfg(feature = "napi")]
use napi_sys_ohos as sys;
use ohos_arkui_sys::{ArkUI_NodeHandle, OH_ArkUI_GetNodeHandleFromNapiValue};
use ohos_hilog_binding::hilog_info;
use ohos_arkui_sys::ArkUI_NodeHandle;

#[cfg(feature = "napi")]
use ohos_arkui_sys::OH_ArkUI_GetNodeHandleFromNapiValue;
#[cfg(feature = "napi")]
use std::ptr;

use crate::ArkUINodeType;

use super::ARK_UI_NATIVE_NODE_API_1;
use super::{ArkUIResult, ARK_UI_NATIVE_NODE_API_1};

#[derive(Clone)]
pub struct ArkUINode {
Expand All @@ -30,22 +35,25 @@ impl ArkUINode {

/// Clear dom
/// We can't use drop impl, because it will be called when the object is dropped.
pub fn dispose(&mut self) {
ARK_UI_NATIVE_NODE_API_1.dispose(self);
self.children.iter_mut().for_each(|child| {
child.dispose();
});
pub fn dispose(&mut self) -> ArkUIResult<()> {
ARK_UI_NATIVE_NODE_API_1.dispose(self)?;
for child in self.children.iter_mut() {
child.dispose()?;
}
self.children.clear();
Ok(())
}
}

#[cfg(feature = "napi")]
/// Convert ArkUI node to native node
pub struct ArkUINodeRaw {
pub(crate) env: sys::napi_env,
pub(crate) value: sys::napi_value,
pub raw: ArkUI_NodeHandle,
}

#[cfg(feature = "napi")]
impl TypeName for ArkUINodeRaw {
fn type_name() -> &'static str {
"ArkUINode"
Expand All @@ -55,8 +63,10 @@ impl TypeName for ArkUINodeRaw {
}
}

#[cfg(feature = "napi")]
impl ValidateNapiValue for ArkUINodeRaw {}

#[cfg(feature = "napi")]
impl FromNapiValue for ArkUINodeRaw {
unsafe fn from_napi_value(
env: sys::napi_env,
Expand Down
Loading

0 comments on commit 1a1e80b

Please sign in to comment.