Skip to content

Commit

Permalink
Add missing traits
Browse files Browse the repository at this point in the history
Signed-off-by: Heinz N. Gies <[email protected]>
  • Loading branch information
Licenser committed Aug 3, 2024
1 parent 0549edc commit 9b7b5d2
Show file tree
Hide file tree
Showing 10 changed files with 955 additions and 254 deletions.
2 changes: 1 addition & 1 deletion src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1262,7 +1262,7 @@ macro_rules! static_cast_i8 {
#[macro_export]
macro_rules! static_cast_i32 {
($v:expr) => {
std::mem::transmute::<u32, i32>($v)
::std::mem::transmute::<u32, i32>($v)
};
}

Expand Down
3 changes: 0 additions & 3 deletions src/numberparse/approx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,6 @@ impl<'de> Deserializer<'de> {

#[cfg(feature = "swar-number-parsing")]
{
// FIXME
// can we omit this: buf.len() - byte_count >= 8
let chars: [u8; 8] = unsafe {
*(buf
.get_kinda_unchecked(byte_count..byte_count + 8)
Expand Down Expand Up @@ -528,7 +526,6 @@ impl<'de> Deserializer<'de> {
StaticNode::F64(0.0)
} else {
if !(-323..=308).contains(&exponent) {
//FIXME Parse it as a expensive float perhaps
return Self::parse_float(idx, buf, negative);
}

Expand Down
253 changes: 44 additions & 209 deletions src/value/lazy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
use crate::prelude::*;
//! Lazy value, this gets initialized with a tape and as long as only non mutating operations are performed
//! it will stay a tape. If it is mutated it is upgtaded to a borrowed value.
//! This allows for a very cheap parsin and data access while still maintaining mutability.
//!
//! # Example
//!
//! ```rust
//! use simd_json::{prelude::*, value::lazy::Value};
//!
//! let mut json = br#"{"key": "value", "snot": 42}"#.to_vec();
//! let tape = simd_json::to_tape( json.as_mut_slice()).unwrap();
//! let value = tape.as_value();
//! let mut lazy = Value::from_tape(value);
//!
//! assert_eq!(lazy.get("key").unwrap(), "value");
//!
//! assert!(lazy.is_tape());
//! lazy.insert("new", 42);
//! assert!(lazy.is_value());
//! assert_eq!(lazy.get("key").unwrap(), "value");
//! assert_eq!(lazy.get("new").unwrap(), 42);
//! ```
use crate::{borrowed, tape};
use std::borrow::Cow;
use std::fmt;
Expand All @@ -7,6 +29,7 @@ mod array;
mod cmp;
mod from;
mod object;
mod trait_impls;

pub use array::Array;
pub use object::Object;
Expand All @@ -15,7 +38,10 @@ pub use object::Object;
/// performed it will stay a tape. If a mutating operation is performed it will upgrade to a borrowed
/// value.
#[derive(Clone, Debug, PartialEq)]
pub enum Value<'tape, 'input> {
pub enum Value<'tape, 'input>
where
'input: 'tape,
{
/// tape variant
Tape(tape::Value<'tape, 'input>),
/// borrowed variant
Expand All @@ -30,6 +56,20 @@ impl Default for Value<'static, '_> {
}

impl<'tape, 'input> Value<'tape, 'input> {
/// returns true when the current representation is a tape
#[must_use]
pub fn is_tape(&self) -> bool {
match self {
Value::Tape(_) => true,
Value::Value(_) => false,
}
}
/// returns true when the current representation is a borrowed value
/// this is the opposite of `is_tape`
#[must_use]
pub fn is_value(&self) -> bool {
!self.is_tape()
}
/// Creates a new lazy Value from a tape
#[must_use]
pub fn from_tape(tape: tape::Value<'tape, 'input>) -> Self {
Expand All @@ -55,13 +95,6 @@ impl<'tape, 'input> Value<'tape, 'input> {
*self = Value::Value(Cow::Owned(value));
}

fn is_tape(&self) -> bool {
match &self {
Value::Tape(_) => true,
Value::Value(_) => false,
}
}

fn as_mut(&mut self) -> &mut borrowed::Value<'input> {
if self.is_tape() {
self.upgrade();
Expand All @@ -75,205 +108,6 @@ impl<'tape, 'input> Value<'tape, 'input> {
}
}

impl<'value> ValueBuilder<'value> for Value<'static, 'value> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn null() -> Self {
Value::Value(Cow::Owned(borrowed::Value::null()))
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn array_with_capacity(capacity: usize) -> Self {
Value::Value(Cow::Owned(borrowed::Value::array_with_capacity(capacity)))
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn object_with_capacity(capacity: usize) -> Self {
Value::Value(Cow::Owned(borrowed::Value::object_with_capacity(capacity)))
}
}

impl<'tape, 'value> ValueAsMutContainer for Value<'tape, 'value> {
type Array = Vec<borrowed::Value<'value>>;
type Object = super::borrowed::Object<'value>;
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_array_mut(&mut self) -> Option<&mut Vec<borrowed::Value<'value>>> {
self.as_mut().as_array_mut()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_object_mut(&mut self) -> Option<&mut super::borrowed::Object<'value>> {
self.as_mut().as_object_mut()
}
}

impl<'tape, 'value> TypedValue for Value<'tape, 'value> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn value_type(&self) -> ValueType {
match &self {
Value::Tape(tape) => tape.value_type(),
Value::Value(value) => value.value_type(),
}
}
}

impl<'tape, 'value> ValueAsScalar for Value<'tape, 'value> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_null(&self) -> Option<()> {
match &self {
Value::Tape(tape) => tape.as_null(),
Value::Value(value) => value.as_null(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_bool(&self) -> Option<bool> {
match &self {
Value::Tape(tape) => tape.as_bool(),
Value::Value(value) => value.as_bool(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_i64(&self) -> Option<i64> {
match &self {
Value::Tape(tape) => tape.as_i64(),
Value::Value(value) => value.as_i64(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_i128(&self) -> Option<i128> {
match &self {
Value::Tape(tape) => tape.as_i128(),
Value::Value(value) => value.as_i128(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_u64(&self) -> Option<u64> {
match &self {
Value::Tape(tape) => tape.as_u64(),
Value::Value(value) => value.as_u64(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_u128(&self) -> Option<u128> {
match &self {
Value::Tape(tape) => tape.as_u128(),
Value::Value(value) => value.as_u128(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_f64(&self) -> Option<f64> {
match &self {
Value::Tape(tape) => tape.as_f64(),
Value::Value(value) => value.as_f64(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn cast_f64(&self) -> Option<f64> {
match &self {
Value::Tape(tape) => tape.cast_f64(),
Value::Value(value) => value.cast_f64(),
}
}

#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_str(&self) -> Option<&str> {
match &self {
Value::Tape(tape) => tape.as_str(),
Value::Value(value) => value.as_str(),
}
}
}

// impl<'tape, 'value> ValueAsContainer for Value<'tape, 'value> {
impl<'tape, 'value> Value<'tape, 'value> {
// type Array = array::Array<'tape, 'value>;
// type Object = Object<'tape, 'value>;

/// Tries to represent the value as an array and returns a reference to it
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
pub fn as_array(&self) -> Option<array::Array<'_, 'value>> {
match self {
Value::Tape(tape) => tape.as_array().map(Array::Tape),
Value::Value(value) => value.as_array().map(array::Array::Value),
}
}

/// Tries to represent the value as an array and returns a reference to it
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
pub fn as_object(&self) -> Option<object::Object> {
match self {
Value::Tape(tape) => tape.as_object().map(Object::Tape),
Value::Value(value) => value.as_object().map(Object::Value),
}
}
}

impl<'tape, 'value> ValueIntoString for Value<'tape, 'value> {
type String = Cow<'value, str>;

fn into_string(self) -> Option<<Self as ValueIntoString>::String> {
match self {
Value::Tape(tape) => tape.into_string().map(Cow::Borrowed),
// This is a bit complex but it allows us to avoid cloning
Value::Value(value) => match value {
Cow::Borrowed(value) => match value {
#[cfg(feature = "beef")]
borrowed::Value::String(s) => Some(s.clone().into()),
#[cfg(not(feature = "beef"))]
borrowed::Value::String(s) => Some(s.clone()),
_ => None,
},
Cow::Owned(value) => match value {
#[cfg(feature = "beef")]
borrowed::Value::String(s) => Some(s.into()),
#[cfg(not(feature = "beef"))]
borrowed::Value::String(s) => Some(s),
_ => None,
},
},
}
}
}

// impl<'value> ValueIntoContainer for Value<'value> {
// type Array = Vec<Self>;
// type Object = Object<'value>;

// fn into_array(self) -> Option<<Self as ValueIntoContainer>::Array> {
// match self {
// Self::Array(a) => Some(a),
// _ => None,
// }
// }

// fn into_object(self) -> Option<<Self as ValueIntoContainer>::Object> {
// match self {
// Self::Object(a) => Some(*a),
// _ => None,
// }
// }
// }

#[cfg(not(tarpaulin_include))]
impl<'tape, 'value> fmt::Display for Value<'tape, 'value> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -321,8 +155,9 @@ impl<'tape, 'value> fmt::Display for Value<'tape, 'value> {
#[cfg(test)]
mod test {
#![allow(clippy::cognitive_complexity)]
use value_trait::prelude::*;

use super::Value;
use super::*;

#[test]
#[should_panic = "Not supported"]
Expand Down
26 changes: 11 additions & 15 deletions src/value/lazy/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use crate::{borrowed, tape};

#[derive(Clone)]
/// Wrapper around the tape that allows interacting with it via a `Array`-like API.
pub enum Array<'tape, 'value> {
pub enum Array<'tape, 'input> {
/// Tape variant
Tape(tape::Array<'tape, 'value>),
Tape(tape::Array<'tape, 'input>),
/// Value variant
Value(&'tape borrowed::Array<'value>),
Value(&'tape borrowed::Array<'input>),
}

pub enum ArrayIter<'tape, 'input> {
Expand All @@ -29,20 +29,18 @@ impl<'tape, 'input> Iterator for ArrayIter<'tape, 'input> {
}

// value_trait::Array for
impl<'tape, 'input> Array<'tape, 'input>
where
'input: 'tape,
{
/// FIXME: docs
impl<'tape, 'input> Array<'tape, 'input> {
/// Gets a ref to a value based on n index, returns `None` if the
/// current Value isn't an Array or doesn't contain the index
/// it was asked for.
#[must_use]
pub fn get(&self, idx: usize) -> Option<Value<'_, 'input>> {
pub fn get<'a>(&'a self, idx: usize) -> Option<Value<'a, 'input>> {
match self {
Array::Tape(t) => t.get(idx).map(Value::Tape),
Array::Value(v) => v.get(idx).map(Cow::Borrowed).map(Value::Value),
}
}
/// FIXME: docs
/// Iterates over the values paris
#[allow(clippy::pedantic)] // we want into_iter_without_iter but that lint doesn't exist in older clippy
#[must_use]
pub fn iter<'i>(&'i self) -> ArrayIter<'i, 'input> {
Expand All @@ -52,17 +50,15 @@ where
}
}

/// FIXME: docs
/// # Panics
/// if the tape is not an array
/// Number of key/value pairs
#[must_use]
pub fn len(&self) -> usize {
match self {
Array::Tape(t) => t.len(),
Array::Value(v) => v.len(),
}
}
/// FIXME: docs
/// Returns if the array is empty
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
Expand Down
Loading

0 comments on commit 9b7b5d2

Please sign in to comment.