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