cucumber/parser/mod.rs
1// Copyright (c) 2018-2024 Brendan Molloy <brendan@bbqsrc.net>,
2// Ilya Solovyiov <ilya.solovyiov@gmail.com>,
3// Kai Ren <tyranron@gmail.com>
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Tools for parsing [Gherkin] files.
12//!
13//! [Gherkin]: https://cucumber.io/docs/gherkin/reference
14
15pub mod basic;
16
17use std::sync::Arc;
18
19use derive_more::{Display, Error};
20use futures::Stream;
21
22use crate::feature::ExpandExamplesError;
23
24#[doc(inline)]
25pub use self::basic::Basic;
26
27/// Source of parsed [`Feature`]s.
28///
29/// [`Feature`]: gherkin::Feature
30pub trait Parser<I> {
31 /// CLI options of this [`Parser`]. In case no options should be introduced,
32 /// just use [`cli::Empty`].
33 ///
34 /// All CLI options from [`Parser`], [`Runner`] and [`Writer`] will be
35 /// merged together, so overlapping arguments will cause a runtime panic.
36 ///
37 /// [`cli::Empty`]: crate::cli::Empty
38 /// [`Runner`]: crate::Runner
39 /// [`Writer`]: crate::Writer
40 type Cli: clap::Args;
41
42 /// Output [`Stream`] of parsed [`Feature`]s.
43 ///
44 /// [`Feature`]: gherkin::Feature
45 type Output: Stream<Item = Result<gherkin::Feature>> + 'static;
46
47 /// Parses the given `input` into a [`Stream`] of [`Feature`]s.
48 ///
49 /// [`Feature`]: gherkin::Feature
50 fn parse(self, input: I, cli: Self::Cli) -> Self::Output;
51}
52
53/// Result of parsing [Gherkin] files.
54///
55/// [Gherkin]: https://cucumber.io/docs/gherkin/reference
56#[allow(clippy::absolute_paths)] // intentional
57pub type Result<T> = std::result::Result<T, Error>;
58
59/// [`Parser`] error.
60#[derive(Clone, Debug, Display, Error)]
61pub enum Error {
62 /// Failed to parse a [`Feature`].
63 ///
64 /// [`Feature`]: gherkin::Feature
65 #[display(fmt = "Failed to parse feature: {}", _0)]
66 Parsing(Arc<gherkin::ParseFileError>),
67
68 /// Failed to expand [`Examples`]
69 ///
70 /// [`Examples`]: gherkin::Examples
71 #[display(fmt = "Failed to expand examples: {}", _0)]
72 ExampleExpansion(Arc<ExpandExamplesError>),
73}
74
75impl From<gherkin::ParseFileError> for Error {
76 fn from(e: gherkin::ParseFileError) -> Self {
77 Self::Parsing(Arc::new(e))
78 }
79}
80
81impl From<ExpandExamplesError> for Error {
82 fn from(e: ExpandExamplesError) -> Self {
83 Self::ExampleExpansion(Arc::new(e))
84 }
85}