use super::{Hashable, NounDecode, NounEncode};
use crate::zbase::{ZBase, ZEntry, ZHashableEntry};
use alloc::fmt::Debug;
#[cfg(feature = "wasm")]
use alloc::{boxed::Box, format, string::ToString};
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, NounDecode, NounEncode, Hashable)]
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi, type = "T"))]
pub struct ZSetEntry<T> {
key: T,
}
impl<T: Hashable + NounEncode> ZEntry for ZSetEntry<T> {
type Key = T;
type Value = T;
type Pair = T;
type BorrowPair<'a>
= &'a T
where
T: 'a;
fn key(&self) -> &Self::Key {
&self.key
}
fn value(&self) -> &Self::Value {
&self.key
}
fn value_mut(&mut self) -> &mut Self::Value {
&mut self.key
}
fn pair(&self) -> Self::BorrowPair<'_> {
&self.key
}
fn into_key(self) -> Self::Key {
self.key
}
fn into_value(self) -> Self::Value {
self.key
}
fn into_pair(self) -> Self::Pair {
self.key
}
fn from_pair(pair: Self::Pair) -> Self {
Self { key: pair }
}
}
impl<T: Hashable + NounEncode> ZHashableEntry for ZSetEntry<T> {
type HashableBorrowPair<'a>
= &'a T
where
T: 'a;
fn hashable_pair(&self) -> Self::HashableBorrowPair<'_> {
&self.key
}
}
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, NounDecode, NounEncode, Hashable)]
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
pub struct ZSet<T>(pub ZBase<ZSetEntry<T>>);
impl<T> serde::Serialize for ZSet<T>
where
T: Hashable + NounEncode + serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(None)?;
for entry in self.0.iter() {
seq.serialize_element(&entry)?;
}
seq.end()
}
}
impl<'de, T> serde::Deserialize<'de> for ZSet<T>
where
T: Hashable + NounEncode + serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self(ZBase::deserialize(deserializer)?))
}
}
impl<T> Default for ZSet<T>
where
T: Hashable + NounEncode,
{
fn default() -> Self {
Self(ZBase::default())
}
}
impl<T> core::ops::Deref for ZSet<T> {
type Target = ZBase<ZSetEntry<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> core::ops::DerefMut for ZSet<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> IntoIterator for ZSet<T>
where
T: Hashable + NounEncode,
{
type Item = T;
type IntoIter = crate::zbase::ZBaseIntoIterator<ZSetEntry<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<T> FromIterator<T> for ZSet<T>
where
T: Hashable + NounEncode,
{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self(ZBase::from_iter(iter))
}
}
impl<T> From<ZSet<T>> for alloc::vec::Vec<T>
where
T: Hashable + NounEncode,
{
fn from(set: ZSet<T>) -> Self {
set.into_iter().collect()
}
}
impl<'a, T> IntoIterator for &'a ZSet<T>
where
T: Hashable + NounEncode,
{
type Item = &'a T;
type IntoIter = crate::zbase::ZBaseIterator<'a, ZSetEntry<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<T> From<alloc::vec::Vec<T>> for ZSet<T>
where
T: Hashable + NounEncode,
{
fn from(v: alloc::vec::Vec<T>) -> Self {
Self(crate::zbase::ZBase::from(v))
}
}
impl<T, const N: usize> From<[T; N]> for ZSet<T>
where
T: Hashable + NounEncode,
{
fn from(v: [T; N]) -> Self {
Self(crate::zbase::ZBase::from(v))
}
}
impl<T: Hashable + NounEncode> ZSet<T> {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, key: T) {
self.0.insert_entry(ZSetEntry { key });
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
#[test]
fn test_zset_encode_decode() {
let mut zm = ZSet::<&str>::new();
let s1 = "ver".to_string();
let s2 = "ve2".to_string();
zm.insert(&s1);
zm.insert(&s2);
let zm_noun = zm.to_noun();
let zm_decode = ZSet::<String>::from_noun(&zm_noun).unwrap();
assert_eq!(Vec::from(zm), Vec::from(zm_decode));
}
#[test]
fn test_zset_order() {
let zs_noun = (1, (2, (3, (), ()), (4, (5, (), ()), ())), (10, (), ())).to_noun();
let zs = ZSet::<u64>::from_noun(&zs_noun).unwrap();
assert_eq!(zs.iter().copied().collect::<Vec<_>>(), &[10, 1, 4, 5, 2, 3]);
assert_eq!(zs.into_iter().collect::<Vec<_>>(), &[10, 1, 4, 5, 2, 3]);
}
#[test]
fn test_zset_ins_order() {
let expected_order = [
20, 4, 15, 14, 2, 19, 6, 5, 8, 7, 11, 1, 17, 16, 3, 13, 10, 12, 18, 9,
];
let mut zs = ZSet::<u64>::new();
for i in 1u64..=20 {
zs.insert(i);
}
assert_eq!(zs.iter().copied().collect::<Vec<_>>(), &expected_order);
assert_eq!(zs.into_iter().collect::<Vec<_>>(), &expected_order);
let mut zs = ZSet::<u64>::new();
for i in expected_order {
zs.insert(i);
}
assert_eq!(zs.iter().copied().collect::<Vec<_>>(), &expected_order);
assert_eq!(zs.into_iter().collect::<Vec<_>>(), &expected_order);
}
}