From dc833a24edb2fe9d22a807ccc5839edb177d9a20 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Wed, 5 Nov 2025 07:32:32 +1100 Subject: [PATCH] Move base BTreeMap API to alloc-only --- jaarg/Cargo.toml | 3 ++- jaarg/examples/btreemap.rs | 5 +++-- jaarg/src/alloc.rs | 40 +++++++++++++++++++++++++++++++++++ jaarg/src/lib.rs | 2 ++ jaarg/src/std.rs | 43 +++++++------------------------------- 5 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 jaarg/src/alloc.rs diff --git a/jaarg/Cargo.toml b/jaarg/Cargo.toml index cfbd249..1905207 100644 --- a/jaarg/Cargo.toml +++ b/jaarg/Cargo.toml @@ -9,4 +9,5 @@ authors.workspace = true [features] default = ["std"] -std = [] +alloc = [] +std = ["alloc"] diff --git a/jaarg/examples/btreemap.rs b/jaarg/examples/btreemap.rs index a08da4a..18b4bf3 100644 --- a/jaarg/examples/btreemap.rs +++ b/jaarg/examples/btreemap.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MIT */ -use jaarg::{std::ParseMapResult, Opt, Opts}; +use jaarg::{alloc::ParseMapResult, Opt, Opts}; use std::process::ExitCode; fn main() -> ExitCode { @@ -16,7 +16,8 @@ fn main() -> ExitCode { let map = match OPTIONS.parse_map_easy() { ParseMapResult::Map(map) => map, - ParseMapResult::Exit(code) => { return code; } + ParseMapResult::ExitSuccess => { return ExitCode::SUCCESS; } + ParseMapResult::ExitFailure => { return ExitCode::FAILURE; } }; println!("{:?}", map); diff --git a/jaarg/src/alloc.rs b/jaarg/src/alloc.rs new file mode 100644 index 0000000..75ae8c4 --- /dev/null +++ b/jaarg/src/alloc.rs @@ -0,0 +1,40 @@ +/* jaarg - Argument parser + * SPDX-FileCopyrightText: (C) 2025 Gay Pizza Specifications + * SPDX-License-Identifier: MIT + */ + +extern crate alloc; + +use alloc::collections::BTreeMap; +use alloc::string::String; +use crate::{Opts, ParseControl, ParseError, ParseResult}; + +impl Opts<&'static str> { + /// Parse an iterator of strings as arguments and return the results in a [`BTreeMap`]. + /// + /// Requires `features = ["alloc"]`. + pub fn parse_map<'a, S: AsRef + 'a, I: Iterator>(&self, program_name: &str, args: I, + help: impl Fn(&str), error: impl FnOnce(&str, ParseError) + ) -> ParseMapResult { + let mut out: BTreeMap<&'static str, String> = BTreeMap::new(); + match self.parse(&program_name, args, |_program_name, id, opt, _name, arg| { + if opt.is_help() { + help(program_name); + Ok(ParseControl::Quit) + } else { + out.insert(id, arg.into()); + Ok(ParseControl::Continue) + } + }, error) { + ParseResult::ContinueSuccess => ParseMapResult::Map(out), + ParseResult::ExitSuccess => ParseMapResult::ExitSuccess, + ParseResult::ExitError => ParseMapResult::ExitFailure, + } + } +} + +/// The result of parsing commands with [Opts::parse_map]. +pub enum ParseMapResult { + Map(BTreeMap<&'static str, String>), + ExitSuccess, ExitFailure +} diff --git a/jaarg/src/lib.rs b/jaarg/src/lib.rs index 42c15a7..2e5cd72 100644 --- a/jaarg/src/lib.rs +++ b/jaarg/src/lib.rs @@ -13,5 +13,7 @@ include!("options.rs"); include!("argparse.rs"); include!("help.rs"); +#[cfg(feature = "alloc")] +pub mod alloc; #[cfg(feature = "std")] pub mod std; diff --git a/jaarg/src/std.rs b/jaarg/src/std.rs index 28026f7..75cc5c3 100644 --- a/jaarg/src/std.rs +++ b/jaarg/src/std.rs @@ -5,18 +5,17 @@ extern crate std; +use crate::alloc::ParseMapResult; use crate::{HandlerResult, HelpWriter, HelpWriterContext, Opt, Opts, ParseControl, ParseError, ParseResult, StandardFullHelpWriter, StandardShortUsageWriter}; -use std::collections::BTreeMap; use std::path::Path; use std::rc::Rc; -use std::string::String; use std::{env, eprintln, println}; impl Opts { /// Wrapper around [Opts::parse] that gathers arguments from the command line and prints errors to stderr. /// The errors are formatted in a standard user-friendly format. /// - /// Requires `features = [std]`. + /// Requires `features = ["std"]`. pub fn parse_easy<'a>(&self, handler: impl FnMut(&str, &ID, &Opt, &str, &str) -> HandlerResult<'a, ParseControl> ) -> ParseResult { let (program_name, argv) = Self::easy_args(); @@ -25,14 +24,14 @@ impl Opts { /// Prints full help text for the options using the standard full. /// - /// Requires `features = [std]`. + /// Requires `features = ["std"]`. pub fn print_full_help(&self, program_name: &str) { self.print_help::>(program_name); } /// Print help text to stdout using the provided help writer. /// - /// Requires `features = [std]`. + /// Requires `features = ["std"]`. pub fn print_help<'a, W: HelpWriter<'a, ID>>(&'a self, program_name: &'a str) { let ctx = HelpWriterContext { options: self, program_name }; println!("{}", W::new(ctx)); @@ -40,7 +39,7 @@ impl Opts { /// Print help text to stderr using the provided help writer. /// - /// Requires `features = [std]`. + /// Requires `features = ["std"]`. pub fn eprint_help<'a, W: HelpWriter<'a, ID>>(&'a self, program_name: &'a str) { let ctx = HelpWriterContext { options: self, program_name }; eprintln!("{}", W::new(ctx)); @@ -63,39 +62,11 @@ impl Opts { } } -/// The result of parsing commands with [Opts::parse_map]. -pub enum ParseMapResult { - Map(BTreeMap<&'static str, String>), - Exit(std::process::ExitCode), -} - impl Opts<&'static str> { - /// Parse an iterator of strings as arguments and return the results in a [BTreeMap]. - /// - /// Requires `features = [std]`. - pub fn parse_map<'a, S: AsRef + 'a, I: Iterator>(&self, program_name: &str, args: I, - help: impl Fn(&str), error: impl FnOnce(&str, ParseError) - ) -> ParseMapResult { - let mut out: BTreeMap<&'static str, String> = BTreeMap::new(); - match self.parse(&program_name, args, |_program_name, id, opt, _name, arg| { - if opt.is_help() { - help(program_name); - Ok(ParseControl::Quit) - } else { - out.insert(id, arg.into()); - Ok(ParseControl::Continue) - } - }, error) { - ParseResult::ContinueSuccess => ParseMapResult::Map(out), - ParseResult::ExitSuccess => ParseMapResult::Exit(std::process::ExitCode::SUCCESS), - ParseResult::ExitError => ParseMapResult::Exit(std::process::ExitCode::FAILURE), - } - } - - /// Parse arguments from the command line and return the results in a [BTreeMap]. + /// Parse arguments from the command line and return the results in a [`alloc::collections::BTreeMap`]. /// Help and errors are formatted in a standard user-friendly format. /// - /// Requires `features = [std]`. + /// Requires `features = ["std"]`. pub fn parse_map_easy(&self) -> ParseMapResult { let (program_name, argv) = Self::easy_args(); self.parse_map(&program_name, argv,