Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make lazyvalue sync #47

Merged
merged 2 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ cfg-if = "1.0"
arrayref = "0.3"
packed_simd = { version = "0.3", package = "packed_simd" }

serde = { version = "1.0", default-features = false }
serde = { version = "1.0", features = ["rc", "derive"] }
itoa = "1.0"
ryu = "1.0"
faststr = "0.2"
Expand Down
5 changes: 3 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use core::{
result,
};
use std::{
borrow::Cow,
error,
str::FromStr,
string::{String, ToString},
Expand Down Expand Up @@ -196,7 +197,7 @@ struct ErrorImpl {
#[derive(ErrorTrait, Debug)]
pub(crate) enum ErrorCode {
#[error("{0}")]
Message(Box<str>),
Message(Cow<'static, str>),

#[error("io error while serializing or deserializing")]
Io(std::io::Error),
Expand Down Expand Up @@ -435,7 +436,7 @@ pub fn make_error(mut msg: String) -> Error {
let (line, column) = parse_line_col(&mut msg).unwrap_or((0, 0));
Error {
err: Box::new(ErrorImpl {
code: ErrorCode::Message(msg.into_boxed_str()),
code: ErrorCode::Message(msg.into()),
line,
column,
descript: None,
Expand Down
10 changes: 6 additions & 4 deletions src/lazyvalue/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ impl<'de: 'a, 'a> Deserialize<'de> for LazyValue<'a> {
where
E: de::Error,
{
Ok(LazyValue::new(FastStr::new(v).into()))
// parse the escaped string
LazyValue::new(FastStr::new(v).into(), true).map_err(de::Error::custom)
}

// borrowed from origin json
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(LazyValue::new(v.into()))
LazyValue::new(FastStr::new(v).into(), false).map_err(de::Error::custom)
}
}

Expand Down Expand Up @@ -64,15 +65,16 @@ impl<'de> Deserialize<'de> for OwnedLazyValue {
where
E: de::Error,
{
Ok(OwnedLazyValue::new(FastStr::new(v).into()))
// parse the escaped string
OwnedLazyValue::new(FastStr::new(v).into(), true).map_err(de::Error::custom)
}

// borrowed from origin json
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(OwnedLazyValue::new(v.into()))
OwnedLazyValue::new(FastStr::new(v).into(), false).map_err(de::Error::custom)
}
}

Expand Down
26 changes: 8 additions & 18 deletions src/lazyvalue/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
error::Result,
index::Index,
input::JsonInput,
parser::Parser,
parser::{ParseStatus, Parser},
pointer::PointerTree,
reader::{Reader, SliceRead},
util::utf8::from_utf8,
Expand Down Expand Up @@ -141,9 +141,8 @@ where
let slice = json.to_u8_slice();
let reader = SliceRead::new(slice);
let mut parser = Parser::new(reader);
parser
.get_from_with_iter(path)
.map(|sub| LazyValue::new(json.from_subset(sub)))
let (sub, status) = parser.get_from_with_iter(path)?;
LazyValue::new(json.from_subset(sub), status == ParseStatus::HasEsacped)
}

/// get_many returns multiple fields from the `PointerTree`.
Expand Down Expand Up @@ -180,11 +179,7 @@ where
let slice = json.to_u8_slice();
let reader = SliceRead::new(slice);
let mut parser = Parser::new(reader);
let out = parser.get_many(tree, false)?;
Ok(out
.into_iter()
.map(|subset| LazyValue::new(json.from_subset(subset)))
.collect())
parser.get_many(tree, false)
}

/// Gets a field from path. And return it as a `LazyValue`. If not found, return a err.
Expand Down Expand Up @@ -309,16 +304,15 @@ where
let slice = json.to_u8_slice();
let reader = SliceRead::new(slice);
let mut parser = Parser::new(reader);
let node = parser
.get_from_with_iter_checked(path)
.map(|sub| LazyValue::new(json.from_subset(sub)))?;
let (sub, status) = parser.get_from_with_iter_checked(path)?;
let lv = LazyValue::new(json.from_subset(sub), status == ParseStatus::HasEsacped)?;

// validate the utf-8 if slice
let index = parser.read.index();
if json.need_utf8_valid() {
from_utf8(&slice[..index])?;
}
Ok(node)
Ok(lv)
}

/// get_many returns multiple fields from the `PointerTree`.
Expand Down Expand Up @@ -348,11 +342,7 @@ where
let slice = json.to_u8_slice();
let reader = SliceRead::new(slice);
let mut parser = Parser::new(reader);
let out = parser.get_many(tree, true)?;
let nodes = out
.into_iter()
.map(|subset| LazyValue::new(json.from_subset(subset)))
.collect();
let nodes = parser.get_many(tree, true)?;

// validate the utf-8 if slice
let index = parser.read.index();
Expand Down
8 changes: 4 additions & 4 deletions src/lazyvalue/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ impl<'de> ObjectInner<'de> {
let parser = unsafe { self.parser.as_mut().unwrap_unchecked() };
match parser.parse_entry_lazy(&mut self.strbuf, &mut self.first, check) {
Ok(ret) => {
if let Some((key, val)) = ret {
if let Some((key, val, has_escaped)) = ret {
let val = self.json.slice_ref(val);
Some(Ok((key, LazyValue::new(val))))
Some(LazyValue::new(val, has_escaped).map(|v| (key, v)))
} else {
self.ending = true;
None
Expand Down Expand Up @@ -155,9 +155,9 @@ impl<'de> ArrayInner<'de> {
let parser = unsafe { self.parser.as_mut().unwrap_unchecked() };
match parser.parse_array_elem_lazy(&mut self.first, check) {
Ok(ret) => {
if let Some(ret) = ret {
if let Some((ret, has_escaped)) = ret {
let val = self.json.slice_ref(ret);
Some(Ok(LazyValue::new(val)))
Some(LazyValue::new(val, has_escaped))
} else {
self.ending = true;
None
Expand Down
73 changes: 36 additions & 37 deletions src/lazyvalue/owned.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
use std::{cell::UnsafeCell, hash::Hash, str::from_utf8_unchecked};
use std::{hash::Hash, str::from_utf8_unchecked, sync::Arc};

use faststr::FastStr;

use crate::{
from_str, get_unchecked,
index::Index,
input::JsonSlice,
parser::Parser,
reader::{Reader, Reference, SliceRead},
serde::Number,
JsonType, JsonValueTrait, LazyValue,
from_str, get_unchecked, index::Index, input::JsonSlice, serde::Number, JsonType,
JsonValueTrait, LazyValue, Result,
};

/// LazyValue is a value that wrappers a raw JSON text. It is used for lazy parsing, which means the
/// JSON text is not parsed until it is used.
/// OwnedLazyValue wrappers a unparsed raw JSON text. It is owned. It can be converted from
/// [`LazyValue`](crate::lazyvalue::LazyValue). It can be used for serde.
///
/// # Examples
///
/// ```
/// use sonic_rs::{get, JsonValueTrait, LazyValue, Value};
/// use sonic_rs::{get, JsonValueTrait, OwnedLazyValue};
///
/// // get a lazyvalue from a json, the "a"'s value will not be parsed
/// let input = r#"{
Expand All @@ -29,25 +24,22 @@ use crate::{
/// "sonic": "rs"
/// }
/// }"#;
/// let lv_a: LazyValue = get(input, &["a"]).unwrap();
/// let lv_c: LazyValue = get(input, &["c"]).unwrap();
///
/// let own_a = OwnedLazyValue::from(get(input, &["a"]).unwrap());
/// let own_c = OwnedLazyValue::from(get(input, &["c"]).unwrap());
///
/// // use as_raw_xx to get the unparsed JSON text
/// assert_eq!(lv_a.as_raw_str(), "\"hello world\"");
/// assert_eq!(lv_c.as_raw_str(), "[0, 1, 2]");
/// assert_eq!(own_a.as_raw_str(), "\"hello world\"");
/// assert_eq!(own_c.as_raw_str(), "[0, 1, 2]");
///
/// // use as_xx to get the parsed value
/// assert_eq!(lv_a.as_str().unwrap(), "hello world");
/// assert_eq!(lv_c.as_str(), None);
/// assert!(lv_c.is_array());
/// assert_eq!(own_a.as_str().unwrap(), "hello world");
/// assert_eq!(own_c.as_str(), None);
/// assert!(own_c.is_array());
/// ```
///
/// # Serde Examples
///
/// `OwnedLazyValue` can be deserialized with borrowed or owned.
/// If borrowed, lifetime `'a` is the origin JSON text.
/// If owned, lifetime `'a` is not associate with origin JSON text.
///
/// ```
/// # use sonic_rs::{LazyValue, OwnedLazyValue};
/// use serde::{Deserialize, Serialize};
Expand All @@ -69,8 +61,7 @@ use crate::{
pub struct OwnedLazyValue {
// the raw slice from origin json
pub(crate) raw: FastStr,
// used for deserialize escaped strings
own: UnsafeCell<Vec<u8>>,
unescape: Option<Arc<str>>,
}

impl PartialEq for OwnedLazyValue {
Expand All @@ -83,7 +74,7 @@ impl Clone for OwnedLazyValue {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
own: UnsafeCell::new(Vec::new()),
unescape: self.unescape.clone(),
}
}
}
Expand Down Expand Up @@ -128,12 +119,17 @@ impl JsonValueTrait for OwnedLazyValue {
}

fn as_str(&self) -> Option<&str> {
let mut parser = Parser::new(SliceRead::new(self.as_raw_str().as_bytes()));
parser.read.eat(1);
match parser.parse_string_raw(unsafe { &mut *self.own.get() }) {
Ok(Reference::Borrowed(u)) => unsafe { Some(from_utf8_unchecked(u)) },
Ok(Reference::Copied(u)) => unsafe { Some(from_utf8_unchecked(u)) },
_ => None,
if !self.is_str() {
None
} else if let Some(escaped) = self.unescape.as_ref() {
Some(escaped.as_ref())
} else {
// remove the quotes
let origin = {
let raw = self.as_raw_str().as_bytes();
&raw[1..raw.len() - 1]
};
Some(unsafe { from_utf8_unchecked(origin) })
}
}

Expand Down Expand Up @@ -223,15 +219,18 @@ impl OwnedLazyValue {
lv.map(|v| v.into())
}

pub(crate) fn new(raw: JsonSlice) -> Self {
pub(crate) fn new(raw: JsonSlice, has_escaped: bool) -> Result<Self> {
let raw = match raw {
JsonSlice::Raw(r) => FastStr::new(unsafe { from_utf8_unchecked(r) }),
JsonSlice::FastStr(f) => f.clone(),
};
Self {
raw,
own: UnsafeCell::new(Vec::new()),
}
let unescape = if has_escaped {
let unescape: Arc<str> = unsafe { crate::from_slice_unchecked(raw.as_ref()) }?;
Some(unescape)
} else {
None
};
Ok(Self { raw, unescape })
}
}

Expand All @@ -243,7 +242,7 @@ impl<'de> From<LazyValue<'de>> for OwnedLazyValue {
};
Self {
raw,
own: UnsafeCell::new(Vec::new()),
unescape: lv.unescape,
}
}
}
21 changes: 1 addition & 20 deletions src/lazyvalue/ser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use ::serde::{ser::SerializeStruct, Serialize};
use ::serde::ser::SerializeStruct;

use super::{owned::OwnedLazyValue, value::LazyValue};
use crate::Result;

impl<'a> serde::ser::Serialize for LazyValue<'a> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
Expand Down Expand Up @@ -29,24 +28,6 @@ impl serde::ser::Serialize for OwnedLazyValue {
}
}

/// Convert a `T: Serialize` into a `LazyValue`.
pub fn to_lazyvalue<'a, T>(value: &T) -> Result<LazyValue<'a>>
where
T: ?Sized + Serialize,
{
let json_string = crate::to_string(value)?;
Ok(LazyValue::new(json_string.into()))
}

/// Convert a `T: Serialize` into a `OwnedLazyValue`.
pub fn to_ownedlazyvalue<T>(value: &T) -> Result<OwnedLazyValue>
where
T: ?Sized + Serialize,
{
let json_string = crate::to_string(value)?;
Ok(OwnedLazyValue::new(json_string.into()))
}

#[cfg(test)]
mod test {
use ::serde::{Deserialize, Serialize};
Expand Down
Loading
Loading