85 lines
2.1 KiB
Rust
85 lines
2.1 KiB
Rust
use std::str::FromStr;
|
|
|
|
use crate::ast::{ParseErrorKind, ParseResult, Value, ValueKind};
|
|
use crate::source::WithSource;
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct Args(Vec<Arg>);
|
|
|
|
impl Args {
|
|
pub fn new() -> Self {
|
|
Self(Vec::new())
|
|
}
|
|
|
|
pub fn contains(&mut self, name: &str) -> bool {
|
|
self.0.iter().find(|arg| arg.name.inner == name).is_some()
|
|
}
|
|
|
|
pub fn get(&mut self, name: &str) -> Option<Arg> {
|
|
let idx = self.0.iter().position(|old| old.name.inner == name);
|
|
idx.map(|idx| self.0.remove(idx))
|
|
}
|
|
|
|
pub fn insert(&mut self, arg: Arg) -> Option<Arg> {
|
|
let existing = self
|
|
.0
|
|
.iter()
|
|
.position(|old| old.name.inner == arg.name.inner);
|
|
self.0.push(arg);
|
|
existing.map(|idx| self.0.remove(idx))
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Arg {
|
|
pub name: WithSource<String>,
|
|
pub val: Value,
|
|
}
|
|
|
|
pub trait ParseArgs: Sized {
|
|
fn parse_args(args: &mut Args) -> ParseResult<Self>;
|
|
}
|
|
|
|
pub trait ParseValue: Sized {
|
|
fn parse_value(val: &Value) -> ParseResult<Self>;
|
|
}
|
|
|
|
pub trait ParseScoped: Sized {
|
|
type Default;
|
|
fn parse_scoped(args: &mut Args, scope: &str, default: Self::Default) -> ParseResult<Self>;
|
|
}
|
|
|
|
impl ParseValue for usize {
|
|
fn parse_value(val: &Value) -> ParseResult<Self> {
|
|
match val.inner {
|
|
ValueKind::Number(num) => Ok(num as Self),
|
|
_ => Err(val.map(ParseErrorKind::InvalidValue)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: ParseValue> ParseValue for Option<T> {
|
|
fn parse_value(val: &Value) -> ParseResult<Self> {
|
|
if let ValueKind::Symbol(symbol) = &val.inner {
|
|
if symbol.to_lowercase() == "none" {
|
|
return Ok(None);
|
|
}
|
|
}
|
|
|
|
T::parse_value(val).map(|t| Some(t))
|
|
}
|
|
}
|
|
|
|
pub(crate) trait ParseSymbol: FromStr {}
|
|
|
|
impl<T: ParseSymbol> ParseValue for T {
|
|
fn parse_value(val: &Value) -> ParseResult<Self> {
|
|
match &val.inner {
|
|
ValueKind::Symbol(symbol) => {
|
|
T::from_str(&symbol).map_err(|_| val.map(ParseErrorKind::InvalidValue))
|
|
}
|
|
_ => Err(val.map(ParseErrorKind::InvalidValue)),
|
|
}
|
|
}
|
|
}
|