summaryrefslogtreecommitdiffstats
path: root/third_party/rust/clap/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/clap/src/util')
-rw-r--r--third_party/rust/clap/src/util/color.rs62
-rw-r--r--third_party/rust/clap/src/util/fnv.rs46
-rw-r--r--third_party/rust/clap/src/util/graph.rs49
-rw-r--r--third_party/rust/clap/src/util/id.rs92
-rw-r--r--third_party/rust/clap/src/util/mod.rs40
-rw-r--r--third_party/rust/clap/src/util/str_to_bool.rs15
6 files changed, 304 insertions, 0 deletions
diff --git a/third_party/rust/clap/src/util/color.rs b/third_party/rust/clap/src/util/color.rs
new file mode 100644
index 0000000000..15c9901a07
--- /dev/null
+++ b/third_party/rust/clap/src/util/color.rs
@@ -0,0 +1,62 @@
+/// 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
+ ///
+ #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
+ #[cfg_attr(feature = "color", doc = " ```no_run")]
+ /// # 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
+ ///
+ #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
+ #[cfg_attr(feature = "color", doc = " ```no_run")]
+ /// # 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
+ ///
+ #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
+ #[cfg_attr(feature = "color", doc = " ```no_run")]
+ /// # use clap::{Command, ColorChoice};
+ /// Command::new("myprog")
+ /// .color(ColorChoice::Never)
+ /// .get_matches();
+ /// ```
+ Never,
+}
+
+impl Default for ColorChoice {
+ fn default() -> Self {
+ Self::Auto
+ }
+}
diff --git a/third_party/rust/clap/src/util/fnv.rs b/third_party/rust/clap/src/util/fnv.rs
new file mode 100644
index 0000000000..4602300a49
--- /dev/null
+++ b/third_party/rust/clap/src/util/fnv.rs
@@ -0,0 +1,46 @@
+use std::{
+ fmt::Display,
+ hash::{Hash, Hasher},
+};
+
+const MAGIC_INIT: u64 = 0x811C_9DC5;
+
+// TODO: Docs
+pub trait Key: Hash + Display {
+ fn key(&self) -> u64;
+}
+
+impl<T> Key for T
+where
+ T: Hash + Display,
+{
+ fn key(&self) -> u64 {
+ let mut hasher = FnvHasher::new();
+ self.hash(&mut hasher);
+ hasher.finish()
+ }
+}
+
+pub(crate) struct FnvHasher(u64);
+
+impl FnvHasher {
+ pub(crate) fn new() -> Self {
+ FnvHasher(MAGIC_INIT)
+ }
+}
+
+impl Hasher for FnvHasher {
+ fn finish(&self) -> u64 {
+ self.0
+ }
+ fn write(&mut self, bytes: &[u8]) {
+ let FnvHasher(mut hash) = *self;
+
+ for byte in bytes.iter() {
+ hash ^= u64::from(*byte);
+ hash = hash.wrapping_mul(0x0100_0000_01b3);
+ }
+
+ *self = FnvHasher(hash);
+ }
+}
diff --git a/third_party/rust/clap/src/util/graph.rs b/third_party/rust/clap/src/util/graph.rs
new file mode 100644
index 0000000000..d646400b01
--- /dev/null
+++ b/third_party/rust/clap/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/third_party/rust/clap/src/util/id.rs b/third_party/rust/clap/src/util/id.rs
new file mode 100644
index 0000000000..63a7e003ee
--- /dev/null
+++ b/third_party/rust/clap/src/util/id.rs
@@ -0,0 +1,92 @@
+use crate::util::fnv::Key;
+
+use std::{
+ fmt::{Debug, Formatter, Result},
+ hash::{Hash, Hasher},
+ ops::Deref,
+};
+
+#[derive(Clone, Eq, Default)]
+#[cfg_attr(not(debug_assertions), repr(transparent))]
+pub(crate) struct Id {
+ #[cfg(debug_assertions)]
+ name: String,
+ id: u64,
+}
+
+macro_rules! precomputed_hashes {
+ ($($fn_name:ident, $const:expr, $name:expr;)*) => {
+ impl Id {
+ $(
+ pub(crate) fn $fn_name() -> Self {
+ Id {
+ #[cfg(debug_assertions)]
+ name: $name.into(),
+ id: $const,
+ }
+ }
+ )*
+ }
+ };
+}
+
+// precompute some common values
+precomputed_hashes! {
+ empty_hash, 0x1C9D_3ADB_639F_298E, "";
+ help_hash, 0x5963_6393_CFFB_FE5F, "help";
+ version_hash, 0x30FF_0B7C_4D07_9478, "version";
+}
+
+impl Id {
+ pub(crate) fn from_ref<T: Key>(val: T) -> Self {
+ Id {
+ #[cfg(debug_assertions)]
+ name: val.to_string(),
+ id: val.key(),
+ }
+ }
+}
+
+impl Debug for Id {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ #[cfg(debug_assertions)]
+ write!(f, "{}", self.name)?;
+ #[cfg(not(debug_assertions))]
+ write!(f, "[hash: {:X}]", self.id)?;
+
+ Ok(())
+ }
+}
+
+impl Deref for Id {
+ type Target = u64;
+
+ fn deref(&self) -> &Self::Target {
+ &self.id
+ }
+}
+
+impl<T: Key> From<T> for Id {
+ fn from(val: T) -> Self {
+ Id {
+ #[cfg(debug_assertions)]
+ name: val.to_string(),
+ id: val.key(),
+ }
+ }
+}
+
+impl Hash for Id {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.id.hash(state)
+ }
+}
+
+impl PartialEq for Id {
+ fn eq(&self, other: &Id) -> bool {
+ self.id == other.id
+ }
+}
diff --git a/third_party/rust/clap/src/util/mod.rs b/third_party/rust/clap/src/util/mod.rs
new file mode 100644
index 0000000000..ed35765ff6
--- /dev/null
+++ b/third_party/rust/clap/src/util/mod.rs
@@ -0,0 +1,40 @@
+#![allow(clippy::single_component_path_imports)]
+
+mod fnv;
+mod graph;
+mod id;
+#[cfg(feature = "env")]
+mod str_to_bool;
+
+pub use self::fnv::Key;
+
+#[cfg(feature = "env")]
+pub(crate) use self::str_to_bool::str_to_bool;
+pub(crate) use self::{graph::ChildGraph, id::Id};
+
+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/third_party/rust/clap/src/util/str_to_bool.rs b/third_party/rust/clap/src/util/str_to_bool.rs
new file mode 100644
index 0000000000..58e2efa63d
--- /dev/null
+++ b/third_party/rust/clap/src/util/str_to_bool.rs
@@ -0,0 +1,15 @@
+/// 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`.
+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>) -> bool {
+ let pat: &str = &val.as_ref().to_lowercase();
+ !FALSE_LITERALS.contains(&pat)
+}