44// file that was distributed with this source code.
55
66// cSpell:ignore strs
7-
7+ use aligned_vec :: { AVec , Alignment , ConstAlign } ;
88use clap:: { Arg , ArgAction , Command , builder:: ValueParser } ;
99use std:: error:: Error ;
1010use std:: ffi:: OsString ;
@@ -14,14 +14,15 @@ use uucore::format_usage;
1414use uucore:: translate;
1515
1616// it's possible that using a smaller or larger buffer might provide better performance on some
17- // systems, but honestly this is good enough
17+ // systems, but honestly this is good enough (without zero-copy)
18+ // but let it multiple of page size at least for
1819const BUF_SIZE : usize = 16 * 1024 ;
1920
2021#[ uucore:: main]
2122pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
2223 let matches = uucore:: clap_localization:: handle_clap_result ( uu_app ( ) , args) ?;
2324
24- let mut buffer = Vec :: with_capacity ( BUF_SIZE ) ;
25+ let mut buffer: AVec < u8 , ConstAlign < BUF_SIZE > > = AVec :: with_capacity ( BUF_SIZE , BUF_SIZE ) ;
2526 #[ allow( clippy:: unwrap_used, reason = "clap provides 'y' by default" ) ]
2627 let _ = args_into_buffer ( & mut buffer, matches. get_many :: < OsString > ( "STRING" ) . unwrap ( ) ) ;
2728 prepare_buffer ( & mut buffer) ;
@@ -55,8 +56,8 @@ pub fn uu_app() -> Command {
5556
5657/// Copies words from `i` into `buf`, separated by spaces.
5758#[ allow( clippy:: unnecessary_wraps, reason = "needed on some platforms" ) ]
58- fn args_into_buffer < ' a > (
59- buf : & mut Vec < u8 > ,
59+ fn args_into_buffer < ' a , A : Alignment > (
60+ buf : & mut AVec < u8 , A > ,
6061 i : impl Iterator < Item = & ' a OsString > ,
6162) -> Result < ( ) , Box < dyn Error > > {
6263 // On Unix (and wasi), OsStrs are just &[u8]'s underneath...
@@ -91,7 +92,7 @@ fn args_into_buffer<'a>(
9192
9293/// Assumes buf holds a single output line forged from the command line arguments, copies it
9394/// repeatedly until the buffer holds as many copies as it can under [`BUF_SIZE`].
94- fn prepare_buffer ( buf : & mut Vec < u8 > ) {
95+ fn prepare_buffer < A : Alignment > ( buf : & mut AVec < u8 , A > ) {
9596 if buf. len ( ) * 2 > BUF_SIZE {
9697 return ;
9798 }
@@ -102,9 +103,14 @@ fn prepare_buffer(buf: &mut Vec<u8>) {
102103 let target_size = line_len * ( BUF_SIZE / line_len) ;
103104
104105 while buf. len ( ) < target_size {
105- let to_copy = std:: cmp:: min ( target_size - buf. len ( ) , buf. len ( ) ) ;
106+ let current_len = buf. len ( ) ;
107+ let to_copy = std:: cmp:: min ( target_size - current_len, current_len) ;
106108 debug_assert_eq ! ( to_copy % line_len, 0 ) ;
107- buf. extend_from_within ( ..to_copy) ;
109+ #[ allow(
110+ clippy:: unnecessary_to_owned,
111+ reason = "needs useless copy without unsafe"
112+ ) ]
113+ buf. extend_from_slice ( & buf[ ..to_copy] . to_vec ( ) ) ;
108114 }
109115}
110116
@@ -142,7 +148,8 @@ mod tests {
142148 ] ;
143149
144150 for ( line, final_len) in tests {
145- let mut v = std:: iter:: repeat_n ( b'a' , line) . collect :: < Vec < _ > > ( ) ;
151+ let mut v: AVec < u8 , ConstAlign < BUF_SIZE > > =
152+ AVec :: from_iter ( BUF_SIZE , std:: iter:: repeat_n ( b'a' , line) ) ;
146153 prepare_buffer ( & mut v) ;
147154 assert_eq ! ( v. len( ) , final_len) ;
148155 }
@@ -151,24 +158,27 @@ mod tests {
151158 #[ test]
152159 fn test_args_into_buf ( ) {
153160 {
154- let mut v = Vec :: with_capacity ( BUF_SIZE ) ;
161+ let mut v: AVec < u8 , ConstAlign < BUF_SIZE > > = AVec :: with_capacity ( BUF_SIZE , BUF_SIZE ) ;
155162 let default_args = [ "y" . into ( ) ] ;
156163 args_into_buffer ( & mut v, default_args. iter ( ) ) . unwrap ( ) ;
157- assert_eq ! ( String :: from_utf8( v) . unwrap( ) , "y\n " ) ;
164+ assert_eq ! ( String :: from_utf8( v. to_vec ( ) ) . unwrap( ) , "y\n " ) ;
158165 }
159166
160167 {
161- let mut v = Vec :: with_capacity ( BUF_SIZE ) ;
168+ let mut v: AVec < u8 , ConstAlign < BUF_SIZE > > = AVec :: with_capacity ( BUF_SIZE , BUF_SIZE ) ;
162169 let args = [ "foo" . into ( ) ] ;
163170 args_into_buffer ( & mut v, args. iter ( ) ) . unwrap ( ) ;
164- assert_eq ! ( String :: from_utf8( v) . unwrap( ) , "foo\n " ) ;
171+ assert_eq ! ( String :: from_utf8( v. to_vec ( ) ) . unwrap( ) , "foo\n " ) ;
165172 }
166173
167174 {
168- let mut v = Vec :: with_capacity ( BUF_SIZE ) ;
175+ let mut v: AVec < u8 , ConstAlign < BUF_SIZE > > = AVec :: with_capacity ( BUF_SIZE , BUF_SIZE ) ;
169176 let args = [ "foo" . into ( ) , "bar baz" . into ( ) , "qux" . into ( ) ] ;
170177 args_into_buffer ( & mut v, args. iter ( ) ) . unwrap ( ) ;
171- assert_eq ! ( String :: from_utf8( v) . unwrap( ) , "foo bar baz qux\n " ) ;
178+ assert_eq ! (
179+ String :: from_utf8( v. to_vec( ) ) . unwrap( ) ,
180+ "foo bar baz qux\n "
181+ ) ;
172182 }
173183 }
174184}
0 commit comments