//! 栈优先/堆回退双态字节缓冲区的公共实现宏
//!
//! 消除 KeyBufRepr / SubKeyBuf / ZSetSubKeyBuf 三份雷同的 Deref、Eq、Ord、Hash、
//! From 与栈堆切换逻辑,全库统一零拷贝借用与 SIMD 内容比较语义。

/// 生成 `Stack([u8; CAP], u8) | Heap(Vec<u8>)` 双态缓冲区及其公共 trait 实现
macro_rules! stack_heap_buf {
  (
    $(#[$enum_meta:meta])*
    $name:ident, $cap:expr
  ) => {
    $(#[$enum_meta])*
    #[derive(Debug, Clone)]
    pub enum $name {
      /// 栈分配(总字节数 <= 上限)
      Stack([u8; $cap], u8),
      /// 堆分配(超长键自动回退)
      Heap(Vec<u8>),
    }

    impl ::core::ops::Deref for $name {
      type Target = [u8];

      #[inline(always)]
      fn deref(&self) -> &Self::Target {
        match self {
          Self::Stack(buf, len) => {
            let len = (*len as usize).min($cap);
            // 安全性保证:len 经 min($cap) 约束,恒满足 len <= buf.len()
            unsafe { buf.get_unchecked(..len) }
          }
          Self::Heap(vec) => vec.as_slice(),
        }
      }
    }

    impl AsRef<[u8]> for $name {
      #[inline(always)]
      fn as_ref(&self) -> &[u8] {
        self.as_slice()
      }
    }

    impl ::core::borrow::Borrow<[u8]> for $name {
      #[inline(always)]
      fn borrow(&self) -> &[u8] {
        self.as_slice()
      }
    }

    impl PartialEq for $name {
      #[inline(always)]
      fn eq(&self, other: &Self) -> bool {
        $crate::simd::fast_key_eq(self.as_slice(), other.as_slice())
      }
    }

    impl Eq for $name {}

    impl PartialOrd for $name {
      #[inline(always)]
      fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
        Some(self.cmp(other))
      }
    }

    impl Ord for $name {
      #[inline(always)]
      fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        self.as_slice().cmp(other.as_slice())
      }
    }

    impl ::core::hash::Hash for $name {
      #[inline(always)]
      fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
        self.as_slice().hash(state);
      }
    }

    impl PartialEq<[u8]> for $name {
      #[inline(always)]
      fn eq(&self, other: &[u8]) -> bool {
        $crate::simd::fast_key_eq(self.as_slice(), other)
      }
    }

    impl PartialEq<&[u8]> for $name {
      #[inline(always)]
      fn eq(&self, other: &&[u8]) -> bool {
        $crate::simd::fast_key_eq(self.as_slice(), other)
      }
    }

    impl From<Vec<u8>> for $name {
      #[inline]
      fn from(vec: Vec<u8>) -> Self {
        if vec.len() <= $cap {
          let mut buf = [0u8; $cap];
          buf[..vec.len()].copy_from_slice(&vec);
          Self::Stack(buf, vec.len() as u8)
        } else {
          Self::Heap(vec)
        }
      }
    }

    impl From<&[u8]> for $name {
      #[inline]
      fn from(slice: &[u8]) -> Self {
        if slice.len() <= $cap {
          let mut buf = [0u8; $cap];
          buf[..slice.len()].copy_from_slice(slice);
          Self::Stack(buf, slice.len() as u8)
        } else {
          Self::Heap(slice.to_vec())
        }
      }
    }

    impl $name {
      /// 获取只读切片借用(零拷贝)
      #[inline(always)]
      pub fn as_slice(&self) -> &[u8] {
        self
      }

      /// 获取缓冲区字节长度
      #[inline(always)]
      pub fn len(&self) -> usize {
        self.as_slice().len()
      }

      /// 缓冲区是否为空
      #[inline(always)]
      pub fn is_empty(&self) -> bool {
        self.len() == 0
      }

      /// 当前是否分配在栈上
      #[inline(always)]
      pub const fn is_stack(&self) -> bool {
        matches!(self, Self::Stack(..))
      }

      /// 当前是否回退到堆分配
      #[inline(always)]
      pub const fn is_heap(&self) -> bool {
        matches!(self, Self::Heap(..))
      }

      /// 消耗自身转换为 Vec<u8>(若原为堆分配则零额外分配转移所有权)
      #[inline]
      pub fn into_vec(self) -> Vec<u8> {
        match self {
          Self::Stack(buf, len) => {
            let len = (len as usize).min($cap);
            // 安全性保证:len 经 min($cap) 约束,恒满足 len <= buf.len()
            unsafe { buf.get_unchecked(..len) }.to_vec()
          }
          Self::Heap(vec) => vec,
        }
      }
    }
  };
}

pub(crate) use stack_heap_buf;