args: very early arg parse data structure draft

master
Avril 3 years ago
parent 9a346f4d0c
commit 9ecb74d896
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1,139 @@
use super::*;
/// A trait used to validate atoms in the `uv` module to valid ones in this module.
trait Validate: Sized
{
type Valid: Into<Inner>;
type Error: Into<eyre::Report> = eyre::Report;
/// Consume into the strongly validated type.
fn valiate(self) -> Result<Self::Valid, Self::Error>;
/// Weakly validate that this instance itself is correct.
fn self_validate(&self) -> Result<(), Self::Error>;
}
/// Non-validated inputs which get mapped to the validated ones in the parent module.
mod uv {
use crate::*;
use super::Validate;
#[derive(Debug, Clone)]
pub struct ExecTaskAtom
{
prog: Option<String>,
args: Option<Vec<String>>,
//TODO: ...
takes_tail: Option<super::TailKind>,
}
impl Validate for ExecTaskAtom
{
type Valid = super::ExecTaskAtom;
fn valiate(self) -> Result<Self::Valid, Self::Error>
{
todo!()
}
fn self_validate(&self) -> Result<(), Self::Error>
{
todo!()
}
}
pub enum Either
{
Exec(ExecTaskAtom),
Shell(!), //TODO
}
//TODO: impl Validate for Either, or something
/// Validate an atom from this module into `Inner`.
pub(super) fn validate<T>(inv: T) -> eyre::Result<super::Inner>
where T: Validate
{
Ok(inv.valiate().map_err(Into::into)
.wrap_err(eyre!("Failed to validate atom"))
.with_section(|| std::any::type_name::<T>().header("Type name was"))
.with_section(|| std::any::type_name::<T::Valid>().header("Validating for"))?.into())
}
}
/// Options for a normal execution atom
struct ExecTaskAtom
{
prog: String,
args: Vec<String>,
//TODO: ...
takes_tail: TailKind,
}
enum Inner
{
Exec(ExecTaskAtom),
Shell(!), //TODO
}
impl From<ExecTaskAtom> for Inner
{
#[inline] fn from(from: ExecTaskAtom) -> Self
{
Self::Exec(from)
}
}
#[derive(Debug, Clone, Copy)]
pub enum TailKind
{
/// No tail parsing
Contained,
/// Parse rest of arguments
Rest(TailField),
/// Parse concurrently from stdin
Stdin(TailField),
}
impl Default for TailKind
{
#[inline]
fn default() -> Self
{
Self::Contained
}
}
#[derive(Debug, Clone, Copy)]
pub enum TailField
{
//TODO: All possible tail fields for all exec atom types. Validating they are used for the correct atom type will be done in `uv`'s validate step.
}
/// The defaults specified for execution types
pub struct TaskDefault(Box<(uv::ExecTaskAtom, ! /* TODO: ShellTaskAtom */)>);
/// A task atom is task-specific execution directives.
///
/// An atom can inherit from a `TaskDefault`.
pub struct TaskAtom(Box<Inner>); //TODO: how tf are we going to signal tail feeding? Do we just tag which field it is and let the program figure out how to handle it? I think that might be best, esp. for stdin for which reading happens concurrently.
impl TaskAtom
{
fn inherit(default: &TaskDefault, from: uv::Either) -> eyre::Result<Self>
{
//TODO: Clone default.0.<n>, replacing the *set* (not `None`) fields set in `from` then validate it into `Self`
todo!()
}
/// Does this atom take tail parsing? And if so, which field?
pub fn tail(&self) -> &TailKind
{
match self.0.as_ref() {
Inner::Exec(e) => &e.takes_tail,
_ => todo!()
}
}
}

@ -3,6 +3,7 @@ use super::*;
use std::fmt;
mod usage;
mod data;
/// The name of the process that was invoked
#[inline] pub fn prog_name() -> &'static str

@ -1,3 +1,6 @@
#![cfg_attr(nightly, feature(never_type))]
#![cfg_attr(nightly, feature(associated_type_defaults))]
#![allow(dead_code)]
#[macro_use] extern crate log;
@ -15,6 +18,7 @@ use color_eyre::{
WrapErr as _,
},
SectionExt as _,
Help as _,
};
mod ext;

Loading…
Cancel
Save