pub fn extract_string_field(json: &str, field: &str) -> Option<String> {
let search = format!("\"{field}\":");
let idx = json.find(&search)?;
let remainder = json[idx + search.len()..].trim_start();
let stripped = remainder.strip_prefix('"')?;
let end = stripped.find('"')?;
Some(stripped[..end].to_string())
}
pub fn extract_f64_field(json: &str, field: &str) -> Option<f64> {
let search = format!("\"{field}\":");
let idx = json.find(&search)?;
let remainder = json[idx + search.len()..].trim_start();
let end = remainder
.find(|c: char| !c.is_ascii_digit() && c != '.' && c != '-')
.unwrap_or(remainder.len());
remainder[..end].parse().ok()
}
pub fn extract_u64_field(json: &str, field: &str) -> Option<u64> {
let v = extract_f64_field(json, field)?;
if v.is_finite() && v >= 0.0 {
Some(v as u64)
} else {
None
}
}
pub fn object_slice<'a>(json: &'a str, key: &str) -> Option<&'a str> {
let search = format!("\"{key}\":");
let idx = json.find(&search)?;
let after = &json[idx + search.len()..];
let start = idx + search.len() + (after.len() - after.trim_start().len());
if !json[start..].starts_with('{') {
return None;
}
let mut depth = 0usize;
let mut in_str = false;
let mut escaped = false;
for (i, &b) in json.as_bytes()[start..].iter().enumerate() {
if in_str {
if escaped {
escaped = false;
} else if b == b'\\' {
escaped = true;
} else if b == b'"' {
in_str = false;
}
continue;
}
match b {
b'"' => in_str = true,
b'{' => depth += 1,
b'}' => {
depth -= 1;
if depth == 0 {
return Some(&json[start..start + i + 1]);
}
}
_ => {}
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE: &str = r#"{
"cwd": "/Users/ash/repos/grav-bar",
"model": {"id": "claude-fable-5-1", "display_name": "Fable 5.1 (1M context)"},
"context_window": {"used_percentage": 4.5, "note": "has } brace and \" quote"},
"rate_limits": {
"five_hour": {"used_percentage": 37.2, "resets_at": 1757000000},
"seven_day": {"used_percentage": 62.9, "resets_at": 1757200000.7}
},
"nothing": null
}"#;
#[test]
fn string_and_number_fields() {
assert_eq!(
extract_string_field(SAMPLE, "cwd").as_deref(),
Some("/Users/ash/repos/grav-bar")
);
assert_eq!(
extract_string_field(SAMPLE, "display_name").as_deref(),
Some("Fable 5.1 (1M context)")
);
assert_eq!(extract_f64_field(SAMPLE, "nothing"), None);
assert_eq!(extract_string_field(SAMPLE, "missing"), None);
assert_eq!(extract_u64_field(SAMPLE, "resets_at"), Some(1757000000));
}
#[test]
fn object_slice_scopes_duplicate_keys() {
let ctx = object_slice(SAMPLE, "context_window").unwrap();
assert!(ctx.starts_with('{') && ctx.ends_with('}'));
assert_eq!(extract_f64_field(ctx, "used_percentage"), Some(4.5));
let limits = object_slice(SAMPLE, "rate_limits").unwrap();
let week = object_slice(limits, "seven_day").unwrap();
assert_eq!(extract_f64_field(week, "used_percentage"), Some(62.9));
assert_eq!(extract_u64_field(week, "resets_at"), Some(1757200000));
}
#[test]
fn object_slice_rejects_non_objects() {
assert_eq!(object_slice(SAMPLE, "cwd"), None);
assert_eq!(object_slice(SAMPLE, "nothing"), None);
assert_eq!(object_slice("{\"a\": {", "a"), None);
}
}