Skip to content

Commit

Permalink
Add first prototype of simple API
Browse files Browse the repository at this point in the history
See #34
  • Loading branch information
Marcono1234 committed Dec 23, 2023
1 parent e7fbcc7 commit b99723e
Show file tree
Hide file tree
Showing 10 changed files with 1,678 additions and 8 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ assert_no_alloc = { git = "https://github.com/Windfisch/rust-assert-no-alloc.git
"backtrace",
] }

[features]
# Feature for all experimental functionality of Struson which is likely going to change in the future,
# or might even be removed again
# Note: Might be better to use standard Rust attributes for this once they are available, see https://github.com/rust-lang/rfcs/issues/1491
experimental = []

[lints.rust]
unsafe_code = "forbid"

Expand Down
17 changes: 16 additions & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,38 @@ args = ["test", "--features", "serde"]
dependencies = ["build-serde-interop"]


# All features
[tasks.build-all-features]
command = "cargo"
args = ["build", "--all-targets", "--all-features"]

[tasks.test-all-features]
command = "cargo"
# Important: Don't use `--all-targets` here; that would exclude doc tests (see https://github.com/rust-lang/cargo/issues/6669)
# Benchmark tests are performed further below; could include them here for this execution in the future though
args = ["test", "--all-features"]
dependencies = ["build-all-features"]


[tasks.test-benches]
command = "cargo"
# Run all benchmarks as tests to make sure they don't encounter any errors, e.g. due to malformed JSON
# Unfortunately this seems to rerun library tests, see https://github.com/rust-lang/cargo/issues/6454
args = ["test", "--benches", "--all-features"]
dependencies = ["test-default", "test-serde-interop"]
dependencies = ["test-default", "test-serde-interop", "test-all-features"]

[tasks.build]
dependencies = [
"build-default",
"build-serde-interop",
"build-all-features",
]

[tasks.test]
dependencies = [
"test-default",
"test-serde-interop",
"test-all-features",
"test-benches",
]

Expand Down
62 changes: 60 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,63 @@ If you need to process JSON in a DOM like way or want object mapper functionalit

## Usage examples

### Reading
Two variants of the API are provided:

- simple: ensures correct API usage at compile-time
- advanced: ensures correct API usage only at runtime (by panicking); more flexible and
provides more functionality

### Simple API

**🔬 Experimental**\
The simple API and its naming is currently experimental, please provide feedback [here](https://github.com/Marcono1234/struson/issues/34).
Any feedback is appreciated!

#### Reading

See [`SimpleJsonReader`](https://docs.rs/struson/latest/struson/reader/simple/struct.SimpleJsonReader.html).

```rust
# use struson::reader::simple::*;
// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json_reader = SimpleJsonReader::new(r#"["a", "short", "example"]"#.as_bytes());
let mut words = Vec::<String>::new();
json_reader.next_array_items(|item_reader| {
let word = item_reader.next_string()?;
words.push(word);
Ok(())
})?;
assert_eq!(words, vec!["a", "short", "example"]);
# Ok::<(), Box<dyn std::error::Error>>(())
```

#### Writing

See [`SimpleJsonWriter`](https://docs.rs/struson/latest/struson/writer/simple/struct.SimpleJsonWriter.html).

```rust
# use struson::writer::simple::*;
// In this example JSON bytes are stored in a Vec;
// normally they would be written to a file or network connection
let mut writer = Vec::<u8>::new();
let json_writer = SimpleJsonWriter::new(&mut writer);
json_writer.object_value(|object_writer| {
object_writer.number_member("a", 1)?;
object_writer.bool_member("b", true)?;
Ok(())
})?;

let json = String::from_utf8(writer)?;
assert_eq!(json, r#"{"a":1,"b":true}"#);
# Ok::<(), Box<dyn std::error::Error>>(())
```

### Advanced API

#### Reading

See [`JsonStreamReader`](https://docs.rs/struson/latest/struson/reader/struct.JsonStreamReader.html).

```rust
use struson::reader::*;
Expand All @@ -60,7 +116,9 @@ json_reader.end_object()?;
json_reader.consume_trailing_whitespace()?;
```

### Writing
#### Writing

See [`JsonStreamWriter`](https://docs.rs/struson/latest/struson/writer/struct.JsonStreamWriter.html).

```rust
use struson::writer::*;
Expand Down
64 changes: 62 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,65 @@
//!
//! # Usage examples
//!
//! ## Reading
//! Two variants of the API are provided:
//! - simple: ensures correct API usage at compile-time
//! - advanced: ensures correct API usage only at runtime (by panicking); more flexible and
//! provides more functionality
//!
//! ## Simple API
//!
//! **🔬 Experimental**\
//! The simple API and its naming is currently experimental, please provide feedback [here](https://github.com/Marcono1234/struson/issues/34).
//! Any feedback is appreciated!
//!
//! ### Reading
//! See [`SimpleJsonReader`](crate::reader::simple::SimpleJsonReader).
//!
//! ```
//! # #[cfg(feature = "experimental")]
//! # {
//! # use struson::reader::simple::*;
//! // In this example JSON data comes from a string;
//! // normally it would come from a file or a network connection
//! let json_reader = SimpleJsonReader::new(r#"["a", "short", "example"]"#.as_bytes());
//! let mut words = Vec::<String>::new();
//! json_reader.next_array_items(|item_reader| {
//! let word = item_reader.next_string()?;
//! words.push(word);
//! Ok(())
//! })?;
//! assert_eq!(words, vec!["a", "short", "example"]);
//! # }
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! ### Writing
//! See [`SimpleJsonWriter`](crate::writer::simple::SimpleJsonWriter).
//!
//! ```
//! # #[cfg(feature = "experimental")]
//! # {
//! # use struson::writer::simple::*;
//! // In this example JSON bytes are stored in a Vec;
//! // normally they would be written to a file or network connection
//! let mut writer = Vec::<u8>::new();
//! let json_writer = SimpleJsonWriter::new(&mut writer);
//! json_writer.object_value(|object_writer| {
//! object_writer.number_member("a", 1)?;
//! object_writer.bool_member("b", true)?;
//! Ok(())
//! })?;
//!
//! let json = String::from_utf8(writer)?;
//! assert_eq!(json, r#"{"a":1,"b":true}"#);
//! # }
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! ## Advanced API
//!
//! ### Reading
//! See [`JsonStreamReader`](crate::reader::JsonStreamReader).
//!
//! ```
//! # use struson::reader::*;
Expand All @@ -59,7 +117,9 @@
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! ## Writing
//! ### Writing
//! See [`JsonStreamWriter`](crate::writer::JsonStreamWriter).
//!
//! ```
//! # use struson::writer::*;
//! // In this example JSON bytes are stored in a Vec;
Expand Down
2 changes: 2 additions & 0 deletions src/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ use crate::writer::JsonWriter;
mod stream_reader;
// Re-export streaming implementation under `reader` module
pub use stream_reader::*;
#[cfg(feature = "experimental")]
pub mod simple;

type IoError = std::io::Error;

Expand Down
Loading

0 comments on commit b99723e

Please sign in to comment.