1- use crate :: deserialize:: { Subspan , SubspanMeta } ;
2- use alloc:: borrow:: Cow ;
3-
41#[ derive( Debug ) ]
52pub ( crate ) enum ArgType < ' a > {
6- LongFlag ( Cow < ' a , str > ) ,
3+ // A `--` separator after which we only expect positional arguments
4+ DoubleDash ,
5+
6+ // `--{arg}`
7+ LongFlag ( & ' a str ) ,
8+
9+ // `-{a}`
710 ShortFlag ( & ' a str ) ,
11+
12+ // `{a}`
813 Positional ,
14+
15+ // End of the argument list
916 None ,
1017}
1118
1219impl < ' a > ArgType < ' a > {
1320 pub ( crate ) fn parse ( arg : & ' a str ) -> Self {
1421 if let Some ( key) = arg. strip_prefix ( "--" ) {
15- ArgType :: LongFlag ( Self :: kebab_to_snake ( key) )
22+ if key. is_empty ( ) {
23+ ArgType :: DoubleDash
24+ } else {
25+ ArgType :: LongFlag ( key)
26+ }
1627 } else if let Some ( key) = arg. strip_prefix ( '-' ) {
1728 ArgType :: ShortFlag ( key)
1829 } else if !arg. is_empty ( ) {
@@ -21,67 +32,4 @@ impl<'a> ArgType<'a> {
2132 ArgType :: None
2233 }
2334 }
24-
25- pub ( crate ) fn kebab_to_snake ( input : & str ) -> Cow < ' _ , str > {
26- if !input. contains ( '-' ) {
27- return Cow :: Borrowed ( input) ;
28- }
29- Cow :: Owned ( input. replace ( '-' , "_" ) )
30- }
31- }
32-
33- // This trait implementation allows for using a Subspan together with an arg string
34- impl < ' a > From < ( & ' a Subspan , & ' a str ) > for ArgType < ' a > {
35- /// Converts a subspan and argument string into the appropriate ArgType.
36- ///
37- /// - For KeyValue metadata: key part (offset 0) is parsed normally (ShortFlag or LongFlag),
38- /// value part (offset > 0) is treated as Positional
39- /// - For Delimiter metadata: treated as Positional
40- /// - For no metadata: parsed normally
41- fn from ( ( subspan, arg) : ( & ' a Subspan , & ' a str ) ) -> Self {
42- if subspan. offset >= arg. len ( ) {
43- return ArgType :: None ;
44- }
45-
46- let end = core:: cmp:: min ( subspan. offset + subspan. len , arg. len ( ) ) ;
47- let part = & arg[ subspan. offset ..end] ;
48-
49- // Check metadata for special handling
50- if let Some ( meta) = & subspan. meta {
51- match meta {
52- SubspanMeta :: KeyValue => {
53- // For KeyValue, if it's the value part (offset > 0),
54- // treat it as a positional argument regardless of content
55- if subspan. offset > 0 {
56- return if !part. is_empty ( ) {
57- ArgType :: Positional
58- } else {
59- ArgType :: None
60- } ;
61- }
62- // Otherwise parse key part normally with parse()
63- }
64- SubspanMeta :: Delimiter ( _) => {
65- // For delimited values, treat as positional
66- return if !part. is_empty ( ) {
67- ArgType :: Positional
68- } else {
69- ArgType :: None
70- } ;
71- }
72- }
73- }
74-
75- // Default parsing for keys and non-special cases
76- ArgType :: parse ( part)
77- }
78- }
79-
80- /// Extracts a substring from arg based on a subspan
81- pub ( crate ) fn extract_subspan < ' a > ( subspan : & Subspan , arg : & ' a str ) -> & ' a str {
82- if subspan. offset >= arg. len ( ) {
83- return "" ;
84- }
85- let end = core:: cmp:: min ( subspan. offset + subspan. len , arg. len ( ) ) ;
86- & arg[ subspan. offset ..end]
8735}
0 commit comments