use crate::{
args::State,
buffer::MetaInfo,
error::{Message, MissingItem},
Doc, Error, Meta, Parser,
};
use std::marker::PhantomData;
pub struct ParseFallbackWith<T, P, F, E> {
pub(crate) inner: P,
pub(crate) inner_res: PhantomData<T>,
pub(crate) fallback: F,
pub(crate) value_str: String,
pub(crate) err: PhantomData<E>,
}
impl<T, P, F, E> Parser<T> for ParseFallbackWith<T, P, F, E>
where
P: Parser<T>,
F: Fn() -> Result<T, E>,
E: ToString,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let mut clone = args.clone();
match self.inner.eval(&mut clone) {
Ok(ok) => {
std::mem::swap(args, &mut clone);
Ok(ok)
}
Err(Error(e)) => {
#[cfg(feature = "autocomplete")]
args.swap_comps(&mut clone);
if e.can_catch() {
match (self.fallback)() {
Ok(ok) => Ok(ok),
Err(e) => Err(Error(Message::PureFailed(e.to_string()))),
}
} else {
Err(Error(e))
}
}
}
}
fn meta(&self) -> Meta {
let m = Meta::Optional(Box::new(self.inner.meta()));
if self.value_str.is_empty() {
m
} else {
let buf = Doc::from(self.value_str.as_str());
Meta::Suffix(Box::new(m), Box::new(buf))
}
}
}
pub struct ParseGroupHelp<P> {
pub(crate) inner: P,
pub(crate) message: Doc,
}
impl<T, P> Parser<T> for ParseGroupHelp<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
#[cfg(feature = "autocomplete")]
let mut comp_items = Vec::new();
#[cfg(feature = "autocomplete")]
args.swap_comps_with(&mut comp_items);
#[allow(clippy::let_and_return)]
let res = self.inner.eval(args);
#[cfg(feature = "autocomplete")]
args.swap_comps_with(&mut comp_items);
#[cfg(feature = "autocomplete")]
args.push_with_group(&self.message.to_completion(), &mut comp_items);
res
}
fn meta(&self) -> Meta {
let meta = Box::new(self.inner.meta());
Meta::Subsection(meta, Box::new(self.message.clone()))
}
}
pub struct ParseWithGroupHelp<P, F> {
pub(crate) inner: P,
pub(crate) f: F,
}
impl<T, P, F> Parser<T> for ParseWithGroupHelp<P, F>
where
P: Parser<T>,
F: Fn(MetaInfo) -> Doc,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
self.inner.eval(args)
}
fn meta(&self) -> Meta {
let meta = self.inner.meta();
let buf = (self.f)(MetaInfo(&meta));
Meta::Subsection(Box::new(meta), Box::new(buf))
}
}
pub struct ParseSome<P> {
pub(crate) inner: P,
pub(crate) message: &'static str,
pub(crate) catch: bool,
}
impl<P> ParseSome<P> {
#[must_use]
#[cfg_attr(not(doctest), doc = include_str!("docs2/some_catch.md"))]
pub fn catch(mut self) -> Self {
self.catch = true;
self
}
}
impl<T, P> Parser<Vec<T>> for ParseSome<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<Vec<T>, Error> {
let mut res = Vec::new();
let mut len = usize::MAX;
while let Some(val) = parse_option(&self.inner, &mut len, args, self.catch)? {
res.push(val);
}
if res.is_empty() {
Err(Error(Message::ParseSome(self.message)))
} else {
Ok(res)
}
}
fn meta(&self) -> Meta {
Meta::Many(Box::new(Meta::Required(Box::new(self.inner.meta()))))
}
}
pub struct ParseCollect<P, C, T> {
pub(crate) inner: P,
pub(crate) catch: bool,
pub(crate) ctx: PhantomData<(C, T)>,
}
impl<T, C, P> ParseCollect<P, C, T> {
#[must_use]
#[cfg_attr(not(doctest), doc = include_str!("docs2/some_catch.md"))]
pub fn catch(mut self) -> Self {
self.catch = true;
self
}
}
impl<T, C, P> Parser<C> for ParseCollect<P, C, T>
where
P: Parser<T>,
C: FromIterator<T>,
{
fn eval(&self, args: &mut State) -> Result<C, Error> {
let mut len = usize::MAX;
std::iter::from_fn(|| parse_option(&self.inner, &mut len, args, self.catch).transpose())
.collect::<Result<C, Error>>()
}
fn meta(&self) -> Meta {
Meta::Many(Box::new(Meta::Required(Box::new(self.inner.meta()))))
}
}
pub struct ParseHide<P> {
pub(crate) inner: P,
}
impl<T, P> Parser<T> for ParseHide<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
#[cfg(feature = "autocomplete")]
let mut comps = Vec::new();
#[cfg(feature = "autocomplete")]
args.swap_comps_with(&mut comps);
#[allow(clippy::let_and_return)]
let res = self.inner.eval(args);
#[cfg(feature = "autocomplete")]
args.swap_comps_with(&mut comps);
if let Err(Error(Message::Missing(_))) = res {
Err(Error(Message::Missing(Vec::new())))
} else {
res
}
}
fn meta(&self) -> Meta {
Meta::Skip
}
}
pub struct ParseUsage<P> {
pub(crate) inner: P,
pub(crate) usage: Doc,
}
impl<T, P> Parser<T> for ParseUsage<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
self.inner.eval(args)
}
fn meta(&self) -> Meta {
Meta::CustomUsage(Box::new(self.inner.meta()), Box::new(self.usage.clone()))
}
}
pub struct ParseOrElse<T> {
pub(crate) this: Box<dyn Parser<T>>,
pub(crate) that: Box<dyn Parser<T>>,
}
impl<T> Parser<T> for ParseOrElse<T> {
fn eval(&self, args: &mut State) -> Result<T, Error> {
#[cfg(feature = "autocomplete")]
let mut comp_items = Vec::new();
#[cfg(feature = "autocomplete")]
args.swap_comps_with(&mut comp_items);
let mut args_a = args.clone();
let mut args_b = args.clone();
let (res_a, err_a) = match self.this.eval(&mut args_a) {
Ok(ok) => (Some(ok), None),
Err(err) => (None, Some(err)),
};
let (res_b, err_b) = match self.that.eval(&mut args_b) {
Ok(ok) => (Some(ok), None),
Err(err) => (None, Some(err)),
};
if this_or_that_picks_first(
err_a,
err_b,
args,
&mut args_a,
&mut args_b,
#[cfg(feature = "autocomplete")]
comp_items,
)? {
Ok(res_a.unwrap())
} else {
Ok(res_b.unwrap())
}
}
fn meta(&self) -> Meta {
self.this.meta().or(self.that.meta())
}
}
fn this_or_that_picks_first(
err_a: Option<Error>,
err_b: Option<Error>,
args: &mut State,
args_a: &mut State,
args_b: &mut State,
#[cfg(feature = "autocomplete")] mut comp_stash: Vec<crate::complete_gen::Comp>,
) -> Result<bool, Error> {
match Ord::cmp(&args_a.depth(), &args_b.depth()) {
std::cmp::Ordering::Less => {
std::mem::swap(args, args_b);
#[cfg(feature = "autocomplete")]
if let Some(comp) = args.comp_mut() {
comp.extend_comps(comp_stash);
}
return match err_b {
Some(err) => Err(err),
None => Ok(false),
};
}
std::cmp::Ordering::Equal => {}
std::cmp::Ordering::Greater => {
std::mem::swap(args, args_a);
#[cfg(feature = "autocomplete")]
if let Some(comp) = args.comp_mut() {
comp.extend_comps(comp_stash);
}
return match err_a {
Some(err) => Err(err),
None => Ok(true),
};
}
}
let no_consume_a = args.len() == args_a.len();
let no_consume_b = args.len() == args_b.len();
#[allow(clippy::let_and_return)] let res = match (err_a, err_b) {
(None, None) => {
if no_consume_a && no_consume_b {
Ok((true, None))
} else {
Ok(args_a.pick_winner(args_b))
}
}
(None, Some(e2)) if no_consume_a && e2.0.wrong_input() => Err(e2),
(Some(e1), None) if no_consume_b && e1.0.wrong_input() => Err(e1),
(Some(e1), Some(e2)) => Err(e1.combine_with(e2)),
(a_ok, _) => Ok((a_ok.is_none(), None)),
};
#[cfg(feature = "autocomplete")]
{
let mut keep_a = true;
let mut keep_b = true;
if args_a.len() != args_b.len() {
if let (Some(_), Some(_)) = (args_a.comp_mut(), args_b.comp_mut()) {
'check: for (ix, arg) in args_a.items.iter().enumerate() {
if ix + 1 == args_a.items.len() {
let os = arg.os_str();
if os.is_empty() || os == "-" || os == "--" {
break 'check;
}
}
if let (Some(a), Some(b)) = (args_a.present(ix), args_b.present(ix)) {
match (a, b) {
(false, true) => {
keep_b = false;
break 'check;
}
(true, false) => {
keep_a = false;
break 'check;
}
_ => {}
}
}
}
}
}
if let (Some(a), Some(b)) = (args_a.comp_mut(), args_b.comp_mut()) {
if keep_a {
comp_stash.extend(a.drain_comps());
}
if keep_b {
comp_stash.extend(b.drain_comps());
}
}
}
match res {
Ok((true, ix)) => {
if let Some(win) = ix {
args_a.save_conflicts(args_b, win);
}
std::mem::swap(args, args_a);
}
Ok((false, ix)) => {
if let Some(win) = ix {
args_b.save_conflicts(args_a, win);
}
std::mem::swap(args, args_b);
}
Err(_) => {}
}
#[cfg(feature = "autocomplete")]
if let Some(comp) = args.comp_mut() {
comp.extend_comps(comp_stash);
}
Ok(res?.0)
}
pub struct ParseWith<T, P, F, E, R> {
pub(crate) inner: P,
pub(crate) inner_res: PhantomData<T>,
pub(crate) parse_fn: F,
pub(crate) res: PhantomData<R>,
pub(crate) err: PhantomData<E>,
}
impl<T, P, F, E, R> Parser<R> for ParseWith<T, P, F, E, R>
where
P: Parser<T>,
F: Fn(T) -> Result<R, E>,
E: ToString,
{
fn eval(&self, args: &mut State) -> Result<R, Error> {
let t = self.inner.eval(args)?;
match (self.parse_fn)(t) {
Ok(r) => Ok(r),
Err(e) => Err(Error(Message::ParseFailed(args.current, e.to_string()))),
}
}
fn meta(&self) -> Meta {
self.inner.meta()
}
}
pub struct ParseFallback<P, T> {
pub(crate) inner: P,
pub(crate) value: T,
pub(crate) value_str: String,
}
impl<P, T> Parser<T> for ParseFallback<P, T>
where
P: Parser<T>,
T: Clone,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let mut clone = args.clone();
match self.inner.eval(&mut clone) {
Ok(ok) => {
std::mem::swap(args, &mut clone);
Ok(ok)
}
Err(Error(e)) => {
#[cfg(feature = "autocomplete")]
args.swap_comps(&mut clone);
if e.can_catch() {
Ok(self.value.clone())
} else {
Err(Error(e))
}
}
}
}
fn meta(&self) -> Meta {
let m = Meta::Optional(Box::new(self.inner.meta()));
if self.value_str.is_empty() {
m
} else {
let buf = Doc::from(self.value_str.as_str());
Meta::Suffix(Box::new(m), Box::new(buf))
}
}
}
struct DisplayWith<'a, T, F>(&'a T, F);
impl<'a, T, F: Fn(&'a T, &mut std::fmt::Formatter<'_>) -> std::fmt::Result> std::fmt::Display
for DisplayWith<'a, T, F>
{
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(value, display) = self;
display(value, f)
}
}
impl<P, T: std::fmt::Display> ParseFallback<P, T> {
#[cfg_attr(not(doctest), doc = include_str!("docs2/dis_fallback.md"))]
#[must_use]
pub fn display_fallback(mut self) -> Self {
self.value_str = format!("[default: {}]", self.value);
self
}
}
impl<P, T: std::fmt::Debug> ParseFallback<P, T> {
#[cfg_attr(not(doctest), doc = include_str!("docs2/deb_fallback_with.md"))]
#[must_use]
pub fn debug_fallback(mut self) -> Self {
self.value_str = format!("[default: {:?}]", self.value);
self
}
}
impl<P, T> ParseFallback<P, T> {
#[cfg_attr(not(doctest), doc = include_str!("docs2/format_fallback.md"))]
#[must_use]
pub fn format_fallback(
mut self,
format: impl Fn(&T, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
) -> Self {
self.value_str = format!("[default: {}]", DisplayWith(&self.value, format));
self
}
}
impl<P, T: std::fmt::Display, F, E> ParseFallbackWith<T, P, F, E>
where
F: Fn() -> Result<T, E>,
{
#[cfg_attr(not(doctest), doc = include_str!("docs2/dis_fallback_with.md"))]
#[must_use]
pub fn display_fallback(mut self) -> Self {
if let Ok(val) = (self.fallback)() {
self.value_str = format!("[default: {}]", val);
}
self
}
}
impl<P, T: std::fmt::Debug, F, E> ParseFallbackWith<T, P, F, E>
where
F: Fn() -> Result<T, E>,
{
#[cfg_attr(not(doctest), doc = include_str!("docs2/deb_fallback.md"))]
#[must_use]
pub fn debug_fallback(mut self) -> Self {
if let Ok(val) = (self.fallback)() {
self.value_str = format!("[default: {:?}]", val);
}
self
}
}
impl<P, T, F, E> ParseFallbackWith<T, P, F, E>
where
F: Fn() -> Result<T, E>,
{
#[cfg_attr(not(doctest), doc = include_str!("docs2/format_fallback_with.md"))]
#[must_use]
pub fn format_fallback(
mut self,
format: impl Fn(&T, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
) -> Self {
if let Ok(val) = (self.fallback)() {
self.value_str = format!("[default: {}]", DisplayWith(&val, format));
}
self
}
}
pub struct ParseGuard<P, F> {
pub(crate) inner: P,
pub(crate) check: F,
pub(crate) message: &'static str,
}
impl<T, P, F> Parser<T> for ParseGuard<P, F>
where
P: Parser<T>,
F: Fn(&T) -> bool,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let t = self.inner.eval(args)?;
if (self.check)(&t) {
Ok(t)
} else {
Err(Error(Message::GuardFailed(args.current, self.message)))
}
}
fn meta(&self) -> Meta {
self.inner.meta()
}
}
pub struct ParseCount<P, T> {
pub(crate) inner: P,
pub(crate) ctx: PhantomData<T>,
}
impl<T, P> Parser<usize> for ParseCount<P, T>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<usize, Error> {
let mut res = 0;
let mut current = args.len();
let mut len = usize::MAX;
while (parse_option(&self.inner, &mut len, args, false)?).is_some() {
res += 1;
if current == args.len() {
break;
}
current = args.len();
}
Ok(res)
}
fn meta(&self) -> Meta {
Meta::Many(Box::new(Meta::Optional(Box::new(self.inner.meta()))))
}
}
pub struct ParseLast<P> {
pub(crate) inner: P,
}
impl<T, P> Parser<T> for ParseLast<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let mut last = None;
let mut current = args.len();
let mut len = usize::MAX;
while let Some(val) = parse_option(&self.inner, &mut len, args, false)? {
last = Some(val);
if current == args.len() {
break;
}
current = args.len();
}
if let Some(last) = last {
Ok(last)
} else {
self.inner.eval(args)
}
}
fn meta(&self) -> Meta {
Meta::Many(Box::new(Meta::Required(Box::new(self.inner.meta()))))
}
}
pub struct ParseOptional<P> {
pub(crate) inner: P,
pub(crate) catch: bool,
}
impl<T, P> Parser<Option<T>> for ParseOptional<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<Option<T>, Error> {
let mut len = usize::MAX;
parse_option(&self.inner, &mut len, args, self.catch)
}
fn meta(&self) -> Meta {
Meta::Optional(Box::new(self.inner.meta()))
}
}
impl<P> ParseOptional<P> {
#[must_use]
#[cfg_attr(not(doctest), doc = include_str!("docs2/optional_catch.md"))]
pub fn catch(mut self) -> Self {
self.catch = true;
self
}
}
pub struct ParseMany<P> {
pub(crate) inner: P,
pub(crate) catch: bool,
}
impl<P> ParseMany<P> {
#[must_use]
#[cfg_attr(not(doctest), doc = include_str!("docs2/many_catch.md"))]
pub fn catch(mut self) -> Self {
self.catch = true;
self
}
}
fn parse_option<P, T>(
parser: &P,
len: &mut usize,
args: &mut State,
mut catch: bool,
) -> Result<Option<T>, Error>
where
P: Parser<T>,
{
let mut orig_args = args.clone();
match parser.eval(args) {
Ok(val) => Ok(if args.len() < *len {
*len = args.len();
Some(val)
} else {
None
}),
Err(Error(err)) => {
let missing = matches!(err, Message::Missing(_));
catch &= !err.wrong_input();
if catch || (missing && orig_args.len() == args.len()) || (!missing && err.can_catch())
{
std::mem::swap(&mut orig_args, args);
#[cfg(feature = "autocomplete")]
if orig_args.comp_mut().is_some() {
args.swap_comps(&mut orig_args);
}
Ok(None)
} else {
Err(Error(err))
}
}
}
}
impl<T, P> Parser<Vec<T>> for ParseMany<P>
where
P: Parser<T>,
{
fn eval(&self, args: &mut State) -> Result<Vec<T>, Error> {
let mut len = usize::MAX;
std::iter::from_fn(|| parse_option(&self.inner, &mut len, args, self.catch).transpose())
.collect::<Result<Vec<T>, Error>>()
}
fn meta(&self) -> Meta {
Meta::Many(Box::new(Meta::Optional(Box::new(self.inner.meta()))))
}
}
pub struct ParsePure<T>(pub(crate) T);
impl<T: Clone + 'static> Parser<T> for ParsePure<T> {
fn eval(&self, args: &mut State) -> Result<T, Error> {
args.current = None;
Ok(self.0.clone())
}
fn meta(&self) -> Meta {
Meta::Skip
}
}
pub struct ParsePureWith<T, F, E>(pub(crate) F)
where
F: Fn() -> Result<T, E>,
E: ToString;
impl<T: Clone + 'static, F: Fn() -> Result<T, E>, E: ToString> Parser<T>
for ParsePureWith<T, F, E>
{
fn eval(&self, _args: &mut State) -> Result<T, Error> {
match (self.0)() {
Ok(ok) => Ok(ok),
Err(e) => Err(Error(Message::PureFailed(e.to_string()))),
}
}
fn meta(&self) -> Meta {
Meta::Skip
}
}
pub struct ParseFail<T> {
pub(crate) field1: &'static str,
pub(crate) field2: PhantomData<T>,
}
impl<T> Parser<T> for ParseFail<T> {
fn eval(&self, args: &mut State) -> Result<T, Error> {
args.current = None;
Err(Error(Message::ParseFail(self.field1)))
}
fn meta(&self) -> Meta {
Meta::Skip
}
}
pub struct ParseMap<T, P, F, R> {
pub(crate) inner: P,
pub(crate) inner_res: PhantomData<T>,
pub(crate) map_fn: F,
pub(crate) res: PhantomData<R>,
}
impl<P, T, F, R> Parser<R> for ParseMap<T, P, F, R>
where
F: Fn(T) -> R,
P: Parser<T> + Sized,
{
fn eval(&self, args: &mut State) -> Result<R, Error> {
let t = self.inner.eval(args)?;
Ok((self.map_fn)(t))
}
fn meta(&self) -> Meta {
self.inner.meta()
}
}
pub struct ParseCon<P> {
pub inner: P,
pub meta: Meta,
pub failfast: bool,
}
impl<T, P> Parser<T> for ParseCon<P>
where
P: Fn(bool, &mut State) -> Result<T, Error>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let res = (self.inner)(self.failfast, args);
args.current = None;
res
}
fn meta(&self) -> Meta {
self.meta.clone()
}
}
impl<T> ParseCon<T> {
#[must_use]
#[cfg_attr(not(doctest), doc = include_str!("docs2/adjacent_struct_0.md"))]
#[cfg_attr(not(doctest), doc = include_str!("docs2/adjacent_struct_1.md"))]
#[cfg_attr(not(doctest), doc = include_str!("docs2/adjacent_command.md"))]
#[cfg_attr(not(doctest), doc = include_str!("docs2/adjacent_struct_3.md"))]
#[cfg_attr(not(doctest), doc = include_str!("docs2/adjacent_struct_4.md"))]
pub fn adjacent(mut self) -> ParseAdjacent<Self> {
self.failfast = true;
ParseAdjacent { inner: self }
}
}
#[cfg(feature = "autocomplete")]
pub struct ParseComp<P, F> {
pub(crate) inner: P,
pub(crate) op: F,
pub(crate) group: Option<String>,
}
#[cfg(feature = "autocomplete")]
impl<P, F> ParseComp<P, F> {
#[must_use]
pub fn group(mut self, group: impl Into<String>) -> Self {
self.group = Some(group.into());
self
}
}
#[cfg(feature = "autocomplete")]
impl<P, T, F, M> Parser<T> for ParseComp<P, F>
where
P: Parser<T> + Sized,
M: Into<String>,
F: Fn(&T) -> Vec<(M, Option<M>)>,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let mut comp_items = Vec::new();
args.swap_comps_with(&mut comp_items);
let res = self.inner.eval(args);
args.swap_comps_with(&mut comp_items);
if let Some(comp) = &mut args.comp_mut() {
if res.is_err() {
comp.extend_comps(comp_items);
return res;
}
}
let res = res?;
let depth = args.depth();
if let Some(comp) = &mut args.comp_mut() {
for ci in comp_items {
let is_meta = ci.is_metavar();
if let Some(is_arg) = is_meta {
let suggestions = (self.op)(&res);
if suggestions.len() != 1 {
comp.push_comp(ci);
}
for (replacement, description) in suggestions {
let group = self.group.clone();
comp.push_value(
replacement.into(),
description.map(Into::into),
group,
depth,
is_arg,
);
}
} else {
comp.push_comp(ci);
}
}
}
Ok(res)
}
fn meta(&self) -> Meta {
self.inner.meta()
}
}
pub struct ParseAdjacent<P> {
pub(crate) inner: P,
}
impl<P, T> Parser<T> for ParseAdjacent<P>
where
P: Parser<T> + Sized,
{
fn eval(&self, args: &mut State) -> Result<T, Error> {
let original_scope = args.scope();
let first_item;
let inner_meta = self.inner.meta();
let mut best_error = if let Some(item) = Meta::first_item(&inner_meta) {
first_item = item;
let missing_item = MissingItem {
item: item.clone(),
position: original_scope.start,
scope: original_scope.clone(),
};
Message::Missing(vec![missing_item])
} else {
unreachable!("bpaf usage BUG: adjacent should start with a required argument");
};
let mut best_args = args.clone();
let mut best_consumed = 0;
for (start, width, mut this_arg) in args.ranges(first_item) {
let mut scratch = this_arg.clone();
scratch.set_scope(start..start + width);
let before = scratch.len();
if before == 0 {
continue;
}
let _ = self.inner.eval(&mut scratch);
if before == scratch.len() {
continue;
}
this_arg.set_scope(start..original_scope.end);
let before = this_arg.len();
if original_scope.end - start > before {
this_arg.set_scope(this_arg.adjacently_available_from(start));
}
loop {
match self.inner.eval(&mut this_arg) {
Ok(res) => {
if let Some(adj_scope) = this_arg.adjacent_scope(args) {
this_arg = args.clone();
this_arg.set_scope(adj_scope);
} else {
std::mem::swap(args, &mut this_arg);
args.set_scope(original_scope);
return Ok(res);
}
}
Err(Error(err)) => {
let consumed = before - this_arg.len();
if consumed > best_consumed {
best_consumed = consumed;
std::mem::swap(&mut best_args, &mut this_arg);
best_error = err;
}
break;
}
}
}
}
std::mem::swap(args, &mut best_args);
Err(Error(best_error))
}
fn meta(&self) -> Meta {
let meta = self.inner.meta();
Meta::Adjacent(Box::new(meta))
}
}
impl<T> Parser<T> for Box<dyn Parser<T>> {
fn eval(&self, args: &mut State) -> Result<T, Error> {
self.as_ref().eval(args)
}
fn meta(&self) -> Meta {
self.as_ref().meta()
}
}