radn-rs/src/mode.rs
2023-07-30 20:30:46 +00:00

238 lines
7.6 KiB
Rust

//! [`Mode`]-based parsing.
mod inlining;
mod regular;
mod serialization;
mod slice_deserializer;
mod stream;
use std::marker::PhantomData;
pub use self::inlining::InliningMode;
pub use self::regular::RegularMode;
pub use self::serialization::{Deserializer, DeserializerExt, Serializable, Serializer};
pub use self::slice_deserializer::SliceDeserializer;
pub use self::stream::{Stream, StreamExt, StreamResultExt};
/// See [`ModeResult`].
pub type ParseSuccess<M, A, I> = <M as Mode>::ParseSuccess<A, I>;
/// [`Mode`] equivalent of [`ParseResult`] for extension.
///
/// [`ParseResult`]: crate::rcore::ParseResult
pub type ExtensionResult<M, A, E> = <M as Mode>::ExtensionResult<A, E>;
/// See [`Mode::prepare`].
pub type ExtensionSource<M, A> = <M as Mode>::ExtensionSource<A>;
/// [`Mode`] equivalent of [`ParseResult`].
///
/// [`ParseResult`]: crate::rcore::ParseResult
pub type ModeResult<M, A, E, I> = Result<ParseSuccess<M, A, I>, E>;
/// Mode of parsing.
///
/// | [`Mode`] | [`Mode::ParseSuccess<A, I>`] | [`Mode::ExtensionResult<A, E>`] | [`Mode::ExtensionSource<A>`] |
/// |------------------|------------------------------|---------------------------------|------------------------------|
/// | [`RegularMode`] | `A` | [`Result<A, E>`] | `A` |
/// | [`InliningMode`] | [`(A, I)`] | `E` | [`()`] |
///
/// [`(A, I)`]: tuple
/// [`()`]: unit
pub trait Mode {
/// Successful parsing, may countain the parser itself
/// (`I`, usually [`Stream`]).
type ParseSuccess<A, I>;
/// Result of extending the value, failing sometimes or always.
type ExtensionResult<A, E>;
/// Data enough to try extending the value.
///
/// May be empty for always-failing extensions.
type ExtensionSource<A>;
/// Do something with the successfully parsed value, potentially failing.
///
/// Useful for for wrappers and chaining parsing after [`InliningFactory`].
///
/// See also [`Mode::map`]
///
/// [`InliningFactory`]: crate::rcore::InliningFactory
fn bind<A0, A1, E, I>(
s: Self::ParseSuccess<A0, I>,
f: impl FnOnce(A0) -> Result<A1, E>,
) -> ModeResult<Self, A1, E, I>;
/// Map the successfully parsed value.
///
/// Useful for for wrappers.
///
/// See also [`Mode::bind`]
fn map<A0, A1, I>(
s: Self::ParseSuccess<A0, I>,
f: impl FnOnce(A0) -> A1,
) -> Self::ParseSuccess<A1, I>;
/// Discard any extra information contained in [`Mode::ParseSuccess`].
fn seal<A, I>(s: Self::ParseSuccess<A, I>) -> A;
/// Map the error of an extension result.
///
/// Useful for for wrappers and chaining parsing after [`InliningFactory`].
///
/// [`InliningFactory`]: crate::rcore::InliningFactory
fn xmap_err<A, E0, E1>(
result: Self::ExtensionResult<A, E0>,
f: impl FnOnce(E0) -> E1,
) -> Self::ExtensionResult<A, E1>;
/// Do something with the extension result, potentially failing.
///
/// Useful for wrappers and chaining extension after [`InliningFactory`].
///
/// [`InliningFactory`]: crate::rcore::InliningFactory
fn xbind<A0, A1, E>(
result: Self::ExtensionResult<A0, E>,
f: impl FnOnce(A0) -> Result<A1, E>,
) -> Self::ExtensionResult<A1, E>;
/// Convert [`Mode::ExtensionResult`] to [`Result`].
fn xseal<A, E>(result: Self::ExtensionResult<A, E>) -> Result<A, E>;
fn smap<A0, A1>(
source: Self::ExtensionSource<A0>,
f: impl FnOnce(A0) -> A1,
) -> Self::ExtensionSource<A1>;
fn prepare<A>(a: A) -> Self::ExtensionSource<A>;
/// For abstract extension implementations.
fn xsbind<AB, A, B, E>(
ab: Self::ExtensionSource<AB>,
t2ab: impl FnOnce(AB) -> (A, B),
ce: impl FnOnce(Self::ExtensionSource<B>) -> Self::ExtensionResult<B, E>,
ab2t: impl FnOnce(A, B) -> Result<AB, E>,
) -> Self::ExtensionResult<AB, E>;
}
/// Type that a [`Mode`] associated with it.
pub trait ParseMode {
/// Associated [`Mode`].
type Mode: ?Sized + Mode;
}
/// [`ParseMode`] equivalent of [`ParseSuccess`].
pub type ParseSuccessP<F, A, I> = ParseSuccess<<F as ParseMode>::Mode, A, I>;
/// [`ParseMode`] equivalent of [`ExtensionResult`].
pub type ExtensionResultP<F, A, E> = ExtensionResult<<F as ParseMode>::Mode, A, E>;
/// [`ParseMode`] equivalent of [`ExtensionSource`].
pub type ExtensionSourceP<F, A> = ExtensionSource<<F as ParseMode>::Mode, A>;
/// [`ParseMode`] equivalent of [`ModeResult`].
pub type ModeResultP<F, A, E, I> = ModeResult<<F as ParseMode>::Mode, A, E, I>;
/// Extension trait for all [`ParseMode`] types, re-exporting [`Mode`] traits.
pub trait ParseModeExt: ParseMode {
/// [`Mode::bind`].
fn bind<A0, A1, E, I>(
s: ParseSuccessP<Self, A0, I>,
f: impl FnOnce(A0) -> Result<A1, E>,
) -> ModeResultP<Self, A1, E, I> {
<Self::Mode as Mode>::bind(s, f)
}
/// [`Mode::map`].
fn map<A0, A1, I>(
s: ParseSuccessP<Self, A0, I>,
f: impl FnOnce(A0) -> A1,
) -> ParseSuccessP<Self, A1, I> {
<Self::Mode as Mode>::map(s, f)
}
/// [`Mode::seal`].
fn seal<A, I>(s: ParseSuccessP<Self, A, I>) -> A {
<Self::Mode as Mode>::seal(s)
}
/// [`Mode::xmap_err`].
fn xmap_err<A, E0, E1>(
result: ExtensionResultP<Self, A, E0>,
f: impl FnOnce(E0) -> E1,
) -> ExtensionResultP<Self, A, E1> {
<Self::Mode as Mode>::xmap_err(result, f)
}
/// [`Mode::xbind`].
fn xbind<A0, A1, E>(
result: ExtensionResultP<Self, A0, E>,
f: impl FnOnce(A0) -> Result<A1, E>,
) -> ExtensionResultP<Self, A1, E> {
<Self::Mode as Mode>::xbind(result, f)
}
/// [`Mode::xseal`].
fn xseal<A, E>(result: ExtensionResultP<Self, A, E>) -> Result<A, E> {
<Self::Mode as Mode>::xseal(result)
}
/// [`Mode::smap`].
fn smap<A0, A1>(
source: ExtensionSourceP<Self, A0>,
f: impl FnOnce(A0) -> A1,
) -> ExtensionSourceP<Self, A1> {
<Self::Mode as Mode>::smap(source, f)
}
/// [`Mode::prepare`].
fn prepare<A>(a: A) -> ExtensionSourceP<Self, A> {
<Self::Mode as Mode>::prepare(a)
}
/// [`Mode::xsbind`].
fn xsbind<AB, A, B, E>(
ab: ExtensionSourceP<Self, AB>,
t2ab: impl FnOnce(AB) -> (A, B),
ce: impl FnOnce(ExtensionSourceP<Self, B>) -> ExtensionResultP<Self, B, E>,
ab2t: impl FnOnce(A, B) -> Result<AB, E>,
) -> ExtensionResultP<Self, AB, E> {
<Self::Mode as Mode>::xsbind(ab, t2ab, ce, ab2t)
}
}
impl<F: ParseMode> ParseModeExt for F {}
/// For auto-implementing [`FactoryParse`] and [`Atomic`].
///
/// [`FactoryParse`]: crate::rcore::FactoryParse
/// [`Atomic`]: crate::atomic::Atomic
pub trait ImplMode {
/// Same as [`ParseMode::Mode`]
type Mode: ?Sized + Mode;
}
/// Used with [`WithMode`] for linking [`ImplMode`] to [`FactoryParse`] and [`Atomic`].
///
/// [`FactoryParse`]: crate::rcore::FactoryParse
/// [`Atomic`]: crate::atomic::Atomic
pub trait WithParseMode: ImplMode {
/// [`WithMode`] implementing [`FactoryModeProxy`] or [`AtomicModeProxy`].
///
/// [`FactoryModeProxy`]: crate::rcore::FactoryModeProxy
/// [`AtomicModeProxy`]: crate::atomic::AtomicModeProxy
type WithMode: ?Sized;
}
impl<T: ?Sized + ImplMode> ParseMode for T {
type Mode = <Self as ImplMode>::Mode;
}
impl<T: ?Sized + ImplMode> WithParseMode for T {
type WithMode = WithMode<Self, <Self as ParseMode>::Mode>;
}
/// Used as [`WithParseMode::WithMode`].
pub struct WithMode<T: ?Sized, M: ?Sized>(PhantomData<M>, T);