diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/clap_builder/src/util | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/clap_builder/src/util')
-rw-r--r-- | vendor/clap_builder/src/util/any_value.rs | 127 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/color.rs | 116 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/flat_map.rs | 254 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/flat_set.rs | 107 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/graph.rs | 49 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/id.rs | 164 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/mod.rs | 47 | ||||
-rw-r--r-- | vendor/clap_builder/src/util/str_to_bool.rs | 21 |
8 files changed, 885 insertions, 0 deletions
diff --git a/vendor/clap_builder/src/util/any_value.rs b/vendor/clap_builder/src/util/any_value.rs new file mode 100644 index 0000000..19aa82b --- /dev/null +++ b/vendor/clap_builder/src/util/any_value.rs @@ -0,0 +1,127 @@ +#[derive(Clone)] +pub(crate) struct AnyValue { + inner: std::sync::Arc<dyn std::any::Any + Send + Sync + 'static>, + // While we can extract `TypeId` from `inner`, the debug repr is of a number, so let's track + // the type_name in debug builds. + id: AnyValueId, +} + +impl AnyValue { + pub(crate) fn new<V: std::any::Any + Clone + Send + Sync + 'static>(inner: V) -> Self { + let id = AnyValueId::of::<V>(); + let inner = std::sync::Arc::new(inner); + Self { inner, id } + } + + pub(crate) fn downcast_ref<T: std::any::Any + Clone + Send + Sync + 'static>( + &self, + ) -> Option<&T> { + self.inner.downcast_ref::<T>() + } + + pub(crate) fn downcast_into<T: std::any::Any + Clone + Send + Sync>(self) -> Result<T, Self> { + let id = self.id; + let value = + ok!(std::sync::Arc::downcast::<T>(self.inner).map_err(|inner| Self { inner, id })); + let value = std::sync::Arc::try_unwrap(value).unwrap_or_else(|arc| (*arc).clone()); + Ok(value) + } + + pub(crate) fn type_id(&self) -> AnyValueId { + self.id + } +} + +impl std::fmt::Debug for AnyValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + f.debug_struct("AnyValue").field("inner", &self.id).finish() + } +} + +#[derive(Copy, Clone)] +pub struct AnyValueId { + type_id: std::any::TypeId, + #[cfg(debug_assertions)] + type_name: &'static str, +} + +impl AnyValueId { + pub(crate) fn of<A: ?Sized + 'static>() -> Self { + Self { + type_id: std::any::TypeId::of::<A>(), + #[cfg(debug_assertions)] + type_name: std::any::type_name::<A>(), + } + } +} + +impl PartialEq for AnyValueId { + fn eq(&self, other: &Self) -> bool { + self.type_id == other.type_id + } +} + +impl Eq for AnyValueId {} + +impl PartialOrd for AnyValueId { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl PartialEq<std::any::TypeId> for AnyValueId { + fn eq(&self, other: &std::any::TypeId) -> bool { + self.type_id == *other + } +} + +impl Ord for AnyValueId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.type_id.cmp(&other.type_id) + } +} + +impl std::hash::Hash for AnyValueId { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.type_id.hash(state); + } +} + +impl std::fmt::Debug for AnyValueId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + #[cfg(not(debug_assertions))] + { + self.type_id.fmt(f) + } + #[cfg(debug_assertions)] + { + f.debug_struct(self.type_name).finish() + } + } +} + +impl<'a, A: ?Sized + 'static> From<&'a A> for AnyValueId { + fn from(_: &'a A) -> Self { + Self::of::<A>() + } +} + +#[cfg(test)] +mod test { + #[test] + #[cfg(debug_assertions)] + fn debug_impl() { + use super::*; + + assert_eq!(format!("{:?}", AnyValue::new(5)), "AnyValue { inner: i32 }"); + } + + #[test] + fn eq_to_type_id() { + use super::*; + + let any_value_id = AnyValueId::of::<i32>(); + let type_id = std::any::TypeId::of::<i32>(); + assert_eq!(any_value_id, type_id); + } +} diff --git a/vendor/clap_builder/src/util/color.rs b/vendor/clap_builder/src/util/color.rs new file mode 100644 index 0000000..d13a6df --- /dev/null +++ b/vendor/clap_builder/src/util/color.rs @@ -0,0 +1,116 @@ +use crate::builder::PossibleValue; +use crate::derive::ValueEnum; + +/// Represents the color preferences for program output +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum ColorChoice { + /// Enables colored output only when the output is going to a terminal or TTY. + /// + /// **NOTE:** This is the default behavior of `clap`. + /// + /// # Platform Specific + /// + /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms). + /// + /// # Examples + /// + /// ```rust + /// # #[cfg(feature = "color")] { + /// # use clap_builder as clap; + /// # use clap::{Command, ColorChoice}; + /// Command::new("myprog") + /// .color(ColorChoice::Auto) + /// .get_matches(); + /// # } + /// ``` + Auto, + + /// Enables colored output regardless of whether or not the output is going to a terminal/TTY. + /// + /// # Platform Specific + /// + /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms). + /// + /// # Examples + /// + /// ```rust + /// # #[cfg(feature = "color")] { + /// # use clap_builder as clap; + /// # use clap::{Command, ColorChoice}; + /// Command::new("myprog") + /// .color(ColorChoice::Always) + /// .get_matches(); + /// # } + /// ``` + Always, + + /// Disables colored output no matter if the output is going to a terminal/TTY, or not. + /// + /// # Platform Specific + /// + /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms) + /// + /// # Examples + /// + /// ```rust + /// # #[cfg(feature = "color")] { + /// # use clap_builder as clap; + /// # use clap::{Command, ColorChoice}; + /// Command::new("myprog") + /// .color(ColorChoice::Never) + /// .get_matches(); + /// # } + /// ``` + Never, +} + +impl ColorChoice { + /// Report all `possible_values` + pub fn possible_values() -> impl Iterator<Item = PossibleValue> { + Self::value_variants() + .iter() + .filter_map(ValueEnum::to_possible_value) + } +} + +impl Default for ColorChoice { + fn default() -> Self { + Self::Auto + } +} + +impl std::fmt::Display for ColorChoice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value() + .expect("no values are skipped") + .get_name() + .fmt(f) + } +} + +impl std::str::FromStr for ColorChoice { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + for variant in Self::value_variants() { + if variant.to_possible_value().unwrap().matches(s, false) { + return Ok(*variant); + } + } + Err(format!("invalid variant: {s}")) + } +} + +impl ValueEnum for ColorChoice { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Auto, Self::Always, Self::Never] + } + + fn to_possible_value(&self) -> Option<PossibleValue> { + Some(match self { + Self::Auto => PossibleValue::new("auto"), + Self::Always => PossibleValue::new("always"), + Self::Never => PossibleValue::new("never"), + }) + } +} diff --git a/vendor/clap_builder/src/util/flat_map.rs b/vendor/clap_builder/src/util/flat_map.rs new file mode 100644 index 0000000..468f0a9 --- /dev/null +++ b/vendor/clap_builder/src/util/flat_map.rs @@ -0,0 +1,254 @@ +#![allow(dead_code)] + +use std::borrow::Borrow; + +/// Flat (Vec) backed map +/// +/// This preserves insertion order +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct FlatMap<K, V> { + keys: Vec<K>, + values: Vec<V>, +} + +impl<K: PartialEq + Eq, V> FlatMap<K, V> { + pub(crate) fn new() -> Self { + Default::default() + } + + pub(crate) fn insert(&mut self, key: K, mut value: V) -> Option<V> { + for (index, existing) in self.keys.iter().enumerate() { + if *existing == key { + std::mem::swap(&mut self.values[index], &mut value); + return Some(value); + } + } + + self.insert_unchecked(key, value); + None + } + + pub(crate) fn insert_unchecked(&mut self, key: K, value: V) { + self.keys.push(key); + self.values.push(value); + } + + pub(crate) fn extend_unchecked(&mut self, iter: impl IntoIterator<Item = (K, V)>) { + for (key, value) in iter { + self.insert_unchecked(key, value); + } + } + + pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: Eq, + { + for existing in &self.keys { + if existing.borrow() == key { + return true; + } + } + false + } + + pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> + where + K: Borrow<Q>, + Q: std::hash::Hash + Eq, + { + self.remove_entry(key).map(|(_, v)| v) + } + + pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: std::hash::Hash + Eq, + { + let index = some!(self + .keys + .iter() + .enumerate() + .find_map(|(i, k)| (k.borrow() == key).then_some(i))); + let key = self.keys.remove(index); + let value = self.values.remove(index); + Some((key, value)) + } + + pub(crate) fn is_empty(&self) -> bool { + self.keys.is_empty() + } + + pub fn entry(&mut self, key: K) -> Entry<K, V> { + for (index, existing) in self.keys.iter().enumerate() { + if *existing == key { + return Entry::Occupied(OccupiedEntry { v: self, index }); + } + } + Entry::Vacant(VacantEntry { v: self, key }) + } + + pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: Eq, + { + for (index, existing) in self.keys.iter().enumerate() { + if existing.borrow() == k { + return Some(&self.values[index]); + } + } + None + } + + pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow<Q>, + Q: Eq, + { + for (index, existing) in self.keys.iter().enumerate() { + if existing.borrow() == k { + return Some(&mut self.values[index]); + } + } + None + } + + pub fn keys(&self) -> std::slice::Iter<'_, K> { + self.keys.iter() + } + + pub fn iter(&self) -> Iter<K, V> { + Iter { + keys: self.keys.iter(), + values: self.values.iter(), + } + } + + pub fn iter_mut(&mut self) -> IterMut<K, V> { + IterMut { + keys: self.keys.iter_mut(), + values: self.values.iter_mut(), + } + } +} + +impl<K: PartialEq + Eq, V> Default for FlatMap<K, V> { + fn default() -> Self { + Self { + keys: Default::default(), + values: Default::default(), + } + } +} + +pub enum Entry<'a, K: 'a, V: 'a> { + Vacant(VacantEntry<'a, K, V>), + Occupied(OccupiedEntry<'a, K, V>), +} + +impl<'a, K: 'a, V: 'a> Entry<'a, K, V> { + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Entry::Occupied(entry) => &mut entry.v.values[entry.index], + Entry::Vacant(entry) => { + entry.v.keys.push(entry.key); + entry.v.values.push(default); + entry.v.values.last_mut().unwrap() + } + } + } + + pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V { + match self { + Entry::Occupied(entry) => &mut entry.v.values[entry.index], + Entry::Vacant(entry) => { + entry.v.keys.push(entry.key); + entry.v.values.push(default()); + entry.v.values.last_mut().unwrap() + } + } + } +} + +pub struct VacantEntry<'a, K: 'a, V: 'a> { + v: &'a mut FlatMap<K, V>, + key: K, +} + +pub struct OccupiedEntry<'a, K: 'a, V: 'a> { + v: &'a mut FlatMap<K, V>, + index: usize, +} + +pub struct Iter<'a, K: 'a, V: 'a> { + keys: std::slice::Iter<'a, K>, + values: std::slice::Iter<'a, V>, +} + +impl<'a, K, V> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + match self.keys.next() { + Some(k) => { + let v = self.values.next().unwrap(); + Some((k, v)) + } + None => None, + } + } + fn size_hint(&self) -> (usize, Option<usize>) { + self.keys.size_hint() + } +} + +impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a V)> { + match self.keys.next_back() { + Some(k) => { + let v = self.values.next_back().unwrap(); + Some((k, v)) + } + None => None, + } + } +} + +impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {} + +pub struct IterMut<'a, K: 'a, V: 'a> { + keys: std::slice::IterMut<'a, K>, + values: std::slice::IterMut<'a, V>, +} + +impl<'a, K, V> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + match self.keys.next() { + Some(k) => { + let v = self.values.next().unwrap(); + Some((k, v)) + } + None => None, + } + } + fn size_hint(&self) -> (usize, Option<usize>) { + self.keys.size_hint() + } +} + +impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { + match self.keys.next_back() { + Some(k) => { + let v = self.values.next_back().unwrap(); + Some((k, v)) + } + None => None, + } + } +} + +impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {} diff --git a/vendor/clap_builder/src/util/flat_set.rs b/vendor/clap_builder/src/util/flat_set.rs new file mode 100644 index 0000000..3e0b23d --- /dev/null +++ b/vendor/clap_builder/src/util/flat_set.rs @@ -0,0 +1,107 @@ +#![allow(dead_code)] + +use std::borrow::Borrow; + +/// Flat (Vec) backed set +/// +/// This preserves insertion order +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct FlatSet<T> { + inner: Vec<T>, +} + +impl<T: PartialEq + Eq> FlatSet<T> { + pub(crate) fn new() -> Self { + Default::default() + } + + pub(crate) fn insert(&mut self, value: T) -> bool { + for existing in &self.inner { + if *existing == value { + return false; + } + } + self.inner.push(value); + true + } + + pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: Eq, + { + for existing in &self.inner { + if existing.borrow() == value { + return true; + } + } + false + } + + pub fn retain<F>(&mut self, f: F) + where + F: FnMut(&T) -> bool, + { + self.inner.retain(f); + } + + pub(crate) fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + pub(crate) fn iter(&self) -> std::slice::Iter<'_, T> { + self.inner.iter() + } + + pub fn sort_by_key<K, F>(&mut self, f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + self.inner.sort_by_key(f); + } +} + +impl<T: PartialEq + Eq> Default for FlatSet<T> { + fn default() -> Self { + Self { + inner: Default::default(), + } + } +} + +impl<T: PartialEq + Eq> IntoIterator for FlatSet<T> { + type Item = T; + type IntoIter = std::vec::IntoIter<T>; + + fn into_iter(self) -> Self::IntoIter { + self.inner.into_iter() + } +} + +impl<'s, T: PartialEq + Eq> IntoIterator for &'s FlatSet<T> { + type Item = &'s T; + type IntoIter = std::slice::Iter<'s, T>; + + fn into_iter(self) -> Self::IntoIter { + self.inner.iter() + } +} + +impl<T: PartialEq + Eq> Extend<T> for FlatSet<T> { + fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { + for value in iter { + self.insert(value); + } + } +} + +impl<T: PartialEq + Eq> FromIterator<T> for FlatSet<T> { + fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { + let mut set = Self::new(); + for value in iter { + set.insert(value); + } + set + } +} diff --git a/vendor/clap_builder/src/util/graph.rs b/vendor/clap_builder/src/util/graph.rs new file mode 100644 index 0000000..d646400 --- /dev/null +++ b/vendor/clap_builder/src/util/graph.rs @@ -0,0 +1,49 @@ +#[derive(Debug)] +struct Child<T> { + id: T, + children: Vec<usize>, +} + +impl<T> Child<T> { + fn new(id: T) -> Self { + Child { + id, + children: vec![], + } + } +} + +#[derive(Debug)] +pub(crate) struct ChildGraph<T>(Vec<Child<T>>); + +impl<T> ChildGraph<T> +where + T: Sized + PartialEq + Clone, +{ + pub(crate) fn with_capacity(s: usize) -> Self { + ChildGraph(Vec::with_capacity(s)) + } + + pub(crate) fn insert(&mut self, req: T) -> usize { + self.0.iter().position(|e| e.id == req).unwrap_or_else(|| { + let idx = self.0.len(); + self.0.push(Child::new(req)); + idx + }) + } + + pub(crate) fn insert_child(&mut self, parent: usize, child: T) -> usize { + let c_idx = self.0.len(); + self.0.push(Child::new(child)); + self.0[parent].children.push(c_idx); + c_idx + } + + pub(crate) fn iter(&self) -> impl Iterator<Item = &T> { + self.0.iter().map(|r| &r.id) + } + + pub(crate) fn contains(&self, req: &T) -> bool { + self.0.iter().any(|r| r.id == *req) + } +} diff --git a/vendor/clap_builder/src/util/id.rs b/vendor/clap_builder/src/util/id.rs new file mode 100644 index 0000000..710d2ea --- /dev/null +++ b/vendor/clap_builder/src/util/id.rs @@ -0,0 +1,164 @@ +use crate::builder::Str; + +/// [`Arg`][crate::Arg] or [`ArgGroup`][crate::ArgGroup] identifier +/// +/// This is used for accessing the value in [`ArgMatches`][crate::ArgMatches] or defining +/// relationships between `Arg`s and `ArgGroup`s with functions like +/// [`Arg::conflicts_with`][crate::Arg::conflicts_with]. +#[derive(Default, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub struct Id(Str); + +impl Id { + pub(crate) const HELP: &'static str = "help"; + pub(crate) const VERSION: &'static str = "version"; + pub(crate) const EXTERNAL: &'static str = ""; + + pub(crate) fn from_static_ref(name: &'static str) -> Self { + Self(Str::from_static_ref(name)) + } + + /// Get the raw string of the `Id` + pub fn as_str(&self) -> &str { + self.0.as_str() + } + + pub(crate) fn as_internal_str(&self) -> &Str { + &self.0 + } +} + +impl From<&'_ Id> for Id { + fn from(id: &'_ Id) -> Self { + id.clone() + } +} + +impl From<Str> for Id { + fn from(name: Str) -> Self { + Self(name) + } +} + +impl From<&'_ Str> for Id { + fn from(name: &'_ Str) -> Self { + Self(name.into()) + } +} + +#[cfg(feature = "string")] +impl From<std::string::String> for Id { + fn from(name: std::string::String) -> Self { + Self(name.into()) + } +} + +#[cfg(feature = "string")] +impl From<&'_ std::string::String> for Id { + fn from(name: &'_ std::string::String) -> Self { + Self(name.into()) + } +} + +impl From<&'static str> for Id { + fn from(name: &'static str) -> Self { + Self(name.into()) + } +} + +impl From<&'_ &'static str> for Id { + fn from(name: &'_ &'static str) -> Self { + Self(name.into()) + } +} + +impl From<Id> for Str { + fn from(name: Id) -> Self { + name.0 + } +} + +impl From<Id> for String { + fn from(name: Id) -> Self { + Str::from(name).into() + } +} + +impl std::fmt::Display for Id { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.as_str(), f) + } +} + +impl std::fmt::Debug for Id { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Debug::fmt(self.as_str(), f) + } +} + +impl AsRef<str> for Id { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl std::borrow::Borrow<str> for Id { + #[inline] + fn borrow(&self) -> &str { + self.as_str() + } +} + +impl PartialEq<str> for Id { + #[inline] + fn eq(&self, other: &str) -> bool { + PartialEq::eq(self.as_str(), other) + } +} +impl PartialEq<Id> for str { + #[inline] + fn eq(&self, other: &Id) -> bool { + PartialEq::eq(self, other.as_str()) + } +} + +impl PartialEq<&'_ str> for Id { + #[inline] + fn eq(&self, other: &&str) -> bool { + PartialEq::eq(self.as_str(), *other) + } +} +impl PartialEq<Id> for &'_ str { + #[inline] + fn eq(&self, other: &Id) -> bool { + PartialEq::eq(*self, other.as_str()) + } +} + +impl PartialEq<Str> for Id { + #[inline] + fn eq(&self, other: &Str) -> bool { + PartialEq::eq(self.as_str(), other.as_str()) + } +} +impl PartialEq<Id> for Str { + #[inline] + fn eq(&self, other: &Id) -> bool { + PartialEq::eq(self.as_str(), other.as_str()) + } +} + +impl PartialEq<std::string::String> for Id { + #[inline] + fn eq(&self, other: &std::string::String) -> bool { + PartialEq::eq(self.as_str(), other.as_str()) + } +} +impl PartialEq<Id> for std::string::String { + #[inline] + fn eq(&self, other: &Id) -> bool { + PartialEq::eq(other, self) + } +} diff --git a/vendor/clap_builder/src/util/mod.rs b/vendor/clap_builder/src/util/mod.rs new file mode 100644 index 0000000..a92aef8 --- /dev/null +++ b/vendor/clap_builder/src/util/mod.rs @@ -0,0 +1,47 @@ +#![allow(clippy::single_component_path_imports)] + +mod any_value; +pub(crate) mod flat_map; +pub(crate) mod flat_set; +mod graph; +mod id; +mod str_to_bool; + +pub use self::id::Id; + +pub(crate) use self::any_value::AnyValue; +pub(crate) use self::any_value::AnyValueId; +pub(crate) use self::flat_map::Entry; +pub(crate) use self::flat_map::FlatMap; +pub(crate) use self::flat_set::FlatSet; +pub(crate) use self::graph::ChildGraph; +pub(crate) use self::str_to_bool::str_to_bool; +pub(crate) use self::str_to_bool::FALSE_LITERALS; +pub(crate) use self::str_to_bool::TRUE_LITERALS; + +pub(crate) mod color; + +pub(crate) const SUCCESS_CODE: i32 = 0; +// While sysexists.h defines EX_USAGE as 64, this doesn't seem to be used much in practice but +// instead 2 seems to be frequently used. +// Examples +// - GNU `ls` returns 2 +// - Python's `argparse` returns 2 +pub(crate) const USAGE_CODE: i32 = 2; + +pub(crate) fn safe_exit(code: i32) -> ! { + use std::io::Write; + + let _ = std::io::stdout().lock().flush(); + let _ = std::io::stderr().lock().flush(); + + std::process::exit(code) +} + +#[cfg(not(feature = "unicode"))] +pub(crate) fn eq_ignore_case(left: &str, right: &str) -> bool { + left.eq_ignore_ascii_case(right) +} + +#[cfg(feature = "unicode")] +pub(crate) use unicase::eq as eq_ignore_case; diff --git a/vendor/clap_builder/src/util/str_to_bool.rs b/vendor/clap_builder/src/util/str_to_bool.rs new file mode 100644 index 0000000..1fbdc75 --- /dev/null +++ b/vendor/clap_builder/src/util/str_to_bool.rs @@ -0,0 +1,21 @@ +/// True values are `y`, `yes`, `t`, `true`, `on`, and `1`. +pub(crate) const TRUE_LITERALS: [&str; 6] = ["y", "yes", "t", "true", "on", "1"]; + +/// False values are `n`, `no`, `f`, `false`, `off`, and `0`. +pub(crate) const FALSE_LITERALS: [&str; 6] = ["n", "no", "f", "false", "off", "0"]; + +/// Converts a string literal representation of truth to true or false. +/// +/// `false` values are `n`, `no`, `f`, `false`, `off`, and `0` (case insensitive). +/// +/// Any other value will be considered as `true`. +pub(crate) fn str_to_bool(val: impl AsRef<str>) -> Option<bool> { + let pat: &str = &val.as_ref().to_lowercase(); + if TRUE_LITERALS.contains(&pat) { + Some(true) + } else if FALSE_LITERALS.contains(&pat) { + Some(false) + } else { + None + } +} |