1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

use crate::abitype::{BoxedAbiType, EncodeBoxedAbiType};
use crate::boxed::refs::Gc;
use crate::boxed::*;

/// Immutable map of boxed values
#[repr(C, align(16))]
pub struct Map<K: Boxed = Any, V: Boxed = Any> {
    header: Header,
    _key: PhantomData<K>,
    _value: PhantomData<V>,
}

impl<K: Boxed, V: Boxed> Boxed for Map<K, V> {}

impl<K: Boxed, V: Boxed> Map<K, V> {
    /// Constructs a new map with the given values
    pub fn new(
        heap: &mut impl AsHeap,
        values: impl ExactSizeIterator<Item = (Gc<K>, Gc<V>)>,
    ) -> Gc<Map<K, V>> {
        if values.len() != 0 {
            todo!("non-empty maps");
        }

        heap.as_heap_mut().place_box(Map {
            header: Map::TYPE_TAG.to_heap_header(Self::size()),
            _key: PhantomData,
            _value: PhantomData,
        })
    }

    /// Constructs a map by constructing an iterator of values
    pub fn from_values<T, F>(
        heap: &mut impl AsHeap,
        values: impl ExactSizeIterator<Item = T>,
        _cons: F,
    ) -> Gc<Map<K, V>>
    where
        F: Fn(&mut Heap, T) -> (Gc<K>, Gc<V>),
    {
        if values.len() != 0 {
            todo!("non-empty maps");
        }

        heap.as_heap_mut().place_box(Map {
            header: Map::TYPE_TAG.to_heap_header(Self::size()),
            _key: PhantomData,
            _value: PhantomData,
        })
    }

    /// Returns the box size for maps
    pub fn size() -> BoxSize {
        BoxSize::Size16
    }

    /// Return if the map is empty
    pub fn is_empty(&self) -> bool {
        true
    }

    /// Returns the number of the entries in the map
    pub fn len(&self) -> usize {
        0
    }

    /// Returns an iterator over the entries in map
    pub fn iter(&self) -> impl Iterator<Item = (Gc<K>, Gc<V>)> + '_ {
        std::iter::empty()
    }
}

impl<K: Boxed, V: Boxed> PartialEqInHeap for Map<K, V> {
    fn eq_in_heap(&self, _heap: &Heap, _other: &Map<K, V>) -> bool {
        // Both maps must be empty
        true
    }
}

impl<K: Boxed, V: Boxed> HashInHeap for Map<K, V> {
    fn hash_in_heap<H: Hasher>(&self, _heap: &Heap, state: &mut H) {
        TypeTag::Map.hash(state);
    }
}

impl<K: Boxed, V: Boxed> fmt::Debug for Map<K, V> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        formatter.write_str("Map(")?;
        formatter.debug_list().entries(self.iter()).finish()?;
        formatter.write_str(")")
    }
}

impl<K: Boxed, V: Boxed> EncodeBoxedAbiType for Map<K, V>
where
    K: EncodeBoxedAbiType,
    V: EncodeBoxedAbiType,
{
    const BOXED_ABI_TYPE: BoxedAbiType = BoxedAbiType::Map(&K::BOXED_ABI_TYPE, &V::BOXED_ABI_TYPE);
}

#[cfg(test)]
mod test {
    use super::*;
    use std::mem;

    #[test]
    fn sizes() {
        assert_eq!(16, mem::size_of::<Map<Any>>());
    }
}