1
- use std:: char;
2
1
use std:: cmp:: Ordering ;
3
2
4
- use im_ternary_tree:: TernaryTreeList ;
5
-
6
- use crate :: calcit:: CalcitList ;
7
- use crate :: calcit:: { Calcit , CalcitErr } ;
3
+ use crate :: calcit:: { Calcit , CalcitErr , CalcitList } ;
8
4
use crate :: util:: number:: f64_to_usize;
9
5
10
6
pub fn binary_str_concat ( xs : & [ Calcit ] ) -> Result < Calcit , CalcitErr > {
11
7
match ( xs. first ( ) , xs. get ( 1 ) ) {
12
8
( Some ( Calcit :: Nil ) , Some ( Calcit :: Nil ) ) => Ok ( Calcit :: new_str ( "" ) ) ,
13
9
( Some ( Calcit :: Nil ) , Some ( b) ) => Ok ( Calcit :: Str ( b. turn_string ( ) . into ( ) ) ) ,
14
10
( Some ( a) , Some ( Calcit :: Nil ) ) => Ok ( Calcit :: Str ( a. turn_string ( ) . into ( ) ) ) ,
11
+ ( Some ( Calcit :: Str ( s1) ) , Some ( Calcit :: Str ( s2) ) ) => {
12
+ let mut s = String :: with_capacity ( s1. len ( ) + s2. len ( ) ) ;
13
+ s. push_str ( s1) ;
14
+ s. push_str ( s2) ;
15
+ Ok ( Calcit :: Str ( s. into ( ) ) )
16
+ }
15
17
( Some ( a) , Some ( b) ) => {
16
18
let mut s = a. turn_string ( ) ;
17
19
s. push_str ( & b. turn_string ( ) ) ;
@@ -61,14 +63,12 @@ pub fn turn_string(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
61
63
pub fn split ( xs : & [ Calcit ] ) -> Result < Calcit , CalcitErr > {
62
64
match ( xs. first ( ) , xs. get ( 1 ) ) {
63
65
( Some ( Calcit :: Str ( s) ) , Some ( Calcit :: Str ( pattern) ) ) => {
64
- let pieces = ( * * s) . split ( & * * pattern) ;
65
- let mut ys = vec ! [ ] ;
66
- for p in pieces {
67
- if !p. is_empty ( ) {
68
- ys. push ( Calcit :: Str ( p. into ( ) ) ) ;
69
- }
70
- }
71
- Ok ( Calcit :: from ( ys) )
66
+ let pieces = ( * * s)
67
+ . split ( & * * pattern)
68
+ . filter ( |s| !s. is_empty ( ) )
69
+ . map ( |s| Calcit :: Str ( s. into ( ) ) )
70
+ . collect :: < Vec < Calcit > > ( ) ;
71
+ Ok ( Calcit :: from ( pieces) )
72
72
}
73
73
( Some ( a) , Some ( b) ) => CalcitErr :: err_str ( format ! ( "split expected 2 strings, got: {a} {b}" ) ) ,
74
74
( _, _) => CalcitErr :: err_str ( "split expected 2 arguments, got nothing" ) ,
@@ -114,41 +114,32 @@ pub fn replace(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
114
114
pub fn split_lines ( xs : & [ Calcit ] ) -> Result < Calcit , CalcitErr > {
115
115
match xs. first ( ) {
116
116
Some ( Calcit :: Str ( s) ) => {
117
- let lines = s. split ( '\n' ) ;
118
- let mut ys = TernaryTreeList :: Empty ;
119
- for line in lines {
120
- ys = ys. push_right ( Calcit :: Str ( line. to_owned ( ) . into ( ) ) ) ;
121
- }
122
- Ok ( Calcit :: from ( CalcitList :: List ( ys) ) )
117
+ let lines = s. lines ( ) . map ( |line| Calcit :: Str ( line. to_owned ( ) . into ( ) ) ) . collect :: < Vec < Calcit > > ( ) ;
118
+ Ok ( Calcit :: from ( lines) )
123
119
}
124
120
Some ( a) => CalcitErr :: err_str ( format ! ( "split-lines expected 1 string, got: {a}" ) ) ,
125
121
_ => CalcitErr :: err_str ( "split-lines expected 1 argument, got nothing" ) ,
126
122
}
127
123
}
128
124
pub fn str_slice ( xs : & [ Calcit ] ) -> Result < Calcit , CalcitErr > {
129
- match ( xs. first ( ) , xs. get ( 1 ) ) {
130
- ( Some ( Calcit :: Str ( s) ) , Some ( Calcit :: Number ( n) ) ) => match f64_to_usize ( * n) {
131
- Ok ( from) => {
132
- let to: usize = match xs. get ( 2 ) {
133
- Some ( Calcit :: Number ( n2) ) => match f64_to_usize ( * n2) {
134
- Ok ( idx2) => idx2,
135
- Err ( e) => return CalcitErr :: err_str ( format ! ( "&str:slice expected number, got: {e}" ) ) ,
136
- } ,
137
- Some ( a) => return CalcitErr :: err_str ( format ! ( "&str:slice expected number, got: {a}" ) ) ,
138
- None => s. chars ( ) . count ( ) ,
139
- } ;
140
- if from >= to {
141
- Ok ( Calcit :: new_str ( "" ) )
142
- } else {
143
- // turn into vec first to also handle UTF8
144
- let s_vec = s. chars ( ) . collect :: < Vec < _ > > ( ) ;
145
- Ok ( Calcit :: Str ( s_vec[ from..to] . iter ( ) . to_owned ( ) . collect :: < String > ( ) . into ( ) ) )
146
- }
125
+ match ( xs. first ( ) , xs. get ( 1 ) , xs. get ( 2 ) ) {
126
+ ( Some ( Calcit :: Str ( s) ) , Some ( Calcit :: Number ( n_from) ) , n_to) => {
127
+ let from = f64_to_usize ( * n_from) ?;
128
+ let to = match n_to {
129
+ Some ( Calcit :: Number ( n) ) => f64_to_usize ( * n) ?,
130
+ Some ( a) => return CalcitErr :: err_str ( format ! ( "&str:slice expected number, got: {a}" ) ) ,
131
+ None => s. chars ( ) . count ( ) ,
132
+ } ;
133
+
134
+ if from >= to {
135
+ Ok ( Calcit :: new_str ( "" ) )
136
+ } else {
137
+ let s: String = s. chars ( ) . skip ( from) . take ( to - from) . collect ( ) ;
138
+ Ok ( Calcit :: Str ( s. into ( ) ) )
147
139
}
148
- Err ( e) => CalcitErr :: err_str ( e) ,
149
- } ,
150
- ( Some ( a) , Some ( b) ) => CalcitErr :: err_str ( format ! ( "&str:slice expected string and number, got: {a} {b}" ) ) ,
151
- ( _, _) => CalcitErr :: err_nodes ( "&str:slice expected string and numbers, got:" , xs) ,
140
+ }
141
+ ( Some ( a) , Some ( b) , ..) => CalcitErr :: err_str ( format ! ( "&str:slice expected string and number, got: {a} {b}" ) ) ,
142
+ ( _, _, _) => CalcitErr :: err_nodes ( "&str:slice expected string and numbers, got:" , xs) ,
152
143
}
153
144
}
154
145
@@ -321,18 +312,7 @@ pub fn first(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
321
312
322
313
pub fn rest ( xs : & [ Calcit ] ) -> Result < Calcit , CalcitErr > {
323
314
match xs. first ( ) {
324
- Some ( Calcit :: Str ( s) ) => {
325
- let mut buffer = String :: with_capacity ( s. len ( ) - 1 ) ;
326
- let mut is_first = true ;
327
- for c in s. chars ( ) {
328
- if is_first {
329
- is_first = false ;
330
- continue ;
331
- }
332
- buffer. push ( c)
333
- }
334
- Ok ( Calcit :: Str ( buffer. into ( ) ) )
335
- }
315
+ Some ( Calcit :: Str ( s) ) => Ok ( Calcit :: Str ( s. chars ( ) . skip ( 1 ) . collect :: < String > ( ) . into ( ) ) ) ,
336
316
Some ( a) => CalcitErr :: err_str ( format ! ( "str:rest expected a string, got: {a}" ) ) ,
337
317
None => CalcitErr :: err_str ( "str:rest expected 1 argument, got nothing" ) ,
338
318
}
@@ -347,21 +327,17 @@ pub fn pad_left(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
347
327
return CalcitErr :: err_str ( "&str:pad-left expected non-empty pattern" ) ;
348
328
}
349
329
if s. len ( ) >= size {
350
- Ok ( xs[ 0 ] . to_owned ( ) )
351
- } else {
352
- let mut buffer = String :: with_capacity ( size) ;
353
- let pad_size = size - s. len ( ) ;
354
- ' write: loop {
355
- for c in pattern. chars ( ) {
356
- buffer. push ( c) ;
357
- if buffer. len ( ) >= pad_size {
358
- break ' write;
359
- }
360
- }
361
- }
362
- buffer. push_str ( s) ;
363
- Ok ( Calcit :: Str ( buffer. into ( ) ) )
330
+ return Ok ( xs[ 0 ] . to_owned ( ) ) ;
331
+ }
332
+
333
+ let pad_size = size - s. len ( ) ;
334
+ let mut buffer = String :: with_capacity ( size) ;
335
+ // Directly iterate over pattern characters
336
+ for c in pattern. chars ( ) . cycle ( ) . take ( pad_size) {
337
+ buffer. push ( c) ;
364
338
}
339
+ buffer. push_str ( s) ;
340
+ Ok ( Calcit :: Str ( buffer. into ( ) ) )
365
341
}
366
342
( a, b, c) => CalcitErr :: err_str ( format ! ( "&str:pad-left expected string, number, string, got: {a} {b} {c}" ) ) ,
367
343
}
@@ -379,20 +355,16 @@ pub fn pad_right(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
379
355
return CalcitErr :: err_str ( "&str:pad-right expected non-empty pattern" ) ;
380
356
}
381
357
if s. len ( ) >= size {
382
- Ok ( xs[ 0 ] . to_owned ( ) )
383
- } else {
384
- let mut buffer = String :: with_capacity ( size) ;
385
- buffer. push_str ( s) ;
386
- ' write: loop {
387
- for c in pattern. chars ( ) {
388
- buffer. push ( c) ;
389
- if buffer. len ( ) >= size {
390
- break ' write;
391
- }
392
- }
393
- }
394
- Ok ( Calcit :: Str ( buffer. into ( ) ) )
358
+ return Ok ( xs[ 0 ] . to_owned ( ) ) ;
359
+ }
360
+
361
+ let mut buffer = String :: with_capacity ( size) ;
362
+ buffer. push_str ( s) ;
363
+ // Directly iterate over pattern characters
364
+ for c in pattern. chars ( ) . cycle ( ) . take ( size - s. len ( ) ) {
365
+ buffer. push ( c) ;
395
366
}
367
+ Ok ( Calcit :: Str ( buffer. into ( ) ) )
396
368
}
397
369
( a, b, c) => CalcitErr :: err_str ( format ! ( "&str:pad-right expected string, number, string, got: {a} {b} {c}" ) ) ,
398
370
}
0 commit comments