use core::ptr;
use crate as rune;
use crate::alloc::fmt::TryWrite;
use crate::alloc::hashbrown::raw::RawIter;
use crate::alloc::prelude::*;
use crate::hashbrown::{IterRef, Table};
use crate::runtime::{
EnvProtocolCaller, Formatter, Iterator, ProtocolCaller, RawAnyGuard, Ref, Value, VmResult,
};
use crate::{Any, ContextError, Module};
#[rune::module(::std::collections::hash_set)]
pub fn module() -> Result<Module, ContextError> {
let mut m = Module::from_meta(self::module_meta)?;
m.ty::<HashSet>()?;
m.function_meta(HashSet::new__meta)?;
m.function_meta(HashSet::with_capacity__meta)?;
m.function_meta(HashSet::len__meta)?;
m.function_meta(HashSet::is_empty__meta)?;
m.function_meta(HashSet::capacity__meta)?;
m.function_meta(HashSet::insert__meta)?;
m.function_meta(HashSet::remove__meta)?;
m.function_meta(HashSet::contains__meta)?;
m.function_meta(HashSet::clear__meta)?;
m.function_meta(HashSet::difference__meta)?;
m.function_meta(HashSet::extend__meta)?;
m.function_meta(HashSet::intersection__meta)?;
m.function_meta(HashSet::union__meta)?;
m.function_meta(HashSet::iter__meta)?;
m.function_meta(HashSet::into_iter__meta)?;
m.function_meta(HashSet::from_iter__meta)?;
m.function_meta(HashSet::debug_fmt__meta)?;
m.function_meta(HashSet::clone__meta)?;
m.implement_trait::<HashSet>(rune::item!(::std::clone::Clone))?;
m.function_meta(HashSet::partial_eq__meta)?;
m.implement_trait::<HashSet>(rune::item!(::std::cmp::PartialEq))?;
m.function_meta(HashSet::eq__meta)?;
m.implement_trait::<HashSet>(rune::item!(::std::cmp::Eq))?;
m.ty::<Iter>()?;
m.function_meta(Iter::next__meta)?;
m.function_meta(Iter::size_hint__meta)?;
m.implement_trait::<Iter>(rune::item!(::std::iter::Iterator))?;
m.function_meta(Iter::len__meta)?;
m.implement_trait::<Iter>(rune::item!(::std::iter::ExactSizeIterator))?;
m.ty::<Difference>()?;
m.function_meta(Difference::next__meta)?;
m.function_meta(Difference::size_hint__meta)?;
m.implement_trait::<Difference>(rune::item!(::std::iter::Iterator))?;
m.ty::<Intersection>()?;
m.function_meta(Intersection::next__meta)?;
m.function_meta(Intersection::size_hint__meta)?;
m.implement_trait::<Intersection>(rune::item!(::std::iter::Iterator))?;
m.ty::<Union>()?;
m.function_meta(Union::next__meta)?;
m.implement_trait::<Union>(rune::item!(::std::iter::Iterator))?;
Ok(m)
}
#[derive(Any)]
#[rune(module = crate, item = ::std::collections::hash_set)]
pub(crate) struct HashSet {
table: Table<()>,
}
impl HashSet {
#[rune::function(keep, path = Self::new)]
fn new() -> Self {
Self {
table: Table::new(),
}
}
#[rune::function(keep, path = Self::with_capacity)]
pub(crate) fn with_capacity(capacity: usize) -> VmResult<Self> {
VmResult::Ok(Self {
table: vm_try!(Table::try_with_capacity(capacity)),
})
}
#[rune::function(keep)]
fn len(&self) -> usize {
self.table.len()
}
#[rune::function(keep)]
fn is_empty(&self) -> bool {
self.table.is_empty()
}
#[rune::function(keep)]
fn capacity(&self) -> usize {
self.table.capacity()
}
#[rune::function(keep)]
pub(crate) fn insert(&mut self, key: Value) -> VmResult<bool> {
let mut caller = EnvProtocolCaller;
VmResult::Ok(vm_try!(self.table.insert_with(key, (), &mut caller)).is_none())
}
#[rune::function(keep)]
fn remove(&mut self, key: Value) -> VmResult<bool> {
let mut caller = EnvProtocolCaller;
VmResult::Ok(vm_try!(self.table.remove_with(&key, &mut caller)).is_some())
}
#[rune::function(keep)]
fn contains(&self, key: Value) -> VmResult<bool> {
let mut caller = EnvProtocolCaller;
VmResult::Ok(vm_try!(self.table.get(&key, &mut caller)).is_some())
}
#[rune::function(keep)]
fn clear(&mut self) {
self.table.clear()
}
#[rune::function(keep, instance, path = Self::difference)]
fn difference(this: Ref<Self>, other: Ref<Self>) -> Difference {
Self::difference_inner(this, other)
}
fn difference_inner(this: Ref<Self>, other: Ref<Self>) -> Difference {
Difference {
this: Table::iter_ref(Ref::map(this, |this| &this.table)),
other: Some(other),
}
}
#[rune::function(keep, instance, path = Self::intersection)]
fn intersection(this: Ref<Self>, other: Ref<Self>) -> Intersection {
if this.table.len() <= other.table.len() {
Intersection {
this: Table::iter_ref(Ref::map(this, |this| &this.table)),
other: Some(other),
}
} else {
Intersection {
this: Table::iter_ref(Ref::map(other, |this| &this.table)),
other: Some(this),
}
}
}
#[rune::function(keep, instance, path = Self::union)]
fn union(this: Ref<Self>, other: Ref<Self>) -> VmResult<Union> {
unsafe {
let (this, this_guard) = Ref::into_raw(Ref::map(this, |this| &this.table));
let (other, other_guard) = Ref::into_raw(Ref::map(other, |this| &this.table));
let iter = if this.as_ref().len() >= other.as_ref().len() {
let this_iter = Table::iter_ref_raw(this);
let other_iter = Table::iter_ref_raw(other);
Union {
this,
this_iter,
other_iter,
_guards: (this_guard, other_guard),
}
} else {
let this_iter = Table::iter_ref_raw(other);
let other_iter = Table::iter_ref_raw(this);
Union {
this: other,
this_iter,
other_iter,
_guards: (other_guard, this_guard),
}
};
VmResult::Ok(iter)
}
}
#[rune::function(keep, instance, path = Self::iter)]
fn iter(this: Ref<Self>) -> Iter {
let iter = Table::iter_ref(Ref::map(this, |this| &this.table));
Iter { iter }
}
#[rune::function(keep)]
fn extend(&mut self, value: Value) -> VmResult<()> {
let mut caller = EnvProtocolCaller;
let mut it = vm_try!(value.into_iter());
while let Some(key) = vm_try!(it.next()) {
vm_try!(self.table.insert_with(key, (), &mut caller));
}
VmResult::Ok(())
}
#[rune::function(keep, instance, protocol = INTO_ITER, path = Self)]
fn into_iter(this: Ref<Self>) -> Iter {
Self::iter(this)
}
#[rune::function(keep, protocol = DEBUG_FMT)]
fn debug_fmt(&self, f: &mut Formatter) -> VmResult<()> {
self.debug_fmt_with(f, &mut EnvProtocolCaller)
}
fn debug_fmt_with(&self, f: &mut Formatter, _: &mut dyn ProtocolCaller) -> VmResult<()> {
vm_try!(vm_write!(f, "{{"));
let mut it = self.table.iter().peekable();
while let Some(value) = it.next() {
vm_try!(vm_write!(f, "{:?}", value));
if it.peek().is_some() {
vm_try!(vm_write!(f, ", "));
}
}
vm_try!(vm_write!(f, "}}"));
VmResult::Ok(())
}
#[rune::function(keep, path = Self::from_iter)]
fn from_iter(it: Iterator) -> VmResult<HashSet> {
let mut caller = EnvProtocolCaller;
Self::from_iter_with(it, &mut caller)
}
pub(crate) fn from_iter_with(
mut it: Iterator,
caller: &mut dyn ProtocolCaller,
) -> VmResult<Self> {
let (lo, _) = vm_try!(it.size_hint());
let mut set = vm_try!(Table::try_with_capacity(lo));
while let Some(key) = vm_try!(it.next()) {
vm_try!(set.insert_with(key, (), caller));
}
VmResult::Ok(HashSet { table: set })
}
#[rune::function(keep, protocol = PARTIAL_EQ)]
fn partial_eq(&self, other: &Self) -> VmResult<bool> {
self.eq_with(other, &mut EnvProtocolCaller)
}
#[rune::function(keep, protocol = EQ)]
fn eq(&self, other: &Self) -> VmResult<bool> {
self.eq_with(other, &mut EnvProtocolCaller)
}
fn eq_with(&self, other: &Self, caller: &mut EnvProtocolCaller) -> VmResult<bool> {
if self.table.len() != other.table.len() {
return VmResult::Ok(false);
}
for (key, ()) in self.table.iter() {
if vm_try!(other.table.get(key, caller)).is_none() {
return VmResult::Ok(false);
}
}
VmResult::Ok(true)
}
#[rune::function(keep, instance, path = Self::clone, protocol = CLONE)]
fn clone(this: &HashSet) -> VmResult<HashSet> {
VmResult::Ok(Self {
table: vm_try!(this.table.try_clone()),
})
}
}
#[derive(Any)]
#[rune(item = ::std::collections::hash_set)]
struct Iter {
iter: IterRef<()>,
}
impl Iter {
#[rune::function(keep, instance, protocol = NEXT)]
pub(crate) fn next(&mut self) -> Option<Value> {
let (value, ()) = self.iter.next()?;
Some(value)
}
#[rune::function(keep, instance, protocol = SIZE_HINT)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[rune::function(keep, instance, protocol = LEN)]
fn len(&self) -> usize {
self.iter.len()
}
}
#[derive(Any)]
#[rune(item = ::std::collections::hash_set)]
struct Intersection {
this: IterRef<()>,
other: Option<Ref<HashSet>>,
}
impl Intersection {
#[rune::function(keep, instance, protocol = NEXT)]
pub(crate) fn next(&mut self) -> VmResult<Option<Value>> {
let mut caller = EnvProtocolCaller;
let Some(other) = &self.other else {
return VmResult::Ok(None);
};
for (key, ()) in self.this.by_ref() {
let c = vm_try!(other.table.get(&key, &mut caller)).is_some();
if c {
return VmResult::Ok(Some(key));
}
}
self.other = None;
VmResult::Ok(None)
}
#[rune::function(keep, instance, protocol = SIZE_HINT)]
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.this.size_hint();
(0, upper)
}
}
#[derive(Any)]
#[rune(item = ::std::collections::hash_set)]
struct Difference {
this: IterRef<()>,
other: Option<Ref<HashSet>>,
}
impl Difference {
#[rune::function(keep, instance, protocol = NEXT)]
pub(crate) fn next(&mut self) -> VmResult<Option<Value>> {
let mut caller = EnvProtocolCaller;
let Some(other) = &self.other else {
return VmResult::Ok(None);
};
for (key, ()) in self.this.by_ref() {
let c = vm_try!(other.table.get(&key, &mut caller)).is_some();
if !c {
return VmResult::Ok(Some(key));
}
}
self.other = None;
VmResult::Ok(None)
}
#[rune::function(keep, instance, protocol = SIZE_HINT)]
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.this.size_hint();
(0, upper)
}
}
#[derive(Any)]
#[rune(item = ::std::collections::hash_set)]
struct Union {
this: ptr::NonNull<Table<()>>,
this_iter: RawIter<(Value, ())>,
other_iter: RawIter<(Value, ())>,
_guards: (RawAnyGuard, RawAnyGuard),
}
impl Union {
#[rune::function(keep, instance, protocol = NEXT)]
fn next(&mut self) -> VmResult<Option<Value>> {
unsafe {
if let Some(bucket) = self.this_iter.next() {
let (value, ()) = bucket.as_ref();
return VmResult::Ok(Some(value.clone()));
}
let mut caller = EnvProtocolCaller;
for bucket in self.other_iter.by_ref() {
let (key, ()) = bucket.as_ref();
if vm_try!(self.this.as_ref().get(key, &mut caller)).is_none() {
return VmResult::Ok(Some(key.clone()));
}
}
VmResult::Ok(None)
}
}
}