Skip to main content

kmdparse/
lib.rs

1#![doc(html_root_url = "https://docs.rs/kmdparse/0.0.2")]
2#![warn(missing_docs)]
3#![no_std]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6//! `kmdparse` is, as the name suggests, parses user commands into arbitrary Rust types,
7//! including in a `no-std` environment.
8//!
9//! Generally, this crate can be viewed as a data deserialization framework. It defines a syntax
10//! designed to be easy to entered interactively and includes utilities for transforming the input
11//! in this format into arbitrary Rust types, as well as automatically suggesting completions for
12//! incomplete user input.
13//!
14//! It is not suitable for parsing command line arguments, even though the syntax it supports is
15//! fairly similar to what those would look like. Instead, it was designed to be used for parsing
16//! commands entered interactively inside the application. Of course, you are not limited to this
17//! use case and free to use `kmdparse` as a generic data deserialization framework in any way
18//! you like.
19//!
20//! # Examples
21//!
22//! Let’s consider the following example. It defines a struct `MailSendCommand` and derives
23//! [`Parsable`] trait for it. This is enough to be able to parse it.
24//!
25//! ```
26//! # extern crate std;
27//! # use std::vec::Vec;
28//! # use std::string::{String, ToString};
29//! use kmdparse::{Parsable, parse};
30//!
31//! #[derive(Debug, PartialEq, Eq, Parsable)]
32//! struct MailSendCommand {
33//!    text: String,
34//!    #[cmd(attr(subject), default = "\"no subject\".to_string()")]
35//!    subject: String,
36//!    #[cmd(attr(to))]
37//!    to: Vec<String>,
38//! }
39//!
40//! # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
41//! let input = "\"Hello, world\" --to user1@example.com user2@example.com --subject Greeting";
42//! let result = parse::<_, MailSendCommand>(input, ())?;
43//! assert_eq!(result, MailSendCommand {
44//!     text: "Hello, world".to_string(),
45//!     subject: "Greeting".to_string(),
46//!     to: vec!["user1@example.com".to_string(), "user2@example.com".to_string()],
47//! });
48//! # Ok(())
49//! # }
50//! ```
51//!
52//! This example demonstrates several features of `kmdparse`:
53//!
54//!  * Parsing functionality can be automatically derived for an arbitrary struct or enum as long
55//!    as the inner types are [`Parsable`] or there is an appropriate [`Parser`] for them. (To
56//!    learn about the distinction between parsable and parser, read documentation for these traits).
57//!  * Derived parser is configurable: you may make fields either required or optional. Optional
58//!    fields can be specified via a name attribute (`--` token). They can have a default value
59//!    explicitly specified (see default attribute on the `subject` field) or not (`to` field
60//!    defaults to an empty vector, as per its [`Default`] implementation)
61//!  * Parsable values can contain nested parsable values: `MailSendCommand` is parsable, it
62//!    contains a [`Vec`] which is parsable and in repeatedly parses [`String`]s that are parsable.
63//!    Note how `kmdparse` recognized that the list of email addresses finished when it
64//!    encountered the attribute that neither [`String`] nor [`Vec`] recognizes.
65//!
66//!
67//! It also supports parsing enums. In case of enum, it expects a discriminator (automatically
68//! converted into kebab-case by the [`Parsable`] derive macro):
69//!
70//! ```
71//! use kmdparse::{parse, Parsable};
72//!
73//! #[derive(Debug, PartialEq, Eq, Parsable)]
74//! enum Priority {
75//!    High,
76//!    Medium,
77//!    Low,
78//! }
79//!
80//! impl Default for Priority {
81//!     fn default() -> Self {
82//!         Priority::Medium
83//!     }
84//! }
85//!
86//! #[derive(Debug, PartialEq, Eq, Parsable)]
87//! enum Command {
88//!     AddTask(String, #[cmd(attr(priority))] Priority),
89//!     Remove(usize),
90//! }
91//!
92//! # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
93//! assert_eq!(
94//!     parse::<_, Command>("add-task parse-all-commands", ())?,
95//!     Command::AddTask("parse-all-commands".to_string(), Priority::Medium),
96//! );
97//! assert_eq!(
98//!     parse::<_, Command>("add-task enjoy-your-day --priority high", ())?,
99//!     Command::AddTask("enjoy-your-day".to_string(), Priority::High),
100//! );
101//! assert_eq!(parse::<_, Command>("remove 1", ())?, Command::Remove(1));
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! # Syntax
107//!
108//! The syntax that `kmdparse` supports is fairly minimal. The parsing machinery sees the input as
109//! a sequence of tokens. Token is any sequence of characters separated by whitespaces. If you wish
110//! to include a whitespace in the token, you may enclose any substring of the input into a pair of
111//! quotation marks (either double or singular); `kmdparse` supports escaping these symbols
112//! inside quoted tokens with a slash (`\`).
113//!
114//! Input can contain a comment beginning with an octothorp (`#`). Octothorps within quoted tokens
115//! are not considered beginning a comment.
116//!
117//! The meaning of the token and attributes are highly specific to each parser. Generally, each
118//! parser consumes tokens sequentially until each required field’s value is filled. It also
119//! handles attributes in any order and at arbitrary positions.
120//!
121//! Due to the nature of the commands' syntax, parsing can seem ambiguous. For example,
122//! `kmdparse` can parse nested structs such as `Vec<Vec<u32>>`. It may be confusing to the end
123//! user, how would a sequence of numbers be interpreted (they all will be put in the only item of
124//! the outer vector). It is best to design your command to be simple and avoid highly nested
125//! structures for the better user experience. In some cases, complexity is unavoidable. In such
126//! situations, users may find useful an ability to group tokens, belonging to the same data
127//! structure, with parenthesis: `(` and `)`. This way, users can express a value `vec![vec![1, 2],
128//! vec![3, 4, 5]]` as `(1 2) (3 4 5)`.
129//!
130//! More details about how the tokenization and the parsing algorithm are documented in the
131//! [`tokens`] module’s and [`Parser`] trait’s documentation.
132//!
133//! # Features
134//! This crate is `no_std` compatible. Features that depend on the standard library are only enabled
135//! when the `std` feature is enabled. These features include support for types from the standard
136//! library, such as `Vec`, `String`, and collections from the standard library.
137
138#[cfg(doc)]
139extern crate std;
140#[cfg(doc)]
141use std::{
142    collections::BTreeSet,
143    string::{String, ToString},
144    vec::Vec,
145};
146
147pub mod error;
148pub mod parsers;
149pub mod testing;
150pub mod tokens;
151
152use error::ParseError;
153use error::ParseFailure;
154#[doc(hidden)]
155pub use kmdparse_derive::Parsable;
156use tokens::TokenStream;
157
158/// The result value returned by the individual parsers
159///
160/// [`Parser::parse`] either succeeds, in which case it returns a value that was parsed and the
161/// remaining tokens in the token stream, or fails with a [`ParseFailure`]. This type alias
162/// represents the return value.
163pub type ParseResult<'a, T> = Result<(T, TokenStream<'a>), ParseFailure<'a>>;
164
165/// Definition of the parsing and completion algorithm for some type
166///
167/// This trait is fundamental for the functionality of `kmdparse`. The implementers must define
168/// two operations: parsing (converting the input [`TokenStream`] into a value of a target type)
169/// and completion (generating the set of possible completions for the last meaningful token in the
170/// input stream).
171///
172/// Most often, the types being parsed are compound, meaning they contain multiple fields with
173/// different parsers. It is best to keep parsers as simple as possible and delegate most of the
174/// work to the child parsers. To ensure correct interaction between parsers, custom
175/// implementations must follow the parsing protocol. The rules are described in the documentation
176/// for each of the `Parser`'s methods.
177///
178/// Please note, that in most cases writing the parser by hand isn't necessary. Parser is
179/// automatically generated for any type that derives [`Parsable`]. The name of the generated
180/// parser is constructed by appending the word Parser to the end of the type.
181///
182/// # Context
183///
184/// The `Parser` trait is generic over an arbitrary context. Context is passed as an argument to both
185/// of the `Parser`'s methods and is intended to make parsers configurable, meaning their behavior
186/// can depend on some information available at runtime.
187///
188/// The following example demonstrates how to implement the parser for a variant-like data,
189/// dependent on data available at runtime.
190///
191/// ```
192/// use kmdparse::{Parser, ParseResult, parse_parser};
193/// use kmdparse::tokens::{TokenStream, Token};
194/// use kmdparse::error::{ParseError, UnrecognizedToken};
195/// use std::borrow::Cow;
196/// use std::collections::{BTreeSet, HashMap};
197///
198/// struct RuntimeContext { variables: HashMap<String, u32> }
199///
200/// #[derive(Default)]
201/// struct VariableParser;
202///
203/// impl<'c> Parser<&'c RuntimeContext> for VariableParser {
204///     type Value = u32;
205///
206///     fn parse<'a>(&self, input: TokenStream<'a>, ctx: &'c RuntimeContext) -> ParseResult<'a, Self::Value> {
207///         match input.take().transpose()? {
208///             None => Err(ParseError::token_required().expected("variable").into()),
209///             Some((attr @ Token::Attribute(_), remaining)) => {
210///                 Err(UnrecognizedToken::new(attr, remaining).into())
211///             }
212///             Some((token @ Token::Text(text), remaining)) => {
213///                 let text = text.parse_string();
214///                 match ctx.variables.get(&text as &str) {
215///                     Some(value) => Ok((*value, remaining)),
216///                     None => Err(UnrecognizedToken::new(token, remaining).into()),
217///                 }
218///             }
219///         }
220///     }
221/// }
222///
223/// # fn main() -> Result<(), ParseError<'static>> {
224/// let context = RuntimeContext {
225///     variables: HashMap::from([("var-1".to_string(), 10), ("var-2".to_string(), 20)]),
226/// };
227///
228/// assert_eq!(parse_parser::<_, VariableParser>("var-1", &context)?, 10);
229/// assert_eq!(parse_parser::<_, VariableParser>("var-2", &context)?, 20);
230/// # Ok(())
231/// # }
232/// ```
233///
234/// Parser implementation should be as generic as possible to avoid type errors when integrating
235/// with other parsers.
236pub trait Parser<Ctx>: Default {
237    /// The type that this parser will parse the input stream into.
238    type Value;
239
240    /// Parsers the beginning of the token stream into a `Value`.
241    ///
242    /// This function performs the parsing of the input stream: it repeatedly consumes tokens from
243    /// the token stream and then produces one of the following return values:
244    ///  * `Ok((value, remaining))` in case of the correctly parsed sequence of tokens. Here
245    ///    `value` is the result of the parsing, (it has type `Self::Value`), and remaining is the
246    ///    token stream representing the set of tokens that wasn’t consumed;
247    ///  * `Err(ParseFailure::Error(error))` in case the parser failed with an error indicating the
248    ///    malformed input. See [`ParseError`];
249    ///  * `Err(ParseFailure::Unexpected(unexpected_token))` if the first token in the input stream
250    ///    is an attribute or an enum variant discriminator that the parser does not recognize.
251    ///
252    /// To be interoperable with other parsers, the parse implementation must follow the parsing
253    /// protocol:
254    ///  * if the first token in the input stream is an attribute and the parser does not recognize
255    ///    this attribute, it should return `Err(UnexpectedToken::new(token, remaining).into())`
256    ///    where `token` is the attribute that was not recognized, and `remaining` is the token
257    ///    stream consisting of tokens directly following token;
258    ///  * if the parser expects the enum variant discriminator and the first token of the input is
259    ///    not recognized as such, it should return `Err(UnexpectedToken::new(token,
260    ///    remaining).into())` with the same values as described above;
261    ///  * the parser must not return [`UnexpectedToken`] result with any token other than the first
262    ///    token of the input stream; if it receives this value from an inner parser, it must convert
263    ///    it into the equivalent error if the parser was not called on the original input;
264    ///  * when all required tokens are successfully consumed parser should continue to take tokens
265    ///    until a text token or an attribute that is not recognized is encountered (this is not
266    ///    necessary if parser does not expect attributes)
267    fn parse<'a>(&self, input: TokenStream<'a>, ctx: Ctx) -> ParseResult<'a, Self::Value>;
268}
269
270/// Sets the default parser for a given type
271///
272/// This trait allows the users of a type to avoid specifying the parser explicitly.
273///
274/// This trait can be procedurally derived for any struct or enum if all its inner types are
275/// Parsable or have explicit parser specified.
276///
277/// # Derive macro
278///
279/// The `Parsable` derive macro accepts attributes that modify parsing behavior. These attributes
280/// are specified in the form `#[cmd(...)]` attributes can be specifed in the same parenthesis
281/// separated by commas or separately: `#[cmd(default, attr(field))]` and `#[cmd(default)]
282/// #[cmd(attr(field))]` are equivalent.
283///
284/// ## Type attribute
285///
286/// The following attributes are applied to the entire struct or enum for which the trait is being
287/// derived.
288///
289/// ### `ctx = "type-name"`, `ctx_bound = "trait-names"`
290///
291/// Restricts the type of the parsing context in case of ctx attribute or bounds the generic
292/// parsing context to the specific trait or collection of traits in case `ctx_bound` attribute is
293/// used. This is needed when one or more inner parser restricts the type of the context it uses.
294///
295/// The following example demonstrates the creation of a custom parser that requires a specific
296/// parsing context and restricting the context type in the derived trait implementation.
297///
298/// ```
299/// use kmdparse::{parse, tokens::TokenStream, Parsable, Parser, ParseResult};
300///
301/// #[derive(Debug, Copy, Clone, PartialEq, Eq)]
302/// enum LengthUnit { Cm, In }
303///
304/// #[derive(Clone)]
305/// struct ParsingContext {
306///     unit: LengthUnit,
307/// }
308///
309/// #[derive(Debug, PartialEq)]
310/// struct Length(f64, LengthUnit);
311///
312/// #[derive(Default)]
313/// struct LengthParser;
314///
315/// impl Parser<ParsingContext> for LengthParser {
316///     type Value = Length;
317///
318///     fn parse<'a>(&self, input: TokenStream<'a>, ctx: ParsingContext) -> ParseResult<'a, Self::Value> {
319///         let unit = ctx.unit;
320///         let parser = <f64 as Parsable<ParsingContext>>::Parser::default();
321///         let (value, remaining) = parser.parse(input, ctx)?;
322///         Ok((Length(value, unit), remaining))
323///     }
324/// }
325///
326/// impl Parsable<ParsingContext> for Length {
327///     type Parser = LengthParser;
328/// }
329///
330/// #[derive(Debug, PartialEq, Parsable)]
331/// #[cmd(ctx = "ParsingContext")]
332/// struct Size {
333///     height: Length,
334///     width: Length,
335/// }
336///
337/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
338/// assert_eq!(
339///     parse::<_, Size>("10 20", ParsingContext{ unit: LengthUnit::Cm })?,
340///     Size {
341///         height: Length(10.0, LengthUnit::Cm),
342///         width: Length(20.0, LengthUnit::Cm)
343///     }
344/// );
345/// # Ok(())
346/// # }
347/// ```
348///
349/// ## Field attributes
350///
351/// The following attributes can be used for the struct’s or enum variant’s fields.
352///
353/// ### `parser = "parser-type-name"`
354///
355/// Specifies a custom parser used for a field.
356///
357/// This attribute is useful in situations where the required parser is different from the parser
358/// defined by the `Parsable` trait (which is used by default) or when implementation of `Parsable`
359/// is not possible (e.g. when dealing with types defined in a foreign crate).
360///
361/// The following example demonstrates how to use `TransformParser` for data validation.
362///
363/// ```
364/// use kmdparse::parsers::{TransformParser, ParsableTransformation};
365/// use kmdparse::error::ParseError;
366/// use kmdparse::Parsable;
367///
368/// struct Number01RangeValidator;
369///
370/// impl ParsableTransformation<f64> for Number01RangeValidator {
371///     type Input = f64;
372///
373///     fn transform(input: Self::Input) -> Result<f64, ParseError<'static>> {
374///         if input < 0.0 || input >= 1.0 {
375///             Err(ParseError::custom("must be between 0 and 1"))
376///         } else {
377///             Ok(input)
378///         }
379///     }
380/// }
381///
382/// #[derive(Debug, Parsable)]
383/// struct Point(
384///     #[cmd(parser = "TransformParser<<f64 as Parsable<kmdparserCtx>>::Parser, Number01RangeValidator, f64>")] f64,
385///     #[cmd(parser = "TransformParser<<f64 as Parsable<kmdparserCtx>>::Parser, Number01RangeValidator, f64>")] f64,
386/// );
387/// ```
388///
389/// ### `default` or `default = "value"` without `attr`
390///
391/// If the `default` attribute is used on a field, this field will not be parsed. Instead, when
392/// constructing the containing instance, the parser uses a default value (if value is not
393/// specified) or a specific value (specified after `=` sign).
394///
395/// ```
396/// use kmdparse::{Parsable, parse};
397///
398/// #[derive(Debug, PartialEq, Eq, Parsable)]
399/// struct MyStruct(#[cmd(default)] u8, #[cmd(default = "5")] u8, u8);
400///
401/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
402/// assert_eq!(parse::<_, MyStruct>("24", ())?, MyStruct(0, 5, 24));
403/// # Ok(())
404/// # }
405/// ```
406///
407/// ### `attr(attribute = "value")` or `attr(attribute)`
408///
409/// Indicates that the field is optional, it can be specified by the user using a named attribute.
410/// This attribute comes in two variants: when “value” is specified, the field’s value is taken
411/// from the expression in the attribute, otherwise the attribute token must be followed by the
412/// field value’s tokens.
413///
414/// ```
415/// use kmdparse::{Parsable, parse};
416///
417/// #[derive(Debug, PartialEq, Eq, Parsable)]
418/// enum Color{ Red, Green, Blue }
419///
420/// impl Default for Color {
421///     fn default() -> Self {
422///         Color::Green
423///     }
424/// }
425///
426/// #[derive(Debug, PartialEq, Eq, Parsable)]
427/// struct MyStruct {
428///     #[cmd(attr(important = "true"))] is_important: bool,
429///     #[cmd(attr(color))] color: Color,
430/// }
431///
432/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
433/// assert_eq!(
434///     parse::<_, MyStruct>("--important", ())?,
435///     MyStruct { color: Color::Green, is_important: true },
436/// );
437/// assert_eq!(
438///     parse::<_, MyStruct>("--color red", ())?,
439///     MyStruct { color: Color::Red, is_important: false },
440/// );
441/// # Ok(())
442/// # }
443/// ```
444///
445/// #### In combination with `default = "value"`
446///
447/// If an optional field’s value is not specified, the default value is used instead, as determined
448/// by the implementation of `Default` trait. This can be overridden by specifying a default value
449/// using `default` attribute.
450///
451/// ```
452/// use kmdparse::{Parsable, parse};
453///
454/// #[derive(Debug, PartialEq, Eq, Parsable)]
455/// struct MyStruct(#[cmd(default = "5", attr(value))] u8);
456///
457/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
458/// assert_eq!(parse::<_, MyStruct>("--value 10", ())?, MyStruct(10));
459/// assert_eq!(parse::<_, MyStruct>("", ())?, MyStruct(5));
460/// # Ok(())
461/// # }
462/// ```
463///
464/// ### `alias_value(alias = "alias", value="value")`
465///
466/// Used for enum variant’s fields. Specifies the value for a field if the specific alias is used
467/// as enum’s discriminator. An `alias` can be either a name of a variant (converted into
468/// kebab-case), a renamed variant name (via `rename` attribute), or an alias defined using `alias`
469/// attribute.
470///
471/// ```
472/// use kmdparse::{Parsable, parse};
473///
474/// #[derive(Debug, PartialEq, Eq, Parsable)]
475/// enum MyEnum {
476///     #[cmd(alias = "enable", alias = "disable")]
477///     SetEnabled(
478///         #[cmd(
479///             alias_value(alias = "enable", value = "true"),
480///             alias_value(alias = "disable", value = "false")
481///         )] bool
482///     )
483/// }
484///
485/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
486/// assert_eq!(parse::<_, MyEnum>("enable", ())?, MyEnum::SetEnabled(true));
487/// assert_eq!(parse::<_, MyEnum>("disable", ())?, MyEnum::SetEnabled(false));
488/// # Ok(())
489/// # }
490/// ```
491///
492/// ## Enum variant attributes
493///
494/// These attributes are applicable to enum variants. Generally, `kmdparse` expects a
495/// discriminator—the variant’s name in kebab-case followed by tokens for its fields if any exist.
496///
497/// ### `rename = "name"`
498///
499/// Changes the name of the variant’s discriminator. The variant cannot be parsed using its
500/// original name.
501///
502/// ```
503/// use kmdparse::{Parsable, parse};
504///
505/// #[derive(Debug, PartialEq, Eq, Parsable)]
506/// enum MyEnum {
507///     #[cmd(rename = "first")] One,
508///     #[cmd(rename = "second")] Two,
509/// }
510///
511/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
512/// assert_eq!(parse::<_, MyEnum>("first", ())?, MyEnum::One);
513/// assert!(parse::<_, MyEnum>("one", ()).is_err());
514/// # Ok(())
515/// # }
516/// ```
517///
518/// ### `alias = "alias"`
519///
520/// Adds an alias for the variant. Variant can have an arbitrary number of aliases and the value
521/// can be parsed using any of this. Specifying an alias does not prevent the usage of the
522/// variant’s original name.
523///
524/// ```
525/// use kmdparse::{Parsable, parse};
526///
527/// #[derive(Debug, PartialEq, Eq, Parsable)]
528/// enum Color {
529///     Black,
530///     White,
531///     #[cmd(alias = "grey")] Gray,
532/// }
533///
534/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
535/// assert_eq!(parse::<_, Color>("grey", ())?, Color::Gray);
536/// assert_eq!(parse::<_, Color>("gray", ())?, Color::Gray);
537/// # Ok(())
538/// # }
539/// ```
540///
541/// ### `ignore`
542///
543/// Disables the parsing of the variant. Note that this does not prevent assigning aliases to the
544/// variant.
545///
546/// ```
547/// use kmdparse::{Parsable, parse};
548///
549/// #[derive(Debug, PartialEq, Eq, Parsable)]
550/// enum MyEnum {
551///     Command,
552///     #[cmd(ignore)] NonInteractive,
553/// }
554///
555/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
556/// assert!(parse::<_, MyEnum>("non-interactive", ()).is_err());
557/// # Ok(())
558/// # }
559/// ```
560///
561/// ### `transparent`
562///
563/// Indicates that a variant can be parsed without a discriminator. This can be used when splitting
564/// a large enum into several smaller ones is desirable.
565///
566/// ```
567/// use kmdparse::{Parsable, parse};
568///
569/// #[derive(Debug, PartialEq, Eq, Parsable)]
570/// enum Subcommand { First, Second }
571///
572/// #[derive(Debug, PartialEq, Eq, Parsable)]
573/// enum Command {
574///     #[cmd(transparent)]
575///     Subcommand(Subcommand),
576///     Third,
577/// }
578///
579/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
580/// assert_eq!(parse::<_, Command>("first", ())?, Command::Subcommand(Subcommand::First));
581/// assert_eq!(parse::<_, Command>("third", ())?, Command::Third);
582/// # Ok(())
583/// # }
584/// ```
585///
586/// ### `transparent_no_error`
587///
588/// Functions similarly to `transparent` but does not terminate parsing on failure. It is useful
589/// when the first field of this variant is not an enum.
590///
591/// ```
592/// use kmdparse::{Parsable, parse};
593///
594/// #[derive(Debug, PartialEq,Parsable)]
595/// enum Value {
596///     #[cmd(transparent_no_error)] Integer(i64),
597///     #[cmd(transparent_no_error)] Real(f64),
598///     #[cmd(transparent_no_error)] Boolean(bool),
599/// }
600///
601/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
602/// assert_eq!(parse::<_, Value>("0.4", ())?, Value::Real(0.4));
603/// assert_eq!(parse::<_, Value>("12", ())?, Value::Integer(12));
604/// assert_eq!(parse::<_, Value>("true", ())?, Value::Boolean(true));
605/// # Ok(())
606/// # }
607/// ```
608///
609/// Note that in the example above, the orders in which the enum variants are declared matters:
610/// `kmdparse` tries to parse transparent variants in order in which they are declared and
611/// returns the first successfully parsed result.
612pub trait Parsable<Ctx> {
613    /// The parser type for this type
614    type Parser: Parser<Ctx, Value = Self>;
615}
616
617/// Parsers a value from an input string using an explicitly specified parser
618///
619/// This function takes an input string slice as an input and a context, and returns a value parsed
620/// from the input or an error. `parse` ensures that all tokens from the input string were
621/// consumed, and the input is valid.
622///
623/// This function is different from [`parse`] in that is expects a parser as its second generic
624/// parameter. The value returned by `parse_parser` does not need to implement [`Parsable`].
625/// `parse_parser` most commonly used with custom parsers.
626///
627/// # Example:
628///
629/// ```
630/// use kmdparse::parse_parser;
631/// use kmdparse::parsers::{IntegerParser, StringParser, tuples::TupleParser2};
632///
633/// type ExplicitParser = TupleParser2<IntegerParser<u64>, StringParser>;
634/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
635/// let value = parse_parser::<_, ExplicitParser>("42 fourty-two", ())?;
636/// assert_eq!(value, (42, "fourty-two".to_string()));
637/// # Ok(())
638/// # }
639/// ```
640pub fn parse_parser<Ctx, P: Parser<Ctx>>(
641    input: &str,
642    ctx: Ctx,
643) -> Result<P::Value, ParseError<'_>> {
644    let tokens = TokenStream::new(input);
645    match P::default().parse(tokens, ctx) {
646        Ok((result, remaining)) => match remaining.peek() {
647            Some(Ok(token)) => Err(ParseError::unknown(token)),
648            Some(Err(err)) => Err(err.into()),
649            None => Ok(result),
650        },
651        Err(ParseFailure::Error(err)) => Err(err),
652        Err(ParseFailure::Unrecognized(unrecognized)) => Err(unrecognized.into_error()),
653    }
654}
655
656/// Parsers a [`Parsable`] value from an input string
657///
658/// This function takes an input string slice as an input and a context, and returns a value parsed
659/// from the input or an error. `parse` ensures that all tokens from the input string were
660/// consumed, and the input is valid.
661///
662/// # Example:
663///
664/// ```
665/// use kmdparse::parse;
666///
667/// # fn main() -> Result<(), kmdparse::error::ParseError<'static>> {
668/// let value: (u64, String) = parse("42 fourty-two", ())?;
669/// assert_eq!(value, (42, "fourty-two".to_string()));
670/// # Ok(())
671/// # }
672/// ```
673pub fn parse<Ctx, T: Parsable<Ctx>>(input: &str, ctx: Ctx) -> Result<T, ParseError<'_>> {
674    parse_parser::<_, T::Parser>(input, ctx)
675}