1dfe32fa1Soh_ci/*
2dfe32fa1Soh_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3dfe32fa1Soh_ci * Licensed under the Apache License, Version 2.0 (the "License");
4dfe32fa1Soh_ci * you may not use this file except in compliance with the License.
5dfe32fa1Soh_ci * You may obtain a copy of the License at
6dfe32fa1Soh_ci *
7dfe32fa1Soh_ci *     http://www.apache.org/licenses/LICENSE-2.0
8dfe32fa1Soh_ci *
9dfe32fa1Soh_ci * Unless required by applicable law or agreed to in writing, software
10dfe32fa1Soh_ci * distributed under the License is distributed on an "AS IS" BASIS,
11dfe32fa1Soh_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12dfe32fa1Soh_ci * See the License for the specific language governing permissions and
13dfe32fa1Soh_ci * limitations under the License.
14dfe32fa1Soh_ci */
15dfe32fa1Soh_ci
16dfe32fa1Soh_ci//! This module defines the tool macro of the enumeration type.
17dfe32fa1Soh_ci
18dfe32fa1Soh_ci/// Macro to implement TryFrom and Display for enumeration types.
19dfe32fa1Soh_ci///
20dfe32fa1Soh_ci/// # Examples
21dfe32fa1Soh_ci///
22dfe32fa1Soh_ci/// ```
23dfe32fa1Soh_ci/// impl_tag_trait! {
24dfe32fa1Soh_ci///     enum Color {
25dfe32fa1Soh_ci///         GREEN = 0,
26dfe32fa1Soh_ci///         YELLOW = 1,
27dfe32fa1Soh_ci///     }
28dfe32fa1Soh_ci/// }
29dfe32fa1Soh_ci/// ```
30dfe32fa1Soh_ci#[macro_export]
31dfe32fa1Soh_cimacro_rules! impl_tag_trait {
32dfe32fa1Soh_ci    ($(#[$meta:meta])* $vis:vis enum $name:ident {
33dfe32fa1Soh_ci        $($(#[$vmeta:meta])* $vname:ident $(= $val:expr)?,)*
34dfe32fa1Soh_ci    }) => {
35dfe32fa1Soh_ci        $(#[$meta])*
36dfe32fa1Soh_ci        $vis enum $name {
37dfe32fa1Soh_ci            $($(#[$vmeta])* $vname $(= $val)?,)*
38dfe32fa1Soh_ci        }
39dfe32fa1Soh_ci
40dfe32fa1Soh_ci        impl std::convert::TryFrom<u32> for $name {
41dfe32fa1Soh_ci            type Error = $crate::AssetError;
42dfe32fa1Soh_ci
43dfe32fa1Soh_ci            fn try_from(v: u32) -> std::result::Result<Self, Self::Error> {
44dfe32fa1Soh_ci                match v {
45dfe32fa1Soh_ci                    $(x if x == $name::$vname as u32 => Ok($name::$vname),)*
46dfe32fa1Soh_ci                    _ => {
47dfe32fa1Soh_ci                        $crate::log_throw_error!($crate::ErrCode::InvalidArgument,
48dfe32fa1Soh_ci                            "[FATAL]Type[{}] try from u32[{}] failed.", stringify!($name), v)
49dfe32fa1Soh_ci                    }
50dfe32fa1Soh_ci                }
51dfe32fa1Soh_ci            }
52dfe32fa1Soh_ci        }
53dfe32fa1Soh_ci
54dfe32fa1Soh_ci        impl std::fmt::Display for $name {
55dfe32fa1Soh_ci            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56dfe32fa1Soh_ci                match self {
57dfe32fa1Soh_ci                    $($name::$vname => {
58dfe32fa1Soh_ci                        write!(f, "{}", stringify!($name::$vname))
59dfe32fa1Soh_ci                    },)*
60dfe32fa1Soh_ci                }
61dfe32fa1Soh_ci            }
62dfe32fa1Soh_ci        }
63dfe32fa1Soh_ci    }
64dfe32fa1Soh_ci}
65dfe32fa1Soh_ci
66dfe32fa1Soh_ci/// Macro to implement TryFrom and Display for enumeration types.
67dfe32fa1Soh_ci///
68dfe32fa1Soh_ci/// # Examples
69dfe32fa1Soh_ci///
70dfe32fa1Soh_ci/// ```
71dfe32fa1Soh_ci/// impl_enum_trait! {
72dfe32fa1Soh_ci///     enum Color {
73dfe32fa1Soh_ci///         GREEN = 0,
74dfe32fa1Soh_ci///         YELLOW = 1,
75dfe32fa1Soh_ci///     }
76dfe32fa1Soh_ci/// }
77dfe32fa1Soh_ci/// ```
78dfe32fa1Soh_ci#[macro_export]
79dfe32fa1Soh_cimacro_rules! impl_enum_trait {
80dfe32fa1Soh_ci    ($(#[$meta:meta])* $vis:vis enum $name:ident {
81dfe32fa1Soh_ci        $($(#[$vmeta:meta])* $vname:ident $(= $val:expr)?,)*
82dfe32fa1Soh_ci    }) => {
83dfe32fa1Soh_ci        $(#[$meta])*
84dfe32fa1Soh_ci        $vis enum $name {
85dfe32fa1Soh_ci            $($(#[$vmeta])* $vname $(= $val)?,)*
86dfe32fa1Soh_ci        }
87dfe32fa1Soh_ci
88dfe32fa1Soh_ci        impl std::convert::TryFrom<u32> for $name {
89dfe32fa1Soh_ci            type Error = $crate::AssetError;
90dfe32fa1Soh_ci
91dfe32fa1Soh_ci            fn try_from(v: u32) -> std::result::Result<Self, Self::Error> {
92dfe32fa1Soh_ci                match v {
93dfe32fa1Soh_ci                    $(x if x == $name::$vname as u32 => Ok($name::$vname),)*
94dfe32fa1Soh_ci                    _ => {
95dfe32fa1Soh_ci                        $crate::log_throw_error!($crate::ErrCode::InvalidArgument,
96dfe32fa1Soh_ci                            "[FATAL]Type[{}] try from u32[{}] failed.", stringify!($name), v)
97dfe32fa1Soh_ci                    }
98dfe32fa1Soh_ci                }
99dfe32fa1Soh_ci            }
100dfe32fa1Soh_ci        }
101dfe32fa1Soh_ci
102dfe32fa1Soh_ci        impl std::fmt::Display for $name {
103dfe32fa1Soh_ci            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
104dfe32fa1Soh_ci                match self {
105dfe32fa1Soh_ci                    $($name::$vname => {
106dfe32fa1Soh_ci                        write!(f, "{}", stringify!($name::$vname))
107dfe32fa1Soh_ci                    },)*
108dfe32fa1Soh_ci                }
109dfe32fa1Soh_ci            }
110dfe32fa1Soh_ci        }
111dfe32fa1Soh_ci
112dfe32fa1Soh_ci        impl $crate::Conversion for $name {
113dfe32fa1Soh_ci            fn data_type(&self) -> $crate::DataType {
114dfe32fa1Soh_ci                $crate::DataType::Number
115dfe32fa1Soh_ci            }
116dfe32fa1Soh_ci
117dfe32fa1Soh_ci            fn into_value(self) -> $crate::Value {
118dfe32fa1Soh_ci                $crate::Value::Number(self as u32)
119dfe32fa1Soh_ci            }
120dfe32fa1Soh_ci        }
121dfe32fa1Soh_ci    }
122dfe32fa1Soh_ci}
123dfe32fa1Soh_ci
124dfe32fa1Soh_ci/// Print log and throw AssetError.
125dfe32fa1Soh_ci///
126dfe32fa1Soh_ci/// # Examples
127dfe32fa1Soh_ci///
128dfe32fa1Soh_ci/// ```
129dfe32fa1Soh_ci/// log_throw_error!(ErrCode::InvalidArgument, "hello, {}", "world");
130dfe32fa1Soh_ci/// ```
131dfe32fa1Soh_ci#[macro_export]
132dfe32fa1Soh_cimacro_rules! log_throw_error {
133dfe32fa1Soh_ci    ($code:expr, $($arg:tt)*) => {{
134dfe32fa1Soh_ci        let str = format!($($arg)*);
135dfe32fa1Soh_ci        asset_log::loge!("{}", str);
136dfe32fa1Soh_ci        Err($crate::AssetError {
137dfe32fa1Soh_ci            code: $code,
138dfe32fa1Soh_ci            msg: str
139dfe32fa1Soh_ci        })
140dfe32fa1Soh_ci    }};
141dfe32fa1Soh_ci}
142dfe32fa1Soh_ci
143dfe32fa1Soh_ci/// Throw AssetError.
144dfe32fa1Soh_ci///
145dfe32fa1Soh_ci/// # Examples
146dfe32fa1Soh_ci///
147dfe32fa1Soh_ci/// ```
148dfe32fa1Soh_ci/// throw_error!(ErrCode::InvalidArgument, "hello, {}", "world");
149dfe32fa1Soh_ci/// ```
150dfe32fa1Soh_ci#[macro_export]
151dfe32fa1Soh_cimacro_rules! throw_error {
152dfe32fa1Soh_ci    ($code:expr, $($arg:tt)*) => {{
153dfe32fa1Soh_ci        let str = format!($($arg)*);
154dfe32fa1Soh_ci        Err($crate::AssetError {
155dfe32fa1Soh_ci            code: $code,
156dfe32fa1Soh_ci            msg: str
157dfe32fa1Soh_ci        })
158dfe32fa1Soh_ci    }};
159dfe32fa1Soh_ci}
160dfe32fa1Soh_ci
161dfe32fa1Soh_ci/// Impl from trait for u32.
162dfe32fa1Soh_ci///
163dfe32fa1Soh_ci/// # Examples
164dfe32fa1Soh_ci///
165dfe32fa1Soh_ci/// ```
166dfe32fa1Soh_ci/// impl_from_for_u32!(Accessibility);
167dfe32fa1Soh_ci/// ```
168dfe32fa1Soh_ci#[macro_export]
169dfe32fa1Soh_cimacro_rules! impl_from_for_u32 {
170dfe32fa1Soh_ci    ($t:ty) => {
171dfe32fa1Soh_ci        impl From<$t> for u32 {
172dfe32fa1Soh_ci            #[inline(always)]
173dfe32fa1Soh_ci            fn from(value: $t) -> Self {
174dfe32fa1Soh_ci                value as u32
175dfe32fa1Soh_ci            }
176dfe32fa1Soh_ci        }
177dfe32fa1Soh_ci    };
178dfe32fa1Soh_ci}
179