Skip to main content

liver_shot/
lib.rs

1//! A lightweight, `no_std` JSON value position extractor.
2//!
3//! Returns a [`Span`] (start/end byte offsets) rather than a parsed value.
4//!
5//! ## Limitations
6//!
7//! - Object navigation only - arrays at the top level or as a path step return [`Error::is_unsupported_array`].
8//! - Values are not validated — only their position is extracted.
9//!
10//! ## Examples
11//!
12//! ### Extract an object
13//!
14//! ```
15//! let json = r#"{"a": {"b": "value", "c": [1, 2, 3]}}"#;
16//!
17//! let span = liver_shot::find("a", json)?;
18//! assert_eq!(r#"{"b": "value", "c": [1, 2, 3]}"#, span.get(json));
19//! # Ok::<(), liver_shot::Error>(())
20//! ```
21//!
22//! ### Extract a nested object
23//!
24//! ```
25//! let json = r#"{"a": {"b": {"c": "value"}}}"#;
26//!
27//! let span = liver_shot::find("a.b", json)?;
28//! assert_eq!(r#"{"c": "value"}"#, span.get(json));
29//! # Ok::<(), liver_shot::Error>(())
30//! ```
31//!
32//! ### Extract an array
33//!
34//! ```
35//! let json = r#"{"a": {"b": "value", "c": [1, 2, 3]}}"#;
36//!
37//! let span = liver_shot::find("a.c", json)?;
38//! assert_eq!("[1, 2, 3]", span.get(json));
39//! # Ok::<(), liver_shot::Error>(())
40//! ```
41//!
42//! ### Reuse [`Span`]
43//!
44//! ```
45//! let json = r#"{"a": {"b": "value", "c": [1, 2, 3]}}"#;
46//!
47//! let a = liver_shot::find("a", json)?;
48//! let b = a.find("b", json)?;
49//! let c = a.find("c", json)?;
50//!
51//! assert_eq!(r#"{"b": "value", "c": [1, 2, 3]}"#, a.get(json));
52//! assert_eq!(r#""value""#, b.get(json));
53//! assert_eq!("[1, 2, 3]", c.get(json));
54//! # Ok::<(), liver_shot::Error>(())
55//! ```
56
57#![no_std]
58
59mod error;
60mod parser;
61mod scanner;
62mod span;
63
64pub use error::Error;
65pub use span::Span;
66
67pub fn find(pattern: &str, data: &str) -> Result<Span, Error> {
68    let bytes = data.as_bytes();
69    let start = crate::scanner::skip_whitespace(bytes)?;
70    let bytes = &bytes[start..];
71
72    match bytes.first() {
73        Some(b'{') => crate::parser::find_path(bytes, pattern)
74            .map(|s| Span::new(start + s.start, start + s.end)),
75        Some(b'[') => Err(Error::unsupported_array()),
76        _ => Err(Error::invalid_json()),
77    }
78}