//! # incparse
//!
//! Zero-copy incremental string parsing with atomic rollback.
//!
//! `incparse` is a small, dependency-free toolkit of composable mini-parsers
//! that operate directly on `&str` buffers. Every parser receives a shared
//! cursor (`&mut usize`) that is advanced on success and left **untouched**
//! on failure. This makes it easy to build hand-written parsers that try
//! several alternatives without copying the input or maintaining a
//! shadow-state.
//!
//! ## Design at a glance
//!
//! * **Cursor model** — parsers take `(buffer: &str, pos: &mut usize)`.
//!   `*pos` always points at a UTF-8 char boundary inside `buffer`.
//! * **Atomic rollback** — the [`atomic`](parse::atomic) combinator runs a
//!   closure against a *copy* of the cursor and commits the new position
//!   only when the closure returns `Ok`. Every combinator in this crate is
//!   built on this primitive, so `Err` results never leave `*pos` dangling
//!   in the middle of a partially-consumed token.
//! * **Zero-copy** — string-returning parsers return `&str` slices into the
//!   original buffer. The only allocations are inside [`obj_list`](parse::obj_list)
//!   (which returns a `Vec`) and inside [`ParseErr`](parse::ParseErr) messages.
//!
//! ## Quick start
//!
//! ```rust
//! use incparse::*;
//!
//! // Parse "Point(3, 4)" into a custom struct.
//! #[derive(Debug, PartialEq)]
//! struct Point(i32, i32);
//!
//! impl Parse for Point {
//!     fn parse_at(buffer: &str, pos: &mut usize) -> Result<Self, ParseErr> {
//!         atomic(pos, |pos| {
//!             token("Point", buffer, pos)?;
//!             token("(", buffer, pos)?;
//!             let x = i32::parse_at(buffer, pos)?;
//!             token(",", buffer, pos)?;
//!             let y = i32::parse_at(buffer, pos)?;
//!             token(")", buffer, pos)?;
//!             Ok(Point(x, y))
//!         })
//!     }
//! }
//!
//! assert_eq!(Point::parse("Point(3, 4)").unwrap(), Point(3, 4));
//! ```
//!
//! ## Primitive number parsing
//!
//! Built-in [`Parse`](parse::Parse) implementations are provided for `u32`,
//! `u64`, `i32`, `i64`, `bool` and `f64`. Their accepted grammars match the
//! corresponding [`core::str::FromStr`] implementations exactly — the
//! library lexes the prefix that belongs to the literal, then delegates the
//! actual conversion (including overflow handling) to `FromStr`. This means
//! the produced values and the set of rejected inputs are identical to what
//! you would get from `"...".parse::<T>()`. The only additional concession
//! is that leading whitespace is skipped before the literal.
//!
//! All numeric parsers are atomic on failure (including overflow): if the
//! lexed text cannot be converted, `*pos` is rolled back.
//!
//! ## What's exported
//!
//! Everything public lives in the [`parse`] module. For convenience the
//! crate root re-exports the whole API, so `use incparse::*;` is enough
//! to bring [`Parse`](parse::Parse), all combinators
//! ([`atomic`](parse::atomic), [`token`](parse::token),
//! [`identifier`](parse::identifier), [`option`](parse::option),
//! [`obj_list`](parse::obj_list), …) and the error type
//! [`ParseErr`](parse::ParseErr) into scope.

pub mod parse;

pub use parse::*;
