This repository has been archived on 2023-07-03. You can view files and clone it, but cannot push or open issues or pull requests.
spd/src/env/mod.rs

158 lines
5.0 KiB
Rust

/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* This file is part of SPD.
*
* SPD is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* SPD is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SPD. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and permission
* notice:
*
* Copyright 2017 Douman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#![no_std]
#![warn(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::needless_lifetimes))]
use core::fmt;
mod derive;
mod split;
use derive::*;
use split::Split;
#[derive(PartialEq, Eq, Debug)]
///Parse errors
pub enum ParseKind<'a> {
///Main command result
Top(ParseError<'a>),
///Sub-command name and result
Sub(&'static str, ParseError<'a>),
}
impl<'a> ParseKind<'a> {
#[inline]
///Returns whether help is requested
pub fn is_help(&self) -> bool {
match self {
Self::Top(err) => err.is_help(),
Self::Sub(_, err) => err.is_help(),
}
}
}
impl<'a> PartialEq<ParseError<'a>> for ParseKind<'a> {
#[inline(always)]
fn eq(&self, right: &ParseError<'a>) -> bool {
match self {
Self::Top(left) => PartialEq::eq(left, right),
Self::Sub(_, left) => PartialEq::eq(left, right),
}
}
}
#[derive(PartialEq, Eq, Debug)]
///Parse errors
pub enum ParseError<'a> {
///User requested help.
///
///Contains slice with `Args::HELP`
HelpRequested(&'static str),
///Too many arguments are specified.
TooManyArgs,
///Argument is required, but missing
///
///Contains name of argument
RequiredArgMissing(&'a str),
///Flag is specified, but value is missing.
///
///Contains full flag name.
MissingValue(&'a str),
///Flag is specified with invalid value
///
///Contains full flag name and provided value.
InvalidFlagValue(&'a str, &'a str),
///Argument is supplied with invalid vlaue
///
///Contains argument name and provided value.
InvalidArgValue(&'a str, &'a str),
///Unknown flag is specified.
UnknownFlag(&'a str)
}
impl<'a> ParseError<'a> {
///Returns whether help is requested
pub fn is_help(&self) -> bool {
match self {
ParseError::HelpRequested(_) => true,
_ => false,
}
}
}
impl<'a> fmt::Display for ParseError<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseError::HelpRequested(help) => f.write_str(help),
ParseError::TooManyArgs => f.write_str("Too many arguments are provided"),
ParseError::RequiredArgMissing(arg) => write!(f, "Argument '{}' is required, but not provided", arg),
ParseError::MissingValue(arg) => write!(f, "Flag '{}' is provided without value", arg),
ParseError::InvalidFlagValue(arg, value) => write!(f, "Flag '{}' is provided with '{}' which is invalid", arg, value),
ParseError::InvalidArgValue(arg, value) => write!(f, "Argument '{}' is provided with '{}' which is invalid", arg, value),
ParseError::UnknownFlag(flag) => write!(f, "Unknown flag '{}' is provided", flag),
}
}
}
impl<'a> fmt::Display for ParseKind<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseKind::Top(res) => fmt::Display::fmt(res, f),
ParseKind::Sub(name, res) => write!(f, "{name}: {res}"),
}
}
}
///Describers command line argument parser
pub trait Args: Sized {
///Help message for parser.
const HELP: &'static str;
///Parses arguments from iterator of strings
fn from_args<'a, T: IntoIterator<Item = &'a str>>(args: T) -> Result<Self, ParseKind<'a>>;
///Parses arguments from string, which gets tokenized and passed to from.
fn from_text<'a>(text: &'a str) -> Result<Self, ParseKind<'a>> {
Self::from_args(Split::from_str(text))
}
}