#![allow(dead_code)]
pub mod parking_lot {
use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicUsize, Ordering};
const WRITER: usize = 1 << (usize::BITS - 1);
pub struct RawRwLock;
pub struct RwLock<T: ?Sized> {
state: AtomicUsize,
data: UnsafeCell<T>,
}
unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
fn backoff(spins: &mut u32) {
if *spins < 64 {
std::hint::spin_loop();
*spins += 1;
} else {
std::thread::yield_now();
}
}
impl<T> RwLock<T> {
pub const fn new(value: T) -> Self {
RwLock { state: AtomicUsize::new(0), data: UnsafeCell::new(value) }
}
pub fn into_inner(self) -> T {
self.data.into_inner()
}
}
impl<T: ?Sized> RwLock<T> {
pub fn read_recursive(&self) -> lock_api::RwLockReadGuard<'_, RawRwLock, T> {
let mut spins = 0;
loop {
let s = self.state.load(Ordering::Relaxed);
if s & WRITER == 0 && self.state.compare_exchange_weak(s, s + 1, Ordering::Acquire, Ordering::Relaxed).is_ok() {
return lock_api::RwLockReadGuard { lock: self, _raw: PhantomData };
}
backoff(&mut spins);
}
}
pub fn read(&self) -> lock_api::RwLockReadGuard<'_, RawRwLock, T> {
self.read_recursive()
}
pub fn write(&self) -> lock_api::RwLockWriteGuard<'_, RawRwLock, T> {
let mut spins = 0;
loop {
if self.state.compare_exchange_weak(0, WRITER, Ordering::Acquire, Ordering::Relaxed).is_ok() {
return lock_api::RwLockWriteGuard { lock: self, _raw: PhantomData };
}
backoff(&mut spins);
}
}
pub fn get_mut(&mut self) -> &mut T {
self.data.get_mut()
}
}
impl<T: ?Sized + std::fmt::Debug> std::fmt::Debug for RwLock<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RwLock").field("data", &&*self.read_recursive()).finish()
}
}
pub mod lock_api {
use super::{RwLock, WRITER};
use std::marker::PhantomData;
use std::sync::atomic::Ordering;
pub struct RwLockReadGuard<'a, R, T: ?Sized> {
pub(super) lock: &'a RwLock<T>,
pub(super) _raw: PhantomData<R>,
}
pub struct RwLockWriteGuard<'a, R, T: ?Sized> {
pub(super) lock: &'a RwLock<T>,
pub(super) _raw: PhantomData<R>,
}
impl<R, T: ?Sized> std::ops::Deref for RwLockReadGuard<'_, R, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.lock.data.get() }
}
}
impl<R, T: ?Sized> Drop for RwLockReadGuard<'_, R, T> {
fn drop(&mut self) {
self.lock.state.fetch_sub(1, Ordering::Release);
}
}
impl<R, T: ?Sized> std::ops::Deref for RwLockWriteGuard<'_, R, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.lock.data.get() }
}
}
impl<R, T: ?Sized> std::ops::DerefMut for RwLockWriteGuard<'_, R, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.lock.data.get() }
}
}
impl<R, T: ?Sized> Drop for RwLockWriteGuard<'_, R, T> {
fn drop(&mut self) {
debug_assert_eq!(self.lock.state.load(Ordering::Relaxed), WRITER);
self.lock.state.store(0, Ordering::Release);
}
}
impl<R, T: ?Sized + std::fmt::Debug> std::fmt::Debug for RwLockReadGuard<'_, R, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(**self).fmt(f)
}
}
impl<R, T: ?Sized + std::fmt::Debug> std::fmt::Debug for RwLockWriteGuard<'_, R, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(**self).fmt(f)
}
}
}
}
pub mod rand_xoshiro {
pub mod rand_core {
pub trait RngCore {
fn next_u32(&mut self) -> u32;
fn next_u64(&mut self) -> u64;
}
pub trait SeedableRng: Sized {
fn seed_from_u64(seed: u64) -> Self;
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Xoshiro256StarStar {
s: [u64; 4],
}
fn splitmix64(x: &mut u64) -> u64 {
*x = x.wrapping_add(0x9e37_79b9_7f4a_7c15);
let mut z = *x;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
impl rand_core::SeedableRng for Xoshiro256StarStar {
fn seed_from_u64(seed: u64) -> Self {
let mut x = seed;
let s = [splitmix64(&mut x), splitmix64(&mut x), splitmix64(&mut x), splitmix64(&mut x)];
if s == [0; 4] {
return Self::seed_from_u64(0);
}
Xoshiro256StarStar { s }
}
}
impl rand_core::RngCore for Xoshiro256StarStar {
fn next_u32(&mut self) -> u32 {
(self.next_u64() >> 32) as u32
}
fn next_u64(&mut self) -> u64 {
let s = &mut self.s;
let result = s[1].wrapping_mul(5).rotate_left(7).wrapping_mul(9);
let t = s[1] << 17;
s[2] ^= s[0];
s[3] ^= s[1];
s[1] ^= s[2];
s[0] ^= s[3];
s[2] ^= t;
s[3] = s[3].rotate_left(45);
result
}
}
}
pub mod rayon {
use std::cell::{Cell, RefCell};
use std::collections::VecDeque;
use std::sync::Mutex;
thread_local! {
static THREAD_INDEX: Cell<Option<usize>> = const { Cell::new(None) };
}
pub fn current_thread_index() -> Option<usize> {
THREAD_INDEX.with(|i| i.get())
}
pub fn join<A, B, RA, RB>(a: A, b: B) -> (RA, RB)
where
A: FnOnce() -> RA + Send,
B: FnOnce() -> RB + Send,
RA: Send,
RB: Send,
{
let ra = a();
(ra, b())
}
pub struct Scope<'scope> {
_marker: std::marker::PhantomData<&'scope ()>,
}
impl<'scope> Scope<'scope> {
pub fn spawn<F: FnOnce(&Scope<'scope>) + Send + 'scope>(&self, f: F) {
f(self)
}
}
pub fn scope<'scope, OP, R>(op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R,
{
op(&Scope { _marker: std::marker::PhantomData })
}
type Task<'scope> = Box<dyn FnOnce(&ScopeFifo<'scope>) + Send + 'scope>;
pub struct ScopeFifo<'scope> {
tasks: RefCell<Vec<Task<'scope>>>,
}
impl<'scope> ScopeFifo<'scope> {
pub fn spawn_fifo<F: FnOnce(&ScopeFifo<'scope>) + Send + 'scope>(&self, f: F) {
self.tasks.borrow_mut().push(Box::new(f));
}
}
#[derive(Debug)]
pub struct ThreadPool {
threads: usize,
}
impl ThreadPool {
pub fn current_num_threads(&self) -> usize {
self.threads
}
pub fn scope<'scope, OP, R>(&self, op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R,
{
op(&Scope { _marker: std::marker::PhantomData })
}
pub fn install<OP: FnOnce() -> R, R>(&self, op: OP) -> R {
op()
}
pub fn scope_fifo<'scope, OP, R>(&self, op: OP) -> R
where
OP: FnOnce(&ScopeFifo<'scope>) -> R,
{
let scope = ScopeFifo { tasks: RefCell::new(Vec::new()) };
let out = op(&scope);
let tasks = scope.tasks.into_inner();
if tasks.is_empty() {
return out;
}
let workers = self.threads.max(1).min(tasks.len());
let queue: Mutex<VecDeque<Task<'scope>>> = Mutex::new(tasks.into());
std::thread::scope(|s| {
for index in 0..workers {
let queue = &queue;
s.spawn(move || {
THREAD_INDEX.with(|i| i.set(Some(index)));
loop {
let task = queue.lock().unwrap().pop_front();
match task {
Some(task) => {
let inner = ScopeFifo { tasks: RefCell::new(Vec::new()) };
task(&inner);
assert!(inner.tasks.into_inner().is_empty(), "a fusion task spawns no tasks");
}
None => break,
}
}
});
}
});
out
}
}
#[derive(Default)]
pub struct ThreadPoolBuilder {
threads: usize,
}
impl ThreadPoolBuilder {
pub fn new() -> Self {
ThreadPoolBuilder { threads: 0 }
}
pub fn num_threads(mut self, threads: usize) -> Self {
self.threads = threads;
self
}
pub fn start_handler<H: Fn(usize) + Send + Sync + 'static>(self, _handler: H) -> Self {
self
}
pub fn build(self) -> Result<ThreadPool, String> {
let threads = if self.threads == 0 { std::thread::available_parallelism().map_or(1, |n| n.get()) } else { self.threads };
Ok(ThreadPool { threads })
}
}
pub mod prelude {
pub trait IntoParallelRefIterator<'a> {
type Iter: Iterator;
fn par_iter(&'a self) -> Self::Iter;
}
impl<'a, T: 'a> IntoParallelRefIterator<'a> for [T] {
type Iter = std::slice::Iter<'a, T>;
fn par_iter(&'a self) -> Self::Iter {
self.iter()
}
}
impl<'a, T: 'a> IntoParallelRefIterator<'a> for Vec<T> {
type Iter = std::slice::Iter<'a, T>;
fn par_iter(&'a self) -> Self::Iter {
self.iter()
}
}
pub trait IntoParallelIterator {
type Iter: Iterator;
fn into_par_iter(self) -> Self::Iter;
}
impl<I: IntoIterator> IntoParallelIterator for I {
type Iter = I::IntoIter;
fn into_par_iter(self) -> Self::Iter {
self.into_iter()
}
}
pub trait CollectIntoVec<T> {
fn collect_into_vec(self, target: &mut Vec<T>);
}
impl<T, I: Iterator<Item = T>> CollectIntoVec<T> for I {
fn collect_into_vec(self, target: &mut Vec<T>) {
target.clear();
target.extend(self);
}
}
pub trait ParallelExtend<T> {
fn par_extend<I: IntoIterator<Item = T>>(&mut self, iter: I);
}
impl<T> ParallelExtend<T> for Vec<T> {
fn par_extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.extend(iter)
}
}
}
}
pub mod weak_table {
use std::collections::HashMap;
use std::ops::Deref;
pub mod traits {
pub trait WeakElement {
type Strong;
fn new(view: &Self::Strong) -> Self;
fn view(&self) -> Option<Self::Strong>;
fn clone(view: &Self::Strong) -> Self::Strong;
}
}
use traits::WeakElement;
fn address<S: Deref>(strong: &S) -> usize {
(&**strong) as *const S::Target as *const u8 as usize
}
fn alive<W: WeakElement>(weak: &W, strong: &W::Strong) -> bool
where
W::Strong: Deref,
{
weak.view().is_some_and(|v| address(&v) == address(strong))
}
pub struct PtrWeakHashSet<W: WeakElement>(HashMap<usize, W>);
impl<W: WeakElement> Default for PtrWeakHashSet<W> {
fn default() -> Self {
PtrWeakHashSet(HashMap::new())
}
}
impl<W: WeakElement> std::fmt::Debug for PtrWeakHashSet<W> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "PtrWeakHashSet({} entries)", self.0.len())
}
}
impl<W: WeakElement> PtrWeakHashSet<W>
where
W::Strong: Deref,
{
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, strong: W::Strong) -> bool {
let key = address(&strong);
let fresh = !self.0.get(&key).is_some_and(|w| alive(w, &strong));
self.0.insert(key, W::new(&strong));
fresh
}
pub fn contains(&self, strong: &W::Strong) -> bool {
self.0.get(&address(strong)).is_some_and(|w| alive(w, strong))
}
pub fn remove(&mut self, strong: &W::Strong) -> bool {
let key = address(strong);
let present = self.contains(strong);
self.0.remove(&key);
present
}
pub fn clear(&mut self) {
self.0.clear()
}
}
pub struct PtrWeakKeyHashMap<W: WeakElement, V>(HashMap<usize, (W, V)>);
impl<W: WeakElement, V> Default for PtrWeakKeyHashMap<W, V> {
fn default() -> Self {
PtrWeakKeyHashMap(HashMap::new())
}
}
impl<W: WeakElement, V> std::fmt::Debug for PtrWeakKeyHashMap<W, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "PtrWeakKeyHashMap({} entries)", self.0.len())
}
}
impl<W: WeakElement, V> PtrWeakKeyHashMap<W, V>
where
W::Strong: Deref,
{
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, key: W::Strong, value: V) -> Option<V> {
let k = address(&key);
let old = self.0.remove(&k).and_then(|(w, v)| alive(&w, &key).then_some(v));
self.0.insert(k, (W::new(&key), value));
old
}
pub fn get(&self, key: &W::Strong) -> Option<&V> {
self.0.get(&address(key)).and_then(|(w, v)| alive(w, key).then_some(v))
}
pub fn contains_key(&self, key: &W::Strong) -> bool {
self.get(key).is_some()
}
pub fn remove(&mut self, key: &W::Strong) -> Option<V> {
let k = address(key);
match self.0.get(&k) {
Some((w, _)) if alive(w, key) => self.0.remove(&k).map(|(_, v)| v),
_ => None,
}
}
pub fn clear(&mut self) {
self.0.clear()
}
}
}
pub mod priority_queue {
use std::collections::HashMap;
use std::hash::Hash;
pub struct PriorityQueue<I, P> {
items: Vec<(I, P)>,
index: HashMap<I, usize>,
}
impl<I: Clone, P: Clone> Clone for PriorityQueue<I, P> {
fn clone(&self) -> Self {
PriorityQueue { items: self.items.clone(), index: self.index.clone() }
}
}
impl<I: std::fmt::Debug, P: std::fmt::Debug> std::fmt::Debug for PriorityQueue<I, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.items.iter()).finish()
}
}
impl<I: Hash + Eq + Clone, P: Ord> Default for PriorityQueue<I, P> {
fn default() -> Self {
PriorityQueue { items: Vec::new(), index: HashMap::new() }
}
}
impl<I: Hash + Eq + Clone, P: Ord> PriorityQueue<I, P> {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn clear(&mut self) {
self.items.clear();
self.index.clear();
}
fn swap(&mut self, a: usize, b: usize) {
self.items.swap(a, b);
self.index.insert(self.items[a].0.clone(), a);
self.index.insert(self.items[b].0.clone(), b);
}
fn up(&mut self, mut k: usize) {
while k > 0 {
let parent = (k - 1) / 2;
if self.items[k].1 > self.items[parent].1 {
self.swap(k, parent);
k = parent;
} else {
break;
}
}
}
fn down(&mut self, mut k: usize) {
loop {
let (l, r) = (2 * k + 1, 2 * k + 2);
let mut top = k;
if l < self.items.len() && self.items[l].1 > self.items[top].1 {
top = l;
}
if r < self.items.len() && self.items[r].1 > self.items[top].1 {
top = r;
}
if top == k {
break;
}
self.swap(k, top);
k = top;
}
}
pub fn push(&mut self, item: I, priority: P) -> Option<P> {
if let Some(&k) = self.index.get(&item) {
let old = std::mem::replace(&mut self.items[k].1, priority);
self.up(k);
let k = self.index[&item];
self.down(k);
return Some(old);
}
self.items.push((item.clone(), priority));
let k = self.items.len() - 1;
self.index.insert(item, k);
self.up(k);
None
}
pub fn change_priority(&mut self, item: &I, priority: P) -> Option<P> {
if self.index.contains_key(item) {
self.push(item.clone(), priority)
} else {
None
}
}
pub fn get_priority(&self, item: &I) -> Option<&P> {
self.index.get(item).map(|&k| &self.items[k].1)
}
pub fn peek(&self) -> Option<(&I, &P)> {
self.items.first().map(|(i, p)| (i, p))
}
pub fn pop(&mut self) -> Option<(I, P)> {
if self.items.is_empty() {
return None;
}
let last = self.items.len() - 1;
self.swap(0, last);
let (item, priority) = self.items.pop().expect("nonempty");
self.index.remove(&item);
if !self.items.is_empty() {
self.down(0);
}
Some((item, priority))
}
}
}
pub mod serde_json {
use std::collections::BTreeMap;
use std::fmt::Write as _;
#[derive(Clone, Debug, PartialEq)]
pub enum Number {
PosInt(u64),
NegInt(i64),
Float(f64),
}
impl Number {
pub fn is_i64(&self) -> bool {
self.as_i64().is_some()
}
pub fn is_u64(&self) -> bool {
matches!(self, Number::PosInt(_))
}
pub fn is_f64(&self) -> bool {
matches!(self, Number::Float(_))
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Number::PosInt(u) => i64::try_from(*u).ok(),
Number::NegInt(i) => Some(*i),
Number::Float(_) => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match self {
Number::PosInt(u) => Some(*u),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
Some(match self {
Number::PosInt(u) => *u as f64,
Number::NegInt(i) => *i as f64,
Number::Float(x) => *x,
})
}
}
#[derive(Clone, Debug, PartialEq, Default)]
pub enum Value {
#[default]
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
pub type Map<K, V> = BTreeMap<K, V>;
pub type Error = String;
impl Value {
pub fn as_object(&self) -> Option<&Map<String, Value>> {
match self {
Value::Object(m) => Some(m),
_ => None,
}
}
pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>> {
match self {
Value::Object(m) => Some(m),
_ => None,
}
}
pub fn as_array(&self) -> Option<&Vec<Value>> {
match self {
Value::Array(a) => Some(a),
_ => None,
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
match self {
Value::Array(a) => Some(a),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Value::Bool(b) => Some(*b),
_ => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match self {
Value::Number(Number::PosInt(u)) => Some(*u),
_ => None,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Number(Number::PosInt(u)) => i64::try_from(*u).ok(),
Value::Number(Number::NegInt(i)) => Some(*i),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Value::Number(Number::PosInt(u)) => Some(*u as f64),
Value::Number(Number::NegInt(i)) => Some(*i as f64),
Value::Number(Number::Float(f)) => Some(*f),
_ => None,
}
}
pub fn is_null(&self) -> bool {
matches!(self, Value::Null)
}
pub fn get(&self, key: &str) -> Option<&Value> {
self.as_object().and_then(|m| m.get(key))
}
}
impl std::ops::Index<&str> for Value {
type Output = Value;
fn index(&self, key: &str) -> &Value {
static NULL: Value = Value::Null;
self.get(key).unwrap_or(&NULL)
}
}
impl std::ops::IndexMut<&str> for Value {
fn index_mut(&mut self, key: &str) -> &mut Value {
if self.is_null() {
*self = Value::Object(Map::new());
}
match self {
Value::Object(m) => m.entry(key.to_string()).or_insert(Value::Null),
_ => panic!("cannot index a non-object JSON value with \"{key}\""),
}
}
}
impl std::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out = String::new();
write_value(self, &mut out);
f.write_str(&out)
}
}
fn write_string(s: &str, out: &mut String) {
out.push('"');
for c in s.chars() {
match c {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
'\u{8}' => out.push_str("\\b"),
'\u{c}' => out.push_str("\\f"),
c if (c as u32) < 0x20 => {
let _ = write!(out, "\\u{:04x}", c as u32);
}
c => out.push(c),
}
}
out.push('"');
}
fn write_value(v: &Value, out: &mut String) {
match v {
Value::Null => out.push_str("null"),
Value::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
Value::Number(Number::PosInt(u)) => {
let _ = write!(out, "{u}");
}
Value::Number(Number::NegInt(i)) => {
let _ = write!(out, "{i}");
}
Value::Number(Number::Float(x)) => {
if x.is_finite() {
let _ = write!(out, "{x:?}");
} else {
out.push_str("null");
}
}
Value::String(s) => write_string(s, out),
Value::Array(a) => {
out.push('[');
for (k, x) in a.iter().enumerate() {
if k > 0 {
out.push(',');
}
write_value(x, out);
}
out.push(']');
}
Value::Object(m) => {
out.push('{');
for (k, (key, x)) in m.iter().enumerate() {
if k > 0 {
out.push(',');
}
write_string(key, out);
out.push(':');
write_value(x, out);
}
out.push('}');
}
}
}
pub trait ToJson {
fn to_json(&self) -> Value;
fn write_text(&self, out: &mut String) {
let _ = write!(out, "{}", self.to_json());
}
}
fn write_seq<'a, T: ToJson + 'a>(items: impl Iterator<Item = &'a T>, out: &mut String) {
out.push('[');
for (k, item) in items.enumerate() {
if k > 0 {
out.push(',');
}
item.write_text(out);
}
out.push(']');
}
pub fn write_fields(fields: &[(&str, &dyn ToJson)], out: &mut String) {
out.push('{');
for (k, (name, value)) in fields.iter().enumerate() {
if k > 0 {
out.push(',');
}
let _ = write!(out, "\"{name}\":");
value.write_text(out);
}
out.push('}');
}
pub trait FromJson: Sized {
fn from_json(value: &Value) -> Result<Self, Error>;
}
pub fn to_value<T: ToJson + ?Sized>(value: &T) -> Result<Value, Error> {
Ok(value.to_json())
}
pub fn from_value<T: FromJson>(value: Value) -> Result<T, Error> {
T::from_json(&value)
}
pub fn to_string<T: ToJson + ?Sized>(value: &T) -> Result<String, Error> {
let mut out = String::new();
value.write_text(&mut out);
Ok(out)
}
pub fn to_writer<W: std::io::Write, T: ToJson + ?Sized>(mut writer: W, value: &T) -> Result<(), Error> {
writer.write_all(to_string(value)?.as_bytes()).map_err(|e| e.to_string())
}
pub fn from_str<T: FromJson>(text: &str) -> Result<T, Error> {
T::from_json(&parse(text)?)
}
pub fn parse(text: &str) -> Result<Value, Error> {
let mut p = Parser { s: text.as_bytes(), k: 0, depth: 128 };
let v = p.value()?;
match p.ws() {
Some(_) => Err(p.peek_error("trailing characters")),
None => Ok(v),
}
}
struct Parser<'a> {
s: &'a [u8],
k: usize,
depth: usize,
}
impl Parser<'_> {
fn error_at(&self, i: usize, msg: &str) -> Error {
let start = self.s[..i].iter().rposition(|&c| c == b'\n').map_or(0, |p| p + 1);
let line = 1 + self.s[..start].iter().filter(|&&c| c == b'\n').count();
format!("{msg} at line {line} column {}", i - start)
}
fn error(&self, msg: &str) -> Error {
self.error_at(self.k, msg)
}
fn peek_error(&self, msg: &str) -> Error {
self.error_at((self.k + 1).min(self.s.len()), msg)
}
fn peek(&self) -> Option<u8> {
self.s.get(self.k).copied()
}
fn ws(&mut self) -> Option<u8> {
while let Some(b' ' | b'\n' | b'\r' | b'\t') = self.peek() {
self.k += 1;
}
self.peek()
}
fn next(&mut self) -> Option<u8> {
let c = self.peek();
if c.is_some() {
self.k += 1;
}
c
}
fn ident(&mut self, rest: &[u8], v: Value) -> Result<Value, Error> {
self.k += 1;
for &expected in rest {
match self.next() {
None => return Err(self.error("EOF while parsing a value")),
Some(c) if c != expected => return Err(self.error("expected ident")),
_ => {}
}
}
Ok(v)
}
fn value(&mut self) -> Result<Value, Error> {
let Some(c) = self.ws() else {
return Err(self.peek_error("EOF while parsing a value"));
};
match c {
b'n' => self.ident(b"ull", Value::Null),
b't' => self.ident(b"rue", Value::Bool(true)),
b'f' => self.ident(b"alse", Value::Bool(false)),
b'-' => {
self.k += 1;
self.number(false)
}
b'0'..=b'9' => self.number(true),
b'"' => {
self.k += 1;
Ok(Value::String(self.string()?))
}
b'[' | b'{' => {
self.depth -= 1;
if self.depth == 0 {
return Err(self.peek_error("recursion limit exceeded"));
}
self.k += 1;
let v = if c == b'[' { self.array()? } else { self.object()? };
self.depth += 1;
Ok(v)
}
_ => Err(self.peek_error("expected value")),
}
}
fn array(&mut self) -> Result<Value, Error> {
let mut a = Vec::new();
loop {
let Some(c) = self.ws() else {
return Err(self.peek_error("EOF while parsing a list"));
};
if c == b']' {
self.k += 1;
return Ok(Value::Array(a));
}
if !a.is_empty() {
if c != b',' {
return Err(self.peek_error("expected `,` or `]`"));
}
self.k += 1;
match self.ws() {
Some(b']') => return Err(self.peek_error("trailing comma")),
None => return Err(self.peek_error("EOF while parsing a value")),
_ => {}
}
}
a.push(self.value()?);
}
}
fn object(&mut self) -> Result<Value, Error> {
let mut m = Map::new();
loop {
let c = match self.ws() {
Some(b'}') => {
self.k += 1;
return Ok(Value::Object(m));
}
Some(b',') if !m.is_empty() => {
self.k += 1;
self.ws()
}
Some(c) if m.is_empty() => Some(c),
Some(_) => return Err(self.peek_error("expected `,` or `}`")),
None => return Err(self.peek_error("EOF while parsing an object")),
};
match c {
Some(b'"') => self.k += 1,
Some(b'}') => return Err(self.peek_error("trailing comma")),
Some(_) => return Err(self.peek_error("key must be a string")),
None => return Err(self.peek_error("EOF while parsing a value")),
}
let key = self.string()?;
match self.ws() {
Some(b':') => self.k += 1,
Some(_) => return Err(self.peek_error("expected `:`")),
None => return Err(self.peek_error("EOF while parsing an object")),
}
let v = self.value()?;
m.insert(key, v);
}
}
fn hex4(&mut self) -> Result<u16, Error> {
if self.k + 4 > self.s.len() {
self.k = self.s.len();
return Err(self.error("EOF while parsing a string"));
}
let digits = &self.s[self.k..self.k + 4];
self.k += 4;
let mut n = 0u16;
for &d in digits {
let v = match d {
b'0'..=b'9' => d - b'0',
b'a'..=b'f' => d - b'a' + 10,
b'A'..=b'F' => d - b'A' + 10,
_ => return Err(self.error("invalid escape")),
};
n = n * 16 + v as u16;
}
Ok(n)
}
fn string(&mut self) -> Result<String, Error> {
let mut out = Vec::new();
loop {
let Some(c) = self.peek() else {
return Err(self.error("EOF while parsing a string"));
};
self.k += 1;
match c {
b'"' => return Ok(String::from_utf8(out).expect("JSON text is UTF-8")),
b'\\' => {
let Some(e) = self.next() else {
return Err(self.error("EOF while parsing a string"));
};
match e {
b'"' => out.push(b'"'),
b'\\' => out.push(b'\\'),
b'/' => out.push(b'/'),
b'b' => out.push(8),
b'f' => out.push(12),
b'n' => out.push(b'\n'),
b'r' => out.push(b'\r'),
b't' => out.push(b'\t'),
b'u' => {
let ch = match self.hex4()? {
0xDC00..=0xDFFF => return Err(self.error("lone leading surrogate in hex escape")),
n1 @ 0xD800..=0xDBFF => {
for expected in [b'\\', b'u'] {
match self.peek() {
None => return Err(self.error("EOF while parsing a string")),
Some(c) => {
self.k += 1;
if c != expected {
return Err(self.error("unexpected end of hex escape"));
}
}
}
}
let n2 = self.hex4()?;
if !(0xDC00..=0xDFFF).contains(&n2) {
return Err(self.error("lone leading surrogate in hex escape"));
}
char::from_u32((((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000).unwrap()
}
n => char::from_u32(n as u32).unwrap(),
};
out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes());
}
_ => return Err(self.error("invalid escape")),
}
}
0..=0x1F => return Err(self.error("control character (\\u0000-\\u001F) found while parsing a string")),
_ => out.push(c),
}
}
}
fn digits(&mut self, buf: &mut String) {
while let Some(c @ b'0'..=b'9') = self.peek() {
self.k += 1;
buf.push(c as char);
}
}
fn number(&mut self, positive: bool) -> Result<Value, Error> {
let mut buf = String::from(if positive { "" } else { "-" });
match self.next() {
None => return Err(self.error("EOF while parsing a value")),
Some(b'0') => {
buf.push('0');
if let Some(b'0'..=b'9') = self.peek() {
return Err(self.peek_error("invalid number"));
}
}
Some(c @ b'1'..=b'9') => {
buf.push(c as char);
self.digits(&mut buf);
}
Some(_) => return Err(self.error("invalid number")),
}
if self.peek() == Some(b'.') {
self.k += 1;
buf.push('.');
let before = buf.len();
self.digits(&mut buf);
if buf.len() == before {
return Err(self.peek_error(if self.peek().is_some() { "invalid number" } else { "EOF while parsing a value" }));
}
}
if let Some(e @ (b'e' | b'E')) = self.peek() {
self.k += 1;
buf.push(e as char);
if let Some(s @ (b'+' | b'-')) = self.peek() {
self.k += 1;
buf.push(s as char);
}
match self.next() {
Some(c @ b'0'..=b'9') => buf.push(c as char),
None => return Err(self.error("EOF while parsing a value")),
Some(_) => return Err(self.error("invalid number")),
}
self.digits(&mut buf);
}
if let Ok(u) = buf.parse::<u64>() {
return Ok(Value::Number(Number::PosInt(u)));
}
match buf.parse::<i64>() {
Ok(i) if buf != "-0" => Ok(Value::Number(Number::NegInt(i))),
_ => Ok(Value::Number(Number::Float(buf.parse::<f64>().unwrap()))),
}
}
}
impl ToJson for Value {
fn to_json(&self) -> Value {
self.clone()
}
}
impl<T: ToJson + ?Sized> ToJson for &T {
fn to_json(&self) -> Value {
(**self).to_json()
}
fn write_text(&self, out: &mut String) {
(**self).write_text(out)
}
}
impl ToJson for bool {
fn to_json(&self) -> Value {
Value::Bool(*self)
}
}
macro_rules! unsigned {
($($t:ty),*) => {$(
impl ToJson for $t {
fn to_json(&self) -> Value {
Value::Number(Number::PosInt(*self as u64))
}
}
)*};
}
macro_rules! signed {
($($t:ty),*) => {$(
impl ToJson for $t {
fn to_json(&self) -> Value {
if *self >= 0 {
Value::Number(Number::PosInt(*self as u64))
} else {
Value::Number(Number::NegInt(*self as i64))
}
}
}
)*};
}
unsigned!(u8, u16, u32, u64, usize);
signed!(i8, i16, i32, i64, isize);
impl ToJson for f64 {
fn to_json(&self) -> Value {
if self.is_finite() {
Value::Number(Number::Float(*self))
} else {
Value::Null
}
}
}
impl ToJson for f32 {
fn to_json(&self) -> Value {
(*self as f64).to_json()
}
}
impl ToJson for str {
fn to_json(&self) -> Value {
Value::String(self.to_string())
}
}
impl ToJson for String {
fn to_json(&self) -> Value {
Value::String(self.clone())
}
}
impl<T: ToJson> ToJson for Option<T> {
fn to_json(&self) -> Value {
self.as_ref().map_or(Value::Null, |v| v.to_json())
}
fn write_text(&self, out: &mut String) {
match self {
Some(v) => v.write_text(out),
None => out.push_str("null"),
}
}
}
impl<T: ToJson> ToJson for [T] {
fn to_json(&self) -> Value {
Value::Array(self.iter().map(|v| v.to_json()).collect())
}
fn write_text(&self, out: &mut String) {
write_seq(self.iter(), out)
}
}
impl<T: ToJson> ToJson for Vec<T> {
fn to_json(&self) -> Value {
self.as_slice().to_json()
}
fn write_text(&self, out: &mut String) {
self.as_slice().write_text(out)
}
}
impl<T: ToJson, const N: usize> ToJson for [T; N] {
fn to_json(&self) -> Value {
self.as_slice().to_json()
}
fn write_text(&self, out: &mut String) {
self.as_slice().write_text(out)
}
}
impl<A: ToJson, B: ToJson> ToJson for (A, B) {
fn to_json(&self) -> Value {
Value::Array(vec![self.0.to_json(), self.1.to_json()])
}
fn write_text(&self, out: &mut String) {
write_fields_seq(&[&self.0, &self.1], out)
}
}
impl<A: ToJson, B: ToJson, C: ToJson> ToJson for (A, B, C) {
fn to_json(&self) -> Value {
Value::Array(vec![self.0.to_json(), self.1.to_json(), self.2.to_json()])
}
fn write_text(&self, out: &mut String) {
write_fields_seq(&[&self.0, &self.1, &self.2], out)
}
}
fn write_fields_seq(items: &[&dyn ToJson], out: &mut String) {
out.push('[');
for (k, item) in items.iter().enumerate() {
if k > 0 {
out.push(',');
}
item.write_text(out);
}
out.push(']');
}
impl<K: std::fmt::Display, V: ToJson> ToJson for BTreeMap<K, V> {
fn to_json(&self) -> Value {
Value::Object(self.iter().map(|(k, v)| (k.to_string(), v.to_json())).collect())
}
}
impl<T: ToJson> ToJson for std::collections::BTreeSet<T> {
fn to_json(&self) -> Value {
Value::Array(self.iter().map(|v| v.to_json()).collect())
}
fn write_text(&self, out: &mut String) {
write_seq(self.iter(), out)
}
}
impl From<f64> for Value {
fn from(x: f64) -> Value {
x.to_json()
}
}
impl From<bool> for Value {
fn from(b: bool) -> Value {
Value::Bool(b)
}
}
impl From<usize> for Value {
fn from(u: usize) -> Value {
u.to_json()
}
}
impl From<i64> for Value {
fn from(i: i64) -> Value {
i.to_json()
}
}
impl From<String> for Value {
fn from(s: String) -> Value {
Value::String(s)
}
}
impl From<&str> for Value {
fn from(s: &str) -> Value {
Value::String(s.to_string())
}
}
impl<T: ToJson> From<Option<T>> for Value {
fn from(v: Option<T>) -> Value {
v.to_json()
}
}
impl<T: ToJson> From<Vec<T>> for Value {
fn from(v: Vec<T>) -> Value {
v.to_json()
}
}
impl FromJson for Value {
fn from_json(value: &Value) -> Result<Self, Error> {
Ok(value.clone())
}
}
impl FromJson for bool {
fn from_json(value: &Value) -> Result<Self, Error> {
value.as_bool().ok_or_else(|| format!("expected a boolean, got {value}"))
}
}
macro_rules! from_integer {
($($t:ty),*) => {$(
impl FromJson for $t {
fn from_json(value: &Value) -> Result<Self, Error> {
let n = match value {
Value::Number(Number::PosInt(u)) => <$t>::try_from(*u).ok(),
Value::Number(Number::NegInt(i)) => <$t>::try_from(*i).ok(),
_ => None,
};
n.ok_or_else(|| format!("expected an integer ({}), got {value}", stringify!($t)))
}
}
)*};
}
from_integer!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
impl FromJson for f64 {
fn from_json(value: &Value) -> Result<Self, Error> {
value.as_f64().ok_or_else(|| format!("expected a number, got {value}"))
}
}
impl FromJson for String {
fn from_json(value: &Value) -> Result<Self, Error> {
value.as_str().map(str::to_string).ok_or_else(|| format!("expected a string, got {value}"))
}
}
impl<T: FromJson> FromJson for Option<T> {
fn from_json(value: &Value) -> Result<Self, Error> {
if value.is_null() {
Ok(None)
} else {
T::from_json(value).map(Some)
}
}
}
impl<T: FromJson> FromJson for Vec<T> {
fn from_json(value: &Value) -> Result<Self, Error> {
value.as_array().ok_or_else(|| format!("expected an array, got {value}"))?.iter().map(T::from_json).collect()
}
}
impl<A: FromJson, B: FromJson> FromJson for (A, B) {
fn from_json(value: &Value) -> Result<Self, Error> {
match value.as_array().map(Vec::as_slice) {
Some([a, b]) => Ok((A::from_json(a)?, B::from_json(b)?)),
_ => Err(format!("expected a pair, got {value}")),
}
}
}
impl<A: FromJson, B: FromJson, C: FromJson> FromJson for (A, B, C) {
fn from_json(value: &Value) -> Result<Self, Error> {
match value.as_array().map(Vec::as_slice) {
Some([a, b, c]) => Ok((A::from_json(a)?, B::from_json(b)?, C::from_json(c)?)),
_ => Err(format!("expected a triple, got {value}")),
}
}
}
pub struct Fields<'a> {
object: &'a Map<String, Value>,
taken: Vec<&'static str>,
what: &'static str,
}
impl<'a> Fields<'a> {
pub fn of(value: &'a Value, what: &'static str) -> Result<Self, Error> {
let object = value.as_object().ok_or_else(|| format!("{what}: expected an object, got {value}"))?;
Ok(Fields { object, taken: Vec::new(), what })
}
pub fn field<T: FromJson>(&mut self, name: &'static str, default: Option<fn() -> T>) -> Result<T, Error> {
self.taken.push(name);
match (self.object.get(name), default) {
(Some(v), _) => T::from_json(v).map_err(|e| format!("{}.{name}: {e}", self.what)),
(None, Some(d)) => Ok(d()),
(None, None) => Err(format!("{}: missing field `{name}`", self.what)),
}
}
pub fn optional<T: FromJson>(&mut self, name: &'static str) -> Result<Option<T>, Error> {
self.taken.push(name);
match self.object.get(name) {
Some(v) => Option::<T>::from_json(v).map_err(|e| format!("{}.{name}: {e}", self.what)),
None => Ok(None),
}
}
pub fn finish(self, strict: bool) -> Result<(), Error> {
if strict {
if let Some(k) = self.object.keys().find(|k| !self.taken.contains(&k.as_str())) {
return Err(format!("{}: unknown field `{k}`, expected one of {:?}", self.what, self.taken));
}
}
Ok(())
}
}
}
macro_rules! json {
($($json:tt)+) => {
$crate::fusion::shim::json_internal!($($json)+)
};
}
macro_rules! json_internal {
(@array [$($elems:expr,)*]) => {
vec![$($elems,)*]
};
(@array [$($elems:expr),*]) => {
vec![$($elems),*]
};
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!(null)] $($rest)*)
};
(@array [$($elems:expr,)*] true $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!(true)] $($rest)*)
};
(@array [$($elems:expr,)*] false $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!(false)] $($rest)*)
};
(@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!([$($array)*])] $($rest)*)
};
(@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!({$($map)*})] $($rest)*)
};
(@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!($next),] $($rest)*)
};
(@array [$($elems:expr,)*] $last:expr) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)* $crate::fusion::shim::json_internal!($last)])
};
(@array [$($elems:expr),*] , $($rest:tt)*) => {
$crate::fusion::shim::json_internal!(@array [$($elems,)*] $($rest)*)
};
(@object $object:ident () () ()) => {};
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
let _ = $object.insert(::std::string::String::from($($key)+), $value);
$crate::fusion::shim::json_internal!(@object $object () ($($rest)*) ($($rest)*));
};
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
let _ = $object.insert(::std::string::String::from($($key)+), $value);
};
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!(null)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!(true)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!(false)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!([$($array)*])) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!({$($map)*})) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!($value)) , $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object [$($key)+] ($crate::fusion::shim::json_internal!($value)));
};
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
};
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
$crate::fusion::shim::json_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
};
(null) => {
$crate::fusion::shim::serde_json::Value::Null
};
(true) => {
$crate::fusion::shim::serde_json::Value::Bool(true)
};
(false) => {
$crate::fusion::shim::serde_json::Value::Bool(false)
};
([]) => {
$crate::fusion::shim::serde_json::Value::Array(vec![])
};
([ $($tt:tt)+ ]) => {
$crate::fusion::shim::serde_json::Value::Array($crate::fusion::shim::json_internal!(@array [] $($tt)+))
};
({}) => {
$crate::fusion::shim::serde_json::Value::Object($crate::fusion::shim::serde_json::Map::new())
};
({ $($tt:tt)+ }) => {
$crate::fusion::shim::serde_json::Value::Object({
let mut object = $crate::fusion::shim::serde_json::Map::new();
$crate::fusion::shim::json_internal!(@object object () ($($tt)+) ($($tt)+));
object
})
};
($other:expr) => {
$crate::fusion::shim::serde_json::ToJson::to_json(&$other)
};
}
pub(crate) use json;
pub(crate) use json_internal;
macro_rules! nz {
($e:expr) => {
::std::num::NonZeroUsize::new($e as usize).expect("nonzero")
};
}