use crate::{FragmentRef, UnorderedEq, UnorderedPartialEq, Value};
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
mod index_map;
pub use index_map::Equivalent;
use index_map::IndexMap;
pub const KEY_CAPACITY: usize = 16;
pub type Key = smallstr::SmallString<[u8; KEY_CAPACITY]>;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Entry {
pub key: Key,
pub value: Value,
}
impl Entry {
pub fn new(key: Key, value: Value) -> Self {
Self { key, value }
}
pub fn get_fragment(&self, index: usize) -> Result<FragmentRef, usize> {
match index {
0 => Ok(FragmentRef::Entry(self)),
1 => Ok(FragmentRef::Key(&self.key)),
_ => self.value.get_fragment(index - 2),
}
}
pub fn as_key(&self) -> &Key {
&self.key
}
pub fn as_value(&self) -> &Value {
&self.value
}
pub fn into_key(self) -> Key {
self.key
}
pub fn into_value(self) -> Value {
self.value
}
pub fn as_pair(&self) -> (&Key, &Value) {
(&self.key, &self.value)
}
pub fn into_pair(self) -> (Key, Value) {
(self.key, self.value)
}
}
#[derive(Clone)]
pub struct Object {
entries: Vec<Entry>,
indexes: IndexMap,
}
impl Default for Object {
fn default() -> Self {
Self {
entries: Vec::new(),
indexes: IndexMap::new(),
}
}
}
impl Object {
pub fn new() -> Self {
Self::default()
}
pub fn from_vec(entries: Vec<Entry>) -> Self {
let mut indexes = IndexMap::new();
for i in 0..entries.len() {
indexes.insert(&entries, i);
}
Self { entries, indexes }
}
pub fn capacity(&self) -> usize {
self.entries.capacity()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn get_fragment(&self, mut index: usize) -> Result<FragmentRef, usize> {
for e in &self.entries {
match e.get_fragment(index) {
Ok(value) => return Ok(value),
Err(i) => index = i,
}
}
Err(index)
}
pub fn entries(&self) -> &[Entry] {
&self.entries
}
pub fn iter(&self) -> core::slice::Iter<Entry> {
self.entries.iter()
}
pub fn iter_mut(&mut self) -> IterMut {
IterMut(self.entries.iter_mut())
}
pub fn get<Q: ?Sized>(&self, key: &Q) -> Values
where
Q: Hash + Equivalent<Key>,
{
let indexes = self
.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default();
Values {
indexes,
object: self,
}
}
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> ValuesMut
where
Q: Hash + Equivalent<Key>,
{
let indexes = self
.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default();
ValuesMut {
indexes,
entries: &mut self.entries,
}
}
pub fn get_unique<Q: ?Sized>(&self, key: &Q) -> Result<Option<&Value>, Duplicate<&Entry>>
where
Q: Hash + Equivalent<Key>,
{
let mut entries = self.get_entries(key);
match entries.next() {
Some(entry) => match entries.next() {
Some(duplicate) => Err(Duplicate(entry, duplicate)),
None => Ok(Some(&entry.value)),
},
None => Ok(None),
}
}
pub fn get_unique_mut<Q: ?Sized>(
&mut self,
key: &Q,
) -> Result<Option<&mut Value>, Duplicate<&Entry>>
where
Q: Hash + Equivalent<Key>,
{
let index = {
let mut entries = self.get_entries_with_index(key);
match entries.next() {
Some((i, _)) => match entries.next() {
Some((j, _)) => Err(Duplicate(i, j)),
None => Ok(Some(i)),
},
None => Ok(None),
}
};
match index {
Ok(Some(i)) => Ok(Some(&mut self.entries[i].value)),
Ok(None) => Ok(None),
Err(Duplicate(i, j)) => Err(Duplicate(&self.entries[i], &self.entries[j])),
}
}
pub fn get_entries<Q: ?Sized>(&self, key: &Q) -> Entries
where
Q: Hash + Equivalent<Key>,
{
let indexes = self
.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default();
Entries {
indexes,
object: self,
}
}
pub fn get_unique_entry<Q: ?Sized>(&self, key: &Q) -> Result<Option<&Entry>, Duplicate<&Entry>>
where
Q: Hash + Equivalent<Key>,
{
let mut entries = self.get_entries(key);
match entries.next() {
Some(entry) => match entries.next() {
Some(duplicate) => Err(Duplicate(entry, duplicate)),
None => Ok(Some(entry)),
},
None => Ok(None),
}
}
pub fn get_with_index<Q: ?Sized>(&self, key: &Q) -> ValuesWithIndex
where
Q: Hash + Equivalent<Key>,
{
let indexes = self
.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default();
ValuesWithIndex {
indexes,
object: self,
}
}
pub fn get_entries_with_index<Q: ?Sized>(&self, key: &Q) -> EntriesWithIndex
where
Q: Hash + Equivalent<Key>,
{
let indexes = self
.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default();
EntriesWithIndex {
indexes,
object: self,
}
}
pub fn get_or_insert_with<Q: ?Sized>(&mut self, key: &Q, f: impl FnOnce() -> Value) -> &Value
where
Q: Hash + Equivalent<Key> + ToOwned,
Q::Owned: Into<Key>,
{
let index = match self.index_of(key) {
Some(index) => index,
None => {
let index = self.entries.len();
self.push(key.to_owned().into(), f());
index
}
};
&self.entries[index].value
}
pub fn get_mut_or_insert_with<Q: ?Sized>(
&mut self,
key: &Q,
f: impl FnOnce() -> Value,
) -> &mut Value
where
Q: Hash + Equivalent<Key> + ToOwned,
Q::Owned: Into<Key>,
{
let index = match self.index_of(key) {
Some(index) => index,
None => {
let index = self.entries.len();
self.push(key.to_owned().into(), f());
index
}
};
&mut self.entries[index].value
}
pub fn index_of<Q: ?Sized>(&self, key: &Q) -> Option<usize>
where
Q: Hash + Equivalent<Key>,
{
self.indexes
.get(&self.entries, key)
.map(index_map::Indexes::first)
}
pub fn redundant_index_of<Q: ?Sized>(&self, key: &Q) -> Option<usize>
where
Q: Hash + Equivalent<Key>,
{
self.indexes
.get(&self.entries, key)
.and_then(index_map::Indexes::redundant)
}
pub fn indexes_of<Q: ?Sized>(&self, key: &Q) -> Indexes
where
Q: Hash + Equivalent<Key>,
{
self.indexes
.get(&self.entries, key)
.map(IntoIterator::into_iter)
.unwrap_or_default()
}
pub fn first(&self) -> Option<&Entry> {
self.entries.first()
}
pub fn last(&self) -> Option<&Entry> {
self.entries.last()
}
pub fn push(&mut self, key: Key, value: Value) -> bool {
self.push_entry(Entry::new(key, value))
}
pub fn push_entry(&mut self, entry: Entry) -> bool {
let index = self.entries.len();
self.entries.push(entry);
self.indexes.insert(&self.entries, index)
}
pub fn push_front(&mut self, key: Key, value: Value) -> bool {
self.push_entry_front(Entry::new(key, value))
}
pub fn push_entry_front(&mut self, entry: Entry) -> bool {
self.entries.insert(0, entry);
self.indexes.shift_up(0);
self.indexes.insert(&self.entries, 0)
}
pub fn remove_at(&mut self, index: usize) -> Option<Entry> {
if index < self.entries.len() {
self.indexes.remove(&self.entries, index);
self.indexes.shift_down(index);
Some(self.entries.remove(index))
} else {
None
}
}
pub fn insert(&mut self, key: Key, value: Value) -> Option<RemovedByInsertion> {
match self.index_of(&key) {
Some(index) => {
let mut entry = Entry::new(key, value);
core::mem::swap(&mut entry, &mut self.entries[index]);
Some(RemovedByInsertion {
index,
first: Some(entry),
object: self,
})
}
None => {
self.push(key, value);
None
}
}
}
pub fn insert_front(&mut self, key: Key, value: Value) -> RemovedByInsertFront {
if let Some(first) = self.entries.first_mut() {
if first.key == key {
let first = core::mem::replace(first, Entry::new(key, value));
return RemovedByInsertFront {
first: Some(first),
object: self,
};
}
}
self.push_front(key, value);
RemovedByInsertFront {
first: None,
object: self,
}
}
pub fn remove<'q, Q: ?Sized>(&mut self, key: &'q Q) -> RemovedEntries<'_, 'q, Q>
where
Q: Hash + Equivalent<Key>,
{
RemovedEntries { key, object: self }
}
pub fn remove_unique<Q: ?Sized>(&mut self, key: &Q) -> Result<Option<Entry>, Duplicate<Entry>>
where
Q: Hash + Equivalent<Key>,
{
let mut entries = self.remove(key);
match entries.next() {
Some(entry) => match entries.next() {
Some(duplicate) => Err(Duplicate(entry, duplicate)),
None => Ok(Some(entry)),
},
None => Ok(None),
}
}
pub fn sort(&mut self) {
use locspan::BorrowStripped;
self.entries.sort_by(|a, b| a.stripped().cmp(b.stripped()));
self.indexes.clear();
for i in 0..self.entries.len() {
self.indexes.insert(&self.entries, i);
}
}
#[cfg(feature = "canonicalize")]
pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
for (_, item) in self.iter_mut() {
item.canonicalize_with(buffer);
}
self.sort()
}
#[cfg(feature = "canonicalize")]
pub fn canonicalize(&mut self) {
let mut buffer = ryu_js::Buffer::new();
self.canonicalize_with(&mut buffer)
}
}
pub struct IterMut<'a>(std::slice::IterMut<'a, Entry>);
impl<'a> Iterator for IterMut<'a> {
type Item = (&'a Key, &'a mut Value);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|entry| (&entry.key, &mut entry.value))
}
}
impl PartialEq for Object {
fn eq(&self, other: &Self) -> bool {
self.entries == other.entries
}
}
impl Eq for Object {}
impl UnorderedPartialEq for Object {
fn unordered_eq(&self, other: &Self) -> bool {
if self.entries.len() != other.entries.len() {
return false;
}
if !self.iter().all(|Entry { key, value: a }| {
other
.get_entries(key)
.any(|Entry { value: b, .. }| a.unordered_eq(b))
}) {
return false;
}
if self.indexes.contains_duplicate_keys()
&& !other.iter().all(
|Entry {
key: other_key,
value: b,
}| {
self.get_entries(other_key)
.any(|Entry { value: a, .. }| a.unordered_eq(b))
},
) {
return false;
}
true
}
}
impl UnorderedEq for Object {}
impl PartialOrd for Object {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.entries.cmp(&other.entries))
}
}
impl Ord for Object {
fn cmp(&self, other: &Self) -> Ordering {
self.entries.cmp(&other.entries)
}
}
impl Hash for Object {
fn hash<H: Hasher>(&self, state: &mut H) {
self.entries.hash(state)
}
}
impl fmt::Debug for Object {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map()
.entries(self.entries.iter().map(Entry::as_pair))
.finish()
}
}
impl From<Vec<Entry>> for Object {
fn from(entries: Vec<Entry>) -> Self {
Self::from_vec(entries)
}
}
impl<'a> IntoIterator for &'a Object {
type Item = &'a Entry;
type IntoIter = core::slice::Iter<'a, Entry>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut Object {
type Item = (&'a Key, &'a mut Value);
type IntoIter = IterMut<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl IntoIterator for Object {
type Item = Entry;
type IntoIter = std::vec::IntoIter<Entry>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl Extend<Entry> for Object {
fn extend<I: IntoIterator<Item = Entry>>(&mut self, iter: I) {
for entry in iter {
self.push_entry(entry);
}
}
}
impl FromIterator<Entry> for Object {
fn from_iter<I: IntoIterator<Item = Entry>>(iter: I) -> Self {
let mut object = Object::default();
object.extend(iter);
object
}
}
impl Extend<(Key, Value)> for Object {
fn extend<I: IntoIterator<Item = (Key, Value)>>(&mut self, iter: I) {
for (key, value) in iter {
self.push(key, value);
}
}
}
impl FromIterator<(Key, Value)> for Object {
fn from_iter<I: IntoIterator<Item = (Key, Value)>>(iter: I) -> Self {
let mut object = Object::default();
object.extend(iter);
object
}
}
pub enum Indexes<'a> {
Some {
first: Option<usize>,
other: core::slice::Iter<'a, usize>,
},
None,
}
impl<'a> Default for Indexes<'a> {
fn default() -> Self {
Self::None
}
}
impl<'a> Iterator for Indexes<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Some { first, other } => match first.take() {
Some(index) => Some(index),
None => other.next().cloned(),
},
Self::None => None,
}
}
}
macro_rules! entries_iter {
($($id:ident <$lft:lifetime> {
type Item = $item:ty ;
fn next(&mut $self:ident, $index:ident) { $e:expr }
})*) => {
$(
pub struct $id<$lft> {
indexes: Indexes<$lft>,
object: &$lft Object
}
impl<$lft> Iterator for $id<$lft> {
type Item = $item;
fn next(&mut $self) -> Option<Self::Item> {
$self.indexes.next().map(|$index| $e)
}
}
)*
};
}
entries_iter! {
Values<'a> {
type Item = &'a Value;
fn next(&mut self, index) { &self.object.entries[index].value }
}
ValuesWithIndex<'a> {
type Item = (usize, &'a Value);
fn next(&mut self, index) { (index, &self.object.entries[index].value) }
}
Entries<'a> {
type Item = &'a Entry;
fn next(&mut self, index) { &self.object.entries[index] }
}
EntriesWithIndex<'a> {
type Item = (usize, &'a Entry);
fn next(&mut self, index) { (index, &self.object.entries[index]) }
}
}
macro_rules! entries_iter_mut {
($($id:ident <$lft:lifetime> {
type Item = $item:ty ;
fn next(&mut $self:ident, $index:ident) { $e:expr }
})*) => {
$(
pub struct $id<$lft> {
indexes: Indexes<$lft>,
entries: &$lft mut [Entry]
}
impl<$lft> Iterator for $id<$lft> {
type Item = $item;
fn next(&mut $self) -> Option<Self::Item> {
$self.indexes.next().map(|$index| $e)
}
}
)*
};
}
entries_iter_mut! {
ValuesMut<'a> {
type Item = &'a mut Value;
fn next(&mut self, index) {
unsafe { core::mem::transmute(&mut self.entries[index].value) }
}
}
ValuesMutWithIndex<'a> {
type Item = (usize, &'a mut Value);
fn next(&mut self, index) {
unsafe { (index, core::mem::transmute(&mut self.entries[index].value)) }
}
}
}
pub struct RemovedByInsertion<'a> {
index: usize,
first: Option<Entry>,
object: &'a mut Object,
}
impl<'a> Iterator for RemovedByInsertion<'a> {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
match self.first.take() {
Some(entry) => Some(entry),
None => {
let key = &self.object.entries[self.index].key;
self.object
.redundant_index_of(key)
.and_then(|index| self.object.remove_at(index))
}
}
}
}
impl<'a> Drop for RemovedByInsertion<'a> {
fn drop(&mut self) {
self.last();
}
}
pub struct RemovedByInsertFront<'a> {
first: Option<Entry>,
object: &'a mut Object,
}
impl<'a> Iterator for RemovedByInsertFront<'a> {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
match self.first.take() {
Some(entry) => Some(entry),
None => {
let key = &self.object.entries[0].key;
self.object
.redundant_index_of(key)
.and_then(|index| self.object.remove_at(index))
}
}
}
}
impl<'a> Drop for RemovedByInsertFront<'a> {
fn drop(&mut self) {
self.last();
}
}
pub struct RemovedEntries<'a, 'q, Q: ?Sized>
where
Q: Hash + Equivalent<Key>,
{
key: &'q Q,
object: &'a mut Object,
}
impl<'a, 'q, Q: ?Sized> Iterator for RemovedEntries<'a, 'q, Q>
where
Q: Hash + Equivalent<Key>,
{
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.object
.index_of(self.key)
.and_then(|index| self.object.remove_at(index))
}
}
impl<'a, 'q, Q: ?Sized> Drop for RemovedEntries<'a, 'q, Q>
where
Q: Hash + Equivalent<Key>,
{
fn drop(&mut self) {
self.last();
}
}
#[derive(Debug)]
pub struct Duplicate<T>(pub T, pub T);
pub type DuplicateEntry = Duplicate<Entry>;
impl fmt::Display for DuplicateEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "duplicate entry `{}`", self.0.key)
}
}
impl std::error::Error for DuplicateEntry {}
#[cfg(test)]
mod tests {
use crate::BorrowUnordered;
use super::*;
#[test]
fn remove() {
let mut object = Object::new();
object.insert("a".into(), Value::Null);
object.remove("a");
object.remove("a");
}
#[test]
fn unordered_eq1() {
let mut a = Object::new();
a.push("a".into(), Value::Null);
a.push("b".into(), Value::Null);
let mut b = Object::new();
b.push("b".into(), Value::Null);
b.push("a".into(), Value::Null);
assert_ne!(a, b);
assert_eq!(a.as_unordered(), b.as_unordered())
}
#[test]
fn unordered_eq2() {
let mut a = Object::new();
a.push("a".into(), Value::Null);
a.push("a".into(), Value::Null);
let mut b = Object::new();
b.push("a".into(), Value::Null);
b.push("a".into(), Value::Null);
assert_eq!(a, b);
assert_eq!(a.as_unordered(), b.as_unordered())
}
#[test]
fn insert_front1() {
let mut a = Object::new();
a.push("a".into(), Value::Null);
a.push("b".into(), Value::Null);
a.push("c".into(), Value::Null);
a.insert_front("b".into(), Value::Null);
let mut b = Object::new();
b.push("b".into(), Value::Null);
b.push("a".into(), Value::Null);
b.push("c".into(), Value::Null);
assert_eq!(a, b);
}
#[test]
fn insert_front2() {
let mut a = Object::new();
a.push("a".into(), Value::Null);
a.push("a".into(), Value::Null);
a.push("c".into(), Value::Null);
a.insert_front("a".into(), Value::Null);
let mut b = Object::new();
b.push("a".into(), Value::Null);
b.push("c".into(), Value::Null);
assert_eq!(a, b);
}
}