summaryrefslogtreecommitdiff
path: root/mingling/src
diff options
context:
space:
mode:
Diffstat (limited to 'mingling/src')
-rw-r--r--mingling/src/lib.rs6
-rw-r--r--mingling/src/parser.rs5
-rw-r--r--mingling/src/parser/args.rs95
-rw-r--r--mingling/src/parser/picker.rs116
-rw-r--r--mingling/src/parser/picker/builtin.rs53
5 files changed, 274 insertions, 1 deletions
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
index d85b16d..19c2db9 100644
--- a/mingling/src/lib.rs
+++ b/mingling/src/lib.rs
@@ -1,2 +1,6 @@
// Re-Export Core lib
-pub use mingling_core::*;
+pub use mingling::*;
+pub use mingling_core as mingling;
+
+#[cfg(feature = "parser")]
+pub mod parser;
diff --git a/mingling/src/parser.rs b/mingling/src/parser.rs
new file mode 100644
index 0000000..be6f9b2
--- /dev/null
+++ b/mingling/src/parser.rs
@@ -0,0 +1,5 @@
+mod args;
+pub use crate::parser::args::*;
+
+mod picker;
+pub use crate::parser::picker::*;
diff --git a/mingling/src/parser/args.rs b/mingling/src/parser/args.rs
new file mode 100644
index 0000000..e659feb
--- /dev/null
+++ b/mingling/src/parser/args.rs
@@ -0,0 +1,95 @@
+use mingling_core::{Flag, special_argument, special_flag};
+
+pub struct Argument {
+ vec: Vec<String>,
+}
+
+impl From<&'static str> for Argument {
+ fn from(s: &'static str) -> Self {
+ Argument {
+ vec: vec![s.to_string()],
+ }
+ }
+}
+
+impl From<&'static [&'static str]> for Argument {
+ fn from(slice: &'static [&'static str]) -> Self {
+ Argument {
+ vec: slice.iter().map(|&s| s.to_string()).collect(),
+ }
+ }
+}
+
+impl<const N: usize> From<[&'static str; N]> for Argument {
+ fn from(slice: [&'static str; N]) -> Self {
+ Argument {
+ vec: slice.iter().map(|&s| s.to_string()).collect(),
+ }
+ }
+}
+
+impl<const N: usize> From<&'static [&'static str; N]> for Argument {
+ fn from(slice: &'static [&'static str; N]) -> Self {
+ Argument {
+ vec: slice.iter().map(|&s| s.to_string()).collect(),
+ }
+ }
+}
+
+impl From<Vec<String>> for Argument {
+ fn from(vec: Vec<String>) -> Self {
+ Argument { vec }
+ }
+}
+
+impl AsRef<[String]> for Argument {
+ fn as_ref(&self) -> &[String] {
+ &self.vec
+ }
+}
+
+impl std::ops::Deref for Argument {
+ type Target = Vec<String>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.vec
+ }
+}
+
+impl std::ops::DerefMut for Argument {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.vec
+ }
+}
+
+impl Argument {
+ /// Extracts argument (with value) from arguments
+ pub fn pick_argument<F>(&mut self, flag: F) -> Option<String>
+ where
+ F: Into<Flag>,
+ {
+ let flag: Flag = flag.into();
+ for argument in flag.iter() {
+ let value = special_argument!(self.vec, argument);
+ if value.is_some() {
+ return value;
+ }
+ }
+ None
+ }
+
+ /// Extracts flags from arguments
+ pub fn pick_flag<F>(&mut self, flag: F) -> bool
+ where
+ F: Into<Flag>,
+ {
+ let flag: Flag = flag.into();
+ for argument in flag.iter() {
+ let enabled = special_flag!(self.vec, argument);
+ if enabled {
+ return enabled;
+ }
+ }
+ false
+ }
+}
diff --git a/mingling/src/parser/picker.rs b/mingling/src/parser/picker.rs
new file mode 100644
index 0000000..dc8b8da
--- /dev/null
+++ b/mingling/src/parser/picker.rs
@@ -0,0 +1,116 @@
+use crate::parser::Argument;
+use mingling_core::Flag;
+
+pub mod builtin;
+
+#[doc(hidden)]
+pub struct Picker {
+ pub args: Argument,
+}
+
+impl Picker {
+ pub fn new(args: impl Into<Argument>) -> Picker {
+ Picker { args: args.into() }
+ }
+
+ pub fn pick<TNext>(mut self, val: impl Into<Flag>) -> Pick1<TNext>
+ where
+ TNext: Pickable<Output = TNext> + Default,
+ {
+ let v = TNext::pick(&mut self.args, val.into()).unwrap_or_default();
+ Pick1 {
+ args: self.args,
+ val_1: v,
+ }
+ }
+}
+
+impl<T: Into<Argument>> From<T> for Picker {
+ fn from(value: T) -> Self {
+ Picker::new(value)
+ }
+}
+
+pub trait Pickable {
+ type Output: Default;
+ fn pick(args: &mut Argument, flag: Flag) -> Option<Self::Output>;
+}
+
+#[doc(hidden)]
+macro_rules! define_pick_structs {
+ ($n:tt $($T:ident $val:ident),+) => {
+ #[doc(hidden)]
+ pub struct $n<$($T),+>
+ where
+ $($T: Pickable,)+
+ {
+ #[allow(dead_code)]
+ args: Argument,
+ $(pub $val: $T,)+
+ }
+
+ impl<$($T),+> From<$n<$($T),+>> for ($($T,)+)
+ where
+ $($T: Pickable,)+
+ {
+ fn from(pick: $n<$($T),+>) -> Self {
+ ($(pick.$val,)+)
+ }
+ }
+
+ impl<$($T),+> $n<$($T),+>
+ where
+ $($T: Pickable,)+
+ {
+ pub fn unpack(self) -> ($($T,)+) {
+ ($(self.$val,)+)
+ }
+ }
+ };
+}
+
+#[doc(hidden)]
+macro_rules! impl_pick_structs {
+ ($n:ident $next:ident $next_val:ident $($T:ident $val:ident),+) => {
+ impl<$($T),+> $n<$($T),+>
+ where
+ $($T: Pickable,)+
+ {
+ pub fn pick<TNext>(mut self, val: impl Into<mingling_core::Flag>) -> $next<$($T,)+ TNext>
+ where
+ TNext: Pickable<Output = TNext> + Default,
+ {
+ let v = TNext::pick(&mut self.args, val.into()).unwrap_or_default();
+ $next {
+ args: self.args,
+ $($val: self.$val,)+
+ $next_val: v,
+ }
+ }
+ }
+ };
+}
+
+define_pick_structs! { Pick1 T1 val_1 }
+define_pick_structs! { Pick2 T1 val_1, T2 val_2 }
+define_pick_structs! { Pick3 T1 val_1, T2 val_2, T3 val_3 }
+define_pick_structs! { Pick4 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
+define_pick_structs! { Pick5 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
+define_pick_structs! { Pick6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
+define_pick_structs! { Pick7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
+define_pick_structs! { Pick8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
+define_pick_structs! { Pick9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
+define_pick_structs! { Pick10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
+define_pick_structs! { Pick11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
+define_pick_structs! { Pick12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11, T12 val_12 }
+impl_pick_structs! { Pick1 Pick2 val_2 T1 val_1 }
+impl_pick_structs! { Pick2 Pick3 val_3 T1 val_1, T2 val_2 }
+impl_pick_structs! { Pick3 Pick4 val_4 T1 val_1, T2 val_2, T3 val_3 }
+impl_pick_structs! { Pick4 Pick5 val_5 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
+impl_pick_structs! { Pick5 Pick6 val_6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
+impl_pick_structs! { Pick6 Pick7 val_7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
+impl_pick_structs! { Pick7 Pick8 val_8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
+impl_pick_structs! { Pick8 Pick9 val_9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
+impl_pick_structs! { Pick9 Pick10 val_10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
+impl_pick_structs! { Pick10 Pick11 val_11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
+impl_pick_structs! { Pick11 Pick12 val_12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
diff --git a/mingling/src/parser/picker/builtin.rs b/mingling/src/parser/picker/builtin.rs
new file mode 100644
index 0000000..0b1ce08
--- /dev/null
+++ b/mingling/src/parser/picker/builtin.rs
@@ -0,0 +1,53 @@
+use size::Size;
+
+use crate::parser::Pickable;
+
+impl Pickable for String {
+ type Output = String;
+
+ fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option<Self::Output> {
+ args.pick_argument(flag)
+ }
+}
+
+macro_rules! impl_pickable_for_number {
+ ($($t:ty),*) => {
+ $(
+ impl Pickable for $t {
+ type Output = $t;
+
+ fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option<Self::Output> {
+ let Some(picked) = args.pick_argument(flag) else {
+ return None;
+ };
+ picked.parse().ok()
+ }
+ }
+ )*
+ };
+}
+
+impl_pickable_for_number!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64);
+
+impl Pickable for bool {
+ type Output = bool;
+
+ fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option<Self::Output> {
+ Some(args.pick_flag(flag))
+ }
+}
+
+impl Pickable for usize {
+ type Output = usize;
+
+ fn pick(args: &mut crate::parser::Argument, flag: mingling_core::Flag) -> Option<Self::Output> {
+ let Some(picked) = args.pick_argument(flag) else {
+ return None;
+ };
+ let size_parse = Size::from_str(picked.as_str());
+ match size_parse {
+ Ok(size) => Some(size.bytes() as usize),
+ Err(_) => None,
+ }
+ }
+}