use std::rc::Rc;
#[derive(Clone, Debug, Default)]
pub struct Map {
entries: Vec<(String, Value)>,
}
impl Map {
#[must_use]
pub fn new() -> Self {
Map {
entries: Vec::new(),
}
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
#[must_use]
pub fn contains_key(&self, key: &str) -> bool {
self.entries.iter().any(|(k, _)| k == key)
}
#[must_use]
pub fn get(&self, key: &str) -> Option<&Value> {
self.entries.iter().find(|(k, _)| k == key).map(|(_, v)| v)
}
pub fn insert(&mut self, key: String, value: Value) {
if let Some(entry) = self.entries.iter_mut().find(|(k, _)| *k == key) {
entry.1 = value;
} else {
self.entries.push((key, value));
}
}
pub fn remove(&mut self, key: &str) {
self.entries.retain(|(k, _)| k != key);
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
self.entries.iter().map(|(k, v)| (k, v))
}
}
impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool {
if self.entries.len() != other.entries.len() {
return false;
}
self.entries.iter().all(|(k, v)| other.get(k) == Some(v))
}
}
impl FromIterator<(String, Value)> for Map {
fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
let mut map = Map::new();
for (k, v) in iter {
map.insert(k, v);
}
map
}
}
impl IntoIterator for Map {
type Item = (String, Value);
type IntoIter = std::vec::IntoIter<(String, Value)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
#[derive(Clone, Debug)]
pub enum Value {
Undefined,
Null,
Bool(bool),
Number(f64),
String(String),
Array(Rc<Vec<Value>>),
Object(Rc<Map>),
}
impl Value {
#[must_use]
pub fn is_undefined(&self) -> bool {
matches!(self, Value::Undefined)
}
#[must_use]
pub fn as_array(&self) -> Option<&[Value]> {
match self {
Value::Array(items) => Some(items),
_ => None,
}
}
#[must_use]
pub fn as_object(&self) -> Option<&Map> {
match self {
Value::Object(map) => Some(map),
_ => None,
}
}
#[must_use]
pub fn array(items: Vec<Value>) -> Value {
Value::Array(Rc::new(items))
}
#[must_use]
pub fn object(map: Map) -> Value {
Value::Object(Rc::new(map))
}
#[must_use]
pub fn from_pairs<K, I>(pairs: I) -> Value
where
K: Into<String>,
I: IntoIterator<Item = (K, Value)>,
{
let map = pairs.into_iter().map(|(k, v)| (k.into(), v)).collect();
Value::object(map)
}
#[must_use]
pub fn ptr_eq(&self, other: &Value) -> bool {
match (self, other) {
(Value::Array(a), Value::Array(b)) => Rc::ptr_eq(a, b),
(Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b),
_ => false,
}
}
#[must_use]
pub fn same_value(&self, other: &Value) -> bool {
match (self, other) {
(Value::Undefined, Value::Undefined) | (Value::Null, Value::Null) => true,
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::Number(a), Value::Number(b)) => {
(a.is_nan() && b.is_nan()) || a.to_bits() == b.to_bits()
}
(Value::String(a), Value::String(b)) => a == b,
(Value::Array(_), Value::Array(_)) | (Value::Object(_), Value::Object(_)) => {
self.ptr_eq(other)
}
_ => false,
}
}
}
impl From<f64> for Value {
fn from(n: f64) -> Value {
Value::Number(n)
}
}
impl From<f32> for Value {
fn from(n: f32) -> Value {
Value::Number(f64::from(n))
}
}
impl From<i32> for Value {
fn from(n: i32) -> Value {
Value::Number(f64::from(n))
}
}
impl From<u32> for Value {
fn from(n: u32) -> Value {
Value::Number(f64::from(n))
}
}
impl From<bool> for Value {
fn from(b: bool) -> Value {
Value::Bool(b)
}
}
impl From<&str> for Value {
fn from(s: &str) -> Value {
Value::String(s.to_string())
}
}
impl From<String> for Value {
fn from(s: String) -> Value {
Value::String(s)
}
}
impl From<Vec<Value>> for Value {
fn from(items: Vec<Value>) -> Value {
Value::array(items)
}
}
impl From<Map> for Value {
fn from(map: Map) -> Value {
Value::object(map)
}
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
match (self, other) {
(Value::Undefined, Value::Undefined) | (Value::Null, Value::Null) => true,
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::Number(a), Value::Number(b)) => {
(a.is_nan() && b.is_nan()) || a.to_bits() == b.to_bits()
}
(Value::String(a), Value::String(b)) => a == b,
(Value::Array(a), Value::Array(b)) => a == b,
(Value::Object(a), Value::Object(b)) => a == b,
_ => false,
}
}
}