/// res_c
#[macro_export]
macro_rules! json_cloned {
  ($expr:expr, $expr2:expr) => {
    // $crate::parse::AutoJson as _;
    serde_json::to_string(&$expr)
      .unwrap()
      .auto_cloned_json(&$expr2)
      .unwrap()
  };
}
/// auto_res
#[macro_export]
macro_rules! auto_res {
  ($expr:expr) => {
    match $expr {
      Ok(res) => $crate::Result::Ok(res),
      Err(e) => $crate::Result::Err(e.to_string().into()),
    }
  };
}
/// res_c
#[macro_export]
macro_rules! res_c {
  ($expr:expr) => {
    match $expr {
      $crate::CResult::Ok(res) => res,
      $crate::CResult::Err(e) => return $crate::CResult::Err(e),
    }
  };
}

/// 需要导入use e_utils::ParseResult as _;
#[macro_export]
macro_rules! auto_res_c {
  ($expr:expr) => {
    match $expr.res_c() {
      $crate::CResult::Ok(res) => res,
      $crate::CResult::Err(e) => return $crate::CResult::Err(e),
    }
  };
}
/// 需要导入use e_utils::ParseResult as _;
#[macro_export]
macro_rules! auto_any_res_c {
  ($expr:expr) => {
    match $expr {
      Ok(x) => x,
      Err(e) => return $crate::CResult::Err($crate::CError::cstr_err(e.to_string())),
    }
  };
}
/// res unsafe
#[macro_export]
macro_rules! res {
  ($expr:expr) => {
    unsafe {
      match $expr {
        $crate::CResult::Ok(res) => crate::Result::Ok(res),
        $crate::CResult::Err(e) => crate::Result::Err(e),
      }
    }
  };
}

#[doc(hidden)]
#[macro_export]
macro_rules! pub_struct {
  ($name:ident {$($field:ident: $t:ty,)*}) => {
    #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
    pub struct $name {
      $(pub $field: $t),*
    }
  }
}
#[doc(hidden)]
#[macro_export]
macro_rules! pub_c_struct_camelCase {
  ($name:ident {$($field:ident: $t:ty,)*}) => {
    /// camelCase结构
    #[repr(C)]
    #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
    #[serde(rename_all = "camelCase")]
    pub struct $name {
      $(
        /// 值
        pub $field: $t
      ),*
    }
  }
}
macro_rules! cfg_dialog {
  ($($item:item)*) => {
      $(
          #[cfg(feature = "dialog")]
          $item
      )*
  }
}
macro_rules! cfg_macros {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "macros")]
            $item
        )*
    }
}
macro_rules! cfg_images {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "images")]
            $item
        )*
    }
}
#[allow(unused)]
macro_rules! cfg_fs_ext {
  ($($item:item)*) => {
      $(
          #[cfg(feature = "fs_ext")]
          $item
      )*
  }
}
macro_rules! cfg_fs {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "fs")]
            $item
        )*
    }
}
macro_rules! cfg_uuid {
    ($($item:item)*) => {
        $(
            #[cfg(any(feature = "uuid_v4"))]
            $item
        )*
    }
}
macro_rules! cfg_algorithm {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "algorithm")]
            $item
        )*
    }
}

macro_rules! cfg_base64 {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "base64")]
            $item
        )*
    }
}
macro_rules! cfg_ui {
    ($($item:item)*) => {
        $(
            #[cfg(feature = "ui")]
            $item
        )*
    }
}
// Serialization macro
#[doc(hidden)]
#[macro_export]
macro_rules! serializer_c_array {
  ($name:ident,$ty:ty,$len:expr,$init:expr) => {
    /// 序列化C类型转数组
    pub mod $name {
      use e_utils::{deserialize_c_array, serialize_c_array};
      use serde::{Deserializer, Serializer};
      /// Deserialization functions using the macros
      pub fn deserialize<'de, D>(deserializer: D) -> std::result::Result<[$ty; $len], D::Error>
      where
        D: Deserializer<'de>,
      {
        deserialize_c_array!($ty, $len, $init, deserializer)
      }

      /// Serialization functions using the macros
      pub fn serialize<S>(arr: &[$ty; $len], serializer: S) -> std::result::Result<S::Ok, S::Error>
      where
        S: Serializer,
      {
        serialize_c_array!($ty, $len, serializer, arr)
      }
    }
  };
}
// Deserialization macro with type parameter
#[doc(hidden)]
#[macro_export]
macro_rules! deserialize_c_array {
  ($ty:ty, $len:expr, $init:expr, $deserializer:expr) => {{
    struct ByteArrayVisitor;

    impl<'de> serde::de::Visitor<'de> for ByteArrayVisitor {
      type Value = [$ty; $len];

      fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "a byte array of length {}", $len)
      }

      fn visit_seq<A>(self, mut seq: A) -> std::result::Result<Self::Value, A::Error>
      where
        A: serde::de::SeqAccess<'de>,
      {
        let mut arr = [$init; $len];
        for (i, val) in arr.iter_mut().enumerate() {
          *val = seq
            .next_element()?
            .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
        }
        // Use mem::transmute to convert between array types
        Ok(unsafe { std::mem::transmute::<[$ty; $len], [$ty; $len]>(arr) })
      }
    }
    $deserializer.deserialize_seq(ByteArrayVisitor)
  }};
}

// Serialization macro
#[doc(hidden)]
#[macro_export]
macro_rules! serialize_c_array {
  ($ty:ty, $len:expr, $serializer:expr, $arr:expr) => {{
    use serde::ser::SerializeSeq as _;
    let mut seq = $serializer.serialize_seq(Some($len))?;
    for &byte in $arr.iter() {
      seq.serialize_element(&byte)?;
    }
    seq.end()
  }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! cstring_to_array {
  ($ty:ty, $len:expr, $value:expr) => {{
    // Ensure the CString, including its NUL terminator, fits in s_path.
    if $value.as_bytes_with_nul().len() > $len {
      return $crate::CResult::Err($crate::CError::cstr_err("String too long for s_path"));
    }

    // Initialize s_path with zeros
    let mut s_path: [$ty; $len] = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };

    // Copy the CString into s_path, including the NUL terminator
    for (i, &byte) in $value.as_bytes_with_nul().iter().enumerate() {
      s_path[i] = byte as $ty; // Cast each byte to the target type $ty
    }

    s_path
  }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! str_to_array {
  ($ty:ty, $len:expr, $value:expr) => {{
    // Convert the input string to a CString to ensure it is NUL-terminated.
    let c_str = std::ffi::CString::new($value).map_err(|_| {
      std::io::Error::new(std::io::ErrorKind::InvalidInput, "String contains NUL byte")
    })?;
    $crate::cstring_to_array!($ty, $len, c_str)
  }};
}
#[doc(hidden)]
#[macro_export]
macro_rules! empty_to_array {
  ($ty:ty, $len:expr) => {{
    let res: [$ty; $len] = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
    res
  }};
}
