flaggy_values/value.rs
1// Copyright 2015 Axel Rasmussen
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::error::*;
16use std::collections::HashMap;
17use std::iter::FromIterator;
18use std::str::FromStr;
19
20/// A Value is the value associated with a given flag. The type of the value
21/// is different depending on the type of flag it is associated with.
22#[derive(Debug, Eq, PartialEq)]
23pub enum Value {
24 /// A single string value (perhaps a string which the user of this library
25 /// can then further interpret / parse as some other type).
26 Single(String),
27 /// A boolean value, from a flag defined as a boolean in its associated
28 /// spec. It is represented here as a string, *but* Values internally
29 /// enforces that all boolean strings must be successfully parseable.
30 Boolean(String),
31 /// A flag with repeated values. These should be treated the same as one
32 /// would a Single string value, except there are potentially zero or more
33 /// of them.
34 Repeated(Vec<String>),
35}
36
37/// Values is a structure which contains all of the parsed command-line flag
38/// values (or the default values for those flags). If parsing fails (including
39/// if some required flags weren't specified, for example), an error is
40/// returned.
41///
42/// This structure provides various accessor functions, to conveniently get at
43/// the flag values. These accessors tend to follow the pattern of assuming the
44/// caller is doing things correctly, and that the caller wants us to panic
45/// early if something goes wrong. If this is not the desired behavior, the
46/// Values::get accessor provides a safe API where the caller can do their own
47/// error handling.
48#[derive(Debug, Eq, PartialEq)]
49pub struct Values {
50 values: HashMap<String, Value>,
51}
52
53impl Values {
54 /// Construct a new Values structure using the given default values, and
55 /// the given values parsed from the program's command-line flags.
56 pub fn new(default_values: HashMap<String, Value>, mut values: HashMap<String, Value>) -> Self {
57 for (name, value) in default_values.into_iter() {
58 values.entry(name).or_insert(value);
59 }
60 Values { values: values }
61 }
62
63 /// Returns whether or not there exists a `Value` for the given flag.
64 pub fn contains_key(&self, name: &str) -> bool {
65 self.values.contains_key(name)
66 }
67
68 /// Return the Value(s) of a single flag, as strings. The returned vector
69 /// might be empty (if there is no Value associated with the flag), or it
70 /// might contain exactly one entry (in the case of named or boolean flags),
71 /// or it might contain many entries (in the case of positional flags).
72 pub fn get(&self, name: &str) -> Vec<&str> {
73 match self.values.get(name) {
74 None => Vec::new(),
75 Some(v) => match v {
76 Value::Single(v) => vec![v.as_str()],
77 Value::Boolean(v) => vec![v.as_str()],
78 Value::Repeated(vs) => vs.iter().map(|v| v.as_str()).collect(),
79 },
80 }
81 }
82
83 /// Return the Value(s) of a single flag, parsed into the given type. This
84 /// is a convenience wrapper around `get`.
85 pub fn get_as<E, T: FromStr<Err = E>>(&self, name: &str) -> ::std::result::Result<Vec<T>, E> {
86 self.get(name).iter().map(|v| v.parse::<T>()).collect()
87 }
88}
89
90impl From<HashMap<String, Value>> for Values {
91 fn from(values: HashMap<String, Value>) -> Self {
92 Values { values: values }
93 }
94}
95
96impl FromIterator<(String, Value)> for Values {
97 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
98 let values: HashMap<String, Value> = iter.into_iter().collect();
99 values.into()
100 }
101}
102
103/// Take a single required flag value from a list of values. Generally this
104/// should not be called directly, instead being used via #[command_callback].
105pub fn take_required<T>(mut vs: Vec<T>) -> ValueResult<T> {
106 match vs.len() {
107 0 => Err(ValueError::CallbackParameter(format!(
108 "expected one required value, found {}",
109 vs.len()
110 ))),
111 1 => Ok(vs.remove(0)),
112 _ => Err(ValueError::CallbackParameter(format!(
113 "expected one required value, found {}",
114 vs.len()
115 ))),
116 }
117}
118
119/// Take a single optional flag value from a list of values. Generally this
120/// should not be called directly, instead being used via #[command_callback].
121pub fn take_optional<T>(mut vs: Vec<T>) -> ValueResult<Option<T>> {
122 match vs.len() {
123 0 => Ok(None),
124 1 => Ok(Some(vs.remove(0))),
125 _ => Err(ValueError::CallbackParameter(format!(
126 "expected optional value, found {} values",
127 vs.len()
128 ))),
129 }
130}