5
5
use clap:: { Arg , ArgAction , Command } ;
6
6
use std:: io:: stdout;
7
7
use std:: ops:: ControlFlow ;
8
+ #[ cfg( unix) ]
9
+ use std:: os:: unix:: ffi:: { OsStrExt , OsStringExt } ;
10
+ #[ cfg( windows) ]
11
+ use std:: os:: windows:: ffi:: OsStrExt ;
8
12
use uucore:: error:: { UResult , UUsageError } ;
9
13
use uucore:: format:: { FormatArgument , FormatItem , parse_spec_and_escape} ;
10
14
use uucore:: { format_usage, help_about, help_section, help_usage, show_warning} ;
@@ -19,23 +23,50 @@ mod options {
19
23
pub const FORMAT : & str = "FORMAT" ;
20
24
pub const ARGUMENT : & str = "ARGUMENT" ;
21
25
}
22
-
23
26
#[ uucore:: main]
24
27
pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
25
28
let matches = uu_app ( ) . get_matches_from ( args) ;
26
29
27
30
let format = matches
28
- . get_one :: < String > ( options:: FORMAT )
31
+ . get_one :: < std :: ffi :: OsString > ( options:: FORMAT )
29
32
. ok_or_else ( || UUsageError :: new ( 1 , "missing operand" ) ) ?;
30
33
31
- let values: Vec < _ > = match matches. get_many :: < String > ( options:: ARGUMENT ) {
32
- Some ( s) => s. map ( |s| FormatArgument :: Unparsed ( s. to_string ( ) ) ) . collect ( ) ,
34
+ #[ cfg( unix) ]
35
+ let format = format. as_bytes ( ) ;
36
+
37
+ #[ cfg( windows) ]
38
+ let format_vec: Vec < u8 > = format
39
+ . encode_wide ( )
40
+ . flat_map ( |wchar| wchar. to_le_bytes ( ) )
41
+ . collect ( ) ;
42
+ #[ cfg( windows) ]
43
+ let format = format_vec. as_slice ( ) ;
44
+
45
+ let values: Vec < _ > = match matches. get_many :: < std:: ffi:: OsString > ( options:: ARGUMENT ) {
46
+ Some ( s) => s
47
+ . map ( |os_str| {
48
+ #[ cfg( unix) ]
49
+ let raw_bytes: Vec < u8 > = os_str. clone ( ) . into_vec ( ) ;
50
+
51
+ #[ cfg( windows) ]
52
+ let raw_bytes: Vec < u8 > = os_str
53
+ . encode_wide ( )
54
+ . flat_map ( |wchar| wchar. to_le_bytes ( ) )
55
+ . collect ( ) ;
56
+ FormatArgument :: Unparsed (
57
+ String :: from_utf8 ( raw_bytes. clone ( ) )
58
+ . unwrap_or_else ( |_| raw_bytes. iter ( ) . map ( |& b| b as char ) . collect ( ) ) ,
59
+ )
60
+ } )
61
+ . collect ( ) ,
33
62
None => vec ! [ ] ,
34
63
} ;
35
64
36
65
let mut format_seen = false ;
37
66
let mut args = values. iter ( ) . peekable ( ) ;
38
- for item in parse_spec_and_escape ( format. as_ref ( ) ) {
67
+
68
+ // Parse and process the format string
69
+ for item in parse_spec_and_escape ( format) {
39
70
if let Ok ( FormatItem :: Spec ( _) ) = item {
40
71
format_seen = true ;
41
72
}
@@ -58,7 +89,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
58
89
}
59
90
60
91
while args. peek ( ) . is_some ( ) {
61
- for item in parse_spec_and_escape ( format. as_ref ( ) ) {
92
+ for item in parse_spec_and_escape ( format) {
62
93
match item?. write ( stdout ( ) , & mut args) ? {
63
94
ControlFlow :: Continue ( ( ) ) => { }
64
95
ControlFlow :: Break ( ( ) ) => return Ok ( ( ) ) ,
@@ -90,6 +121,10 @@ pub fn uu_app() -> Command {
90
121
. help ( "Print version information" )
91
122
. action ( ArgAction :: Version ) ,
92
123
)
93
- . arg ( Arg :: new ( options:: FORMAT ) )
94
- . arg ( Arg :: new ( options:: ARGUMENT ) . action ( ArgAction :: Append ) )
124
+ . arg ( Arg :: new ( options:: FORMAT ) . value_parser ( clap:: value_parser!( std:: ffi:: OsString ) ) )
125
+ . arg (
126
+ Arg :: new ( options:: ARGUMENT )
127
+ . action ( ArgAction :: Append )
128
+ . value_parser ( clap:: value_parser!( std:: ffi:: OsString ) ) ,
129
+ )
95
130
}
0 commit comments