Skip to content

Commit

Permalink
Merge branch 'main' into feat/object_map
Browse files Browse the repository at this point in the history
  • Loading branch information
Ggiggle authored Jan 23, 2025
2 parents b7fb996 + 9bbde4e commit b1a8e9b
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 57 deletions.
74 changes: 36 additions & 38 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,58 @@ env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always

jobs:
jobs:
test-stable:
name: Rust stable ${{matrix.os}}
runs-on: ${{matrix.os}}-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu, macos]
name: Rust stable ubuntu-latest
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v1
- run: ./scripts/test.sh

test-stable-self:
name: Rust stable on self-hosted
runs-on: [self-hosted]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v1
- run: ./scripts/test.sh

test-nightly:
name: Rust nightly ${{matrix.os}}
runs-on: ${{matrix.os}}-latest
test-stable-hosted:
strategy:
fail-fast: false
matrix:
os: [ubuntu, macos]
os:
- [self-hosted, Linux, X64]
- [self-hosted, Linux, ARM64]
name: Rust stable
runs-on: ${{matrix.os}}
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v1
- uses: dtolnay/rust-toolchain@stable
- run: ./scripts/test.sh

test-nightlye-self:
name: Rust nightly on self-hosted
runs-on: [self-hosted]
test-nightly:
name: Rust nightly ubuntu-latest
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v1
- run: ./scripts/test.sh
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: ./scripts/test.sh

clippy_lint:
name: Format check ${{matrix.os}}
runs-on: ${{matrix.os}}-latest
test-nightly-hosted:
strategy:
fail-fast: false
matrix:
os: [ubuntu, macos]
fail-fast: false
matrix:
os:
- [self-hosted, Linux, X64]
- [self-hosted, Linux, ARM64]
name: Rust nightly ${{matrix.os}}
runs-on: ${{matrix.os}}
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: ./scripts/test.sh

clippy_lint:
name: Format check
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
Expand All @@ -73,7 +71,7 @@ jobs:
cargo fmt -- --check
sanitize:
runs-on: [self-hosted, X64]
runs-on: [self-hosted, Linux, X64]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -86,7 +84,7 @@ jobs:
run: ./scripts/sanitize.sh

fuzz:
runs-on: [self-hosted, X64]
runs-on: [self-hosted, Linux, X64]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ permissions:

jobs:
dependency-review:
runs-on: [self-hosted, X64]
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion examples/json_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn filter_json<W: WriteExt>(json: &str, keys: HashSet<FastStr>, w: W) -> sonic_r
let mut maper = outer.serialize_map(None)?;
for ret in to_object_iter(json) {
let (name, value) = ret.expect("invalid json");
if keys.contains(&name) {
if keys.contains(name.as_ref()) {
maper.serialize_entry(&name, &value)?;
}
}
Expand Down
10 changes: 5 additions & 5 deletions fuzz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ pub fn sonic_rs_fuzz_data(data: &[u8]) {
let owned: OwnedLazyValue = sonic_rs::from_slice(data).unwrap();
for ret in to_object_iter(data) {
let (k, lv) = ret.unwrap();
let jv = jv.get(k.as_str()).unwrap();
let ov = owned.get(k.as_str()).unwrap();
let jv = jv.get(k.as_ref()).unwrap();
let ov = owned.get(k.as_ref()).unwrap();
compare_owned_lazyvalue(jv, ov);
compare_lazyvalue(jv, &lv);

let gv = sonic_rs::get(data, &[k.as_str()]).unwrap();
let gv = sonic_rs::get(data, &[k.as_ref()]).unwrap();
compare_lazyvalue(jv, &gv);
}
compare_owned_lazyvalue(&jv, &owned);
Expand All @@ -77,10 +77,10 @@ pub fn sonic_rs_fuzz_data(data: &[u8]) {
unsafe {
for ret in to_object_iter_unchecked(data) {
let (k, lv) = ret.unwrap();
let jv = jv.get(k.as_str()).unwrap();
let jv = jv.get(k.as_ref()).unwrap();
compare_lazyvalue(jv, &lv);

let gv = sonic_rs::get_unchecked(data, &[k.as_str()]).unwrap();
let gv = sonic_rs::get_unchecked(data, &[k.as_ref()]).unwrap();
compare_lazyvalue(jv, &gv);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ pub trait Formatter {
writer.write_all(value.as_bytes())
}

/// Writes a string fragment that doesn't need any escaping to the
/// specified writer.
/// Writes a string as JSON string to the specified writer. Will escape the string if necessary.
/// If `need_quote` is `false`, the string will be written without quotes.
#[inline]
fn write_string_fast<W>(
&mut self,
Expand Down
14 changes: 7 additions & 7 deletions src/lazyvalue/iterator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use faststr::FastStr;
use std::borrow::Cow;

use crate::{
error::Result,
input::{JsonInput, JsonSlice},
lazyvalue::LazyValue,
parser::{Parser, DEFAULT_KEY_BUF_CAPACITY},
parser::{Pair, Parser, DEFAULT_KEY_BUF_CAPACITY},
reader::{Read, Reader},
};
/// A lazied iterator for JSON object text. It will parse the JSON when iterating.
Expand Down Expand Up @@ -101,7 +101,7 @@ impl<'de> ObjectJsonIter<'de> {
}
}

fn next_entry_impl(&mut self) -> Option<Result<(FastStr, LazyValue<'de>)>> {
fn next_entry_impl(&mut self) -> Option<Result<(Cow<'de, str>, LazyValue<'de>)>> {
if self.ending {
return None;
}
Expand All @@ -119,7 +119,7 @@ impl<'de> ObjectJsonIter<'de> {
.parse_entry_lazy(&mut self.strbuf, &mut self.first, self.skip_strict)
{
Ok(ret) => {
if let Some((key, val, status)) = ret {
if let Some(Pair { key, val, status }) = ret {
let val = self.parser.read.slice_ref(val);
Some(Ok(LazyValue::new(val, status.into())).map(|v| (key, v)))
} else {
Expand Down Expand Up @@ -345,7 +345,7 @@ pub unsafe fn to_array_iter_unchecked<'de, I: JsonInput<'de>>(json: I) -> ArrayJ
}

impl<'de> Iterator for ObjectJsonIter<'de> {
type Item = Result<(FastStr, LazyValue<'de>)>;
type Item = Result<(Cow<'de, str>, LazyValue<'de>)>;

fn next(&mut self) -> Option<Self::Item> {
self.next_entry_impl()
Expand Down Expand Up @@ -390,7 +390,7 @@ mod test {

let mut test_ok = |key: &str, val: &str, typ: JsonType| {
let ret = iter.next().unwrap().unwrap();
assert_eq!(ret.0.as_str(), key);
assert_eq!(ret.0.as_ref(), key);
assert_eq!(
ret.1.as_raw_str().as_bytes(),
val.as_bytes(),
Expand All @@ -400,7 +400,7 @@ mod test {
assert_eq!(ret.1.get_type(), typ);

let ret = iter_unchecked.next().unwrap().unwrap();
assert_eq!(ret.0.as_str(), key);
assert_eq!(ret.0.as_ref(), key);
assert_eq!(
ret.1.as_raw_str().as_bytes(),
val.as_bytes(),
Expand Down
26 changes: 23 additions & 3 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
borrow::Cow,
collections::HashMap,
num::NonZeroU8,
ops::Deref,
Expand Down Expand Up @@ -46,6 +47,15 @@ where
Copied(&'c T),
}

impl<'b, 'c> From<Reference<'b, 'c, str>> for Cow<'b, str> {
fn from(value: Reference<'b, 'c, str>) -> Self {
match value {
Reference::Borrowed(b) => Cow::Borrowed(b),
Reference::Copied(c) => Cow::Owned(c.to_string()),
}
}
}

impl<'b, 'c, T> Deref for Reference<'b, 'c, T>
where
T: ?Sized + 'static,
Expand Down Expand Up @@ -186,6 +196,12 @@ fn skip_container_loop(
None
}

pub(crate) struct Pair<'de> {
pub key: Cow<'de, str>,
pub val: &'de [u8],
pub status: ParseStatus,
}

pub(crate) struct Parser<R> {
pub(crate) read: R,
error_index: usize, // mark the error position
Expand Down Expand Up @@ -522,7 +538,7 @@ where
strbuf: &mut Vec<u8>,
first: &mut bool,
check: bool,
) -> Result<Option<(FastStr, &'de [u8], ParseStatus)>> {
) -> Result<Option<Pair<'de>>> {
if *first && self.skip_space() != Some(b'{') {
return perr!(self, ExpectedObjectStart);
}
Expand All @@ -538,14 +554,18 @@ where
}

let parsed = self.parse_str_impl(strbuf)?;
let key = FastStr::new(parsed.deref());
self.parse_object_clo()?;
let (raw, status) = if check {
self.skip_one()
} else {
self.skip_one_unchecked()
}?;
Ok(Some((key, raw, status)))

Ok(Some(Pair {
key: parsed.into(),
val: raw,
status,
}))
}

// Not use non-recurse version here, because it maybe 5% slower than recurse version.
Expand Down

0 comments on commit b1a8e9b

Please sign in to comment.