50
50
//! ```
51
51
52
52
use core:: {
53
- char, fmt ,
54
- fmt:: { Display , Write as _ } ,
53
+ char,
54
+ fmt:: { self , Display } ,
55
55
num:: NonZeroU32 ,
56
56
str:: FromStr ,
57
57
} ;
58
58
59
59
use crate :: {
60
- Bitboard , Board , ByColor , ByRole , CastlingMode , Color , EnPassantMode , File , FromSetup , Piece ,
61
- Position , PositionError , Rank , RemainingChecks , Role , Setup , Square ,
60
+ util :: AppendAscii , Bitboard , Board , ByColor , ByRole , CastlingMode , Color , EnPassantMode , File ,
61
+ FromSetup , Piece , Position , PositionError , Rank , RemainingChecks , Role , Setup , Square ,
62
62
} ;
63
63
64
- fn fmt_castling (
65
- f : & mut fmt :: Formatter < ' _ > ,
64
+ fn append_castling < W : AppendAscii > (
65
+ f : & mut W ,
66
66
board : & Board ,
67
67
castling_rights : Bitboard ,
68
- ) -> fmt :: Result {
68
+ ) -> Result < ( ) , W :: Error > {
69
69
let mut empty = true ;
70
70
71
71
for color in Color :: ALL {
@@ -76,7 +76,7 @@ fn fmt_castling(
76
76
let candidates = board. by_piece ( color. rook ( ) ) & color. backrank ( ) ;
77
77
78
78
for rook in ( castling_rights & color. backrank ( ) ) . into_iter ( ) . rev ( ) {
79
- f. write_char (
79
+ f. append_ascii (
80
80
if Some ( rook) == candidates. first ( ) && king. map_or ( false , |k| rook < k) {
81
81
color. fold_wb ( 'Q' , 'q' )
82
82
} else if Some ( rook) == candidates. last ( ) && king. map_or ( false , |k| k < rook) {
@@ -91,42 +91,46 @@ fn fmt_castling(
91
91
}
92
92
93
93
if empty {
94
- f. write_char ( '-' ) ?;
94
+ f. append_ascii ( '-' ) ?;
95
95
}
96
96
97
97
Ok ( ( ) )
98
98
}
99
99
100
- fn fmt_pockets ( f : & mut fmt:: Formatter < ' _ > , pockets : & ByColor < ByRole < u8 > > ) -> fmt:: Result {
101
- f. write_char ( '[' ) ?;
100
+ fn append_pockets < W : AppendAscii > (
101
+ f : & mut W ,
102
+ pockets : & ByColor < ByRole < u8 > > ,
103
+ ) -> Result < ( ) , W :: Error > {
104
+ f. append_ascii ( '[' ) ?;
102
105
for color in Color :: ALL {
103
106
for role in Role :: ALL {
104
107
let piece = Piece { color, role } ;
105
108
for _ in 0 ..* pockets. piece ( piece) {
106
- f. write_char ( piece. char ( ) ) ?;
109
+ f. append_ascii ( piece. char ( ) ) ?;
107
110
}
108
111
}
109
112
}
110
- f. write_char ( ']' )
113
+ f. append_ascii ( ']' )
111
114
}
112
115
113
- fn fmt_epd ( f : & mut fmt:: Formatter < ' _ > , setup : & Setup ) -> fmt:: Result {
114
- setup. board . board_fen ( setup. promoted ) . fmt ( f) ?;
116
+ fn append_epd < W : AppendAscii > ( f : & mut W , setup : & Setup ) -> Result < ( ) , W :: Error > {
117
+ f. reserve ( 21 ) ;
118
+ setup. board . board_fen ( setup. promoted ) . append_to ( f) ?;
115
119
if let Some ( ref pockets) = setup. pockets {
116
- fmt_pockets ( f, pockets) ?;
120
+ append_pockets ( f, pockets) ?;
117
121
}
118
- f. write_char ( ' ' ) ?;
119
- f. write_char ( setup. turn . char ( ) ) ?;
120
- f. write_char ( ' ' ) ?;
121
- fmt_castling ( f, & setup. board , setup. castling_rights ) ?;
122
- f. write_char ( ' ' ) ?;
122
+ f. append_ascii ( ' ' ) ?;
123
+ f. append_ascii ( setup. turn . char ( ) ) ?;
124
+ f. append_ascii ( ' ' ) ?;
125
+ append_castling ( f, & setup. board , setup. castling_rights ) ?;
126
+ f. append_ascii ( ' ' ) ?;
123
127
match setup. ep_square {
124
- Some ( ref ep_square) => Display :: fmt ( ep_square, f) ?,
125
- None => f. write_char ( '-' ) ?,
128
+ Some ( ref ep_square) => ep_square. append_to ( f) ?,
129
+ None => f. append_ascii ( '-' ) ?,
126
130
}
127
131
if let Some ( ref remaining_checks) = setup. remaining_checks {
128
- f. write_char ( ' ' ) ?;
129
- Display :: fmt ( remaining_checks, f) ?;
132
+ f. append_ascii ( ' ' ) ?;
133
+ remaining_checks. append_to ( f) ?;
130
134
}
131
135
Ok ( ( ) )
132
136
}
@@ -272,7 +276,7 @@ impl FromStr for Board {
272
276
273
277
impl Display for Board {
274
278
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
275
- self . board_fen ( Bitboard ( 0 ) ) . fmt ( f)
279
+ self . board_fen ( Bitboard ( 0 ) ) . append_to ( f)
276
280
}
277
281
}
278
282
@@ -286,39 +290,59 @@ pub struct BoardFen<'b> {
286
290
promoted : Bitboard ,
287
291
}
288
292
289
- impl < ' b > Display for BoardFen < ' b > {
290
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
293
+ impl BoardFen < ' _ > {
294
+ fn append_to < W : AppendAscii > ( & self , f : & mut W ) -> Result < ( ) , W :: Error > {
295
+ f. reserve ( 15 ) ;
296
+
291
297
for rank in Rank :: ALL . into_iter ( ) . rev ( ) {
292
- let mut empty = 0 ;
298
+ let mut prev_file = - 1 ;
293
299
294
- for file in File :: ALL {
295
- let square = Square :: from_coords ( file, rank) ;
300
+ for square in self . board . occupied ( ) & rank {
301
+ let empty = i32:: from ( square. file ( ) ) - prev_file - 1 ;
302
+ if empty > 0 {
303
+ f. append_ascii ( char:: from ( b'0' + empty as u8 ) ) ?;
304
+ }
305
+ prev_file = i32:: from ( square. file ( ) ) ;
296
306
297
- empty = if let Some ( piece) = self . board . piece_at ( square) {
298
- if empty > 0 {
299
- f. write_char ( char:: from_digit ( empty, 10 ) . expect ( "8 files only" ) ) ?;
300
- }
301
- f. write_char ( piece. char ( ) ) ?;
302
- if self . promoted . contains ( square) {
303
- f. write_char ( '~' ) ?;
304
- }
305
- 0
306
- } else {
307
- empty + 1
308
- } ;
307
+ f. append_ascii ( self . board . piece_at ( square) . expect ( "piece" ) . char ( ) ) ?;
308
+ if self . promoted . contains ( square) {
309
+ f. append_ascii ( '~' ) ?;
310
+ }
309
311
}
310
312
313
+ let empty = i32:: from ( File :: H ) - prev_file;
311
314
if empty > 0 {
312
- f. write_char ( char:: from_digit ( empty , 10 ) . expect ( "8 files only" ) ) ?;
315
+ f. append_ascii ( char:: from ( b'0' + empty as u8 ) ) ?;
313
316
}
314
317
315
318
if rank > Rank :: First {
316
- f. write_char ( '/' ) ?;
319
+ f. append_ascii ( '/' ) ?;
317
320
}
318
321
}
319
322
320
323
Ok ( ( ) )
321
324
}
325
+
326
+ #[ cfg( feature = "alloc" ) ]
327
+ pub fn append_to_string ( & self , s : & mut alloc:: string:: String ) {
328
+ let _ = self . append_to ( s) ;
329
+ }
330
+
331
+ #[ cfg( feature = "alloc" ) ]
332
+ pub fn append_ascii_to ( & self , buf : & mut alloc:: vec:: Vec < u8 > ) {
333
+ let _ = self . append_to ( buf) ;
334
+ }
335
+
336
+ #[ cfg( feature = "std" ) ]
337
+ pub fn write_ascii_to < W : std:: io:: Write > ( & self , w : W ) -> std:: io:: Result < ( ) > {
338
+ self . append_to ( & mut crate :: util:: WriteAscii ( w) )
339
+ }
340
+ }
341
+
342
+ impl Display for BoardFen < ' _ > {
343
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
344
+ self . append_to ( f)
345
+ }
322
346
}
323
347
324
348
/// A FEN like `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1`.
@@ -505,6 +529,29 @@ impl Fen {
505
529
pub fn into_position < P : FromSetup > ( self , mode : CastlingMode ) -> Result < P , PositionError < P > > {
506
530
P :: from_setup ( self . 0 , mode)
507
531
}
532
+
533
+ fn append_to < W : AppendAscii > ( & self , f : & mut W ) -> Result < ( ) , W :: Error > {
534
+ append_epd ( f, & self . 0 ) ?;
535
+ f. append_ascii ( ' ' ) ?;
536
+ f. append_u32 ( self . 0 . halfmoves ) ?;
537
+ f. append_ascii ( ' ' ) ?;
538
+ f. append_u32 ( u32:: from ( self . 0 . fullmoves ) )
539
+ }
540
+
541
+ #[ cfg( feature = "alloc" ) ]
542
+ pub fn append_to_string ( & self , s : & mut alloc:: string:: String ) {
543
+ let _ = self . append_to ( s) ;
544
+ }
545
+
546
+ #[ cfg( feature = "alloc" ) ]
547
+ pub fn append_ascii_to ( & self , buf : & mut alloc:: vec:: Vec < u8 > ) {
548
+ let _ = self . append_to ( buf) ;
549
+ }
550
+
551
+ #[ cfg( feature = "std" ) ]
552
+ pub fn write_ascii_to < W : std:: io:: Write > ( & self , w : W ) -> std:: io:: Result < ( ) > {
553
+ self . append_to ( & mut crate :: util:: WriteAscii ( w) )
554
+ }
508
555
}
509
556
510
557
impl From < Setup > for Fen {
@@ -529,8 +576,7 @@ impl FromStr for Fen {
529
576
530
577
impl Display for Fen {
531
578
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
532
- fmt_epd ( f, & self . 0 ) ?;
533
- write ! ( f, " {} {}" , self . 0 . halfmoves, self . 0 . fullmoves)
579
+ self . append_to ( f)
534
580
}
535
581
}
536
582
@@ -571,6 +617,25 @@ impl Epd {
571
617
pub fn into_position < P : FromSetup > ( self , mode : CastlingMode ) -> Result < P , PositionError < P > > {
572
618
P :: from_setup ( self . into_setup ( ) , mode)
573
619
}
620
+
621
+ fn append_to < W : AppendAscii > ( & self , f : & mut W ) -> Result < ( ) , W :: Error > {
622
+ append_epd ( f, & self . 0 )
623
+ }
624
+
625
+ #[ cfg( feature = "alloc" ) ]
626
+ pub fn append_to_string ( & self , s : & mut alloc:: string:: String ) {
627
+ let _ = self . append_to ( s) ;
628
+ }
629
+
630
+ #[ cfg( feature = "alloc" ) ]
631
+ pub fn append_ascii_to ( & self , buf : & mut alloc:: vec:: Vec < u8 > ) {
632
+ let _ = self . append_to ( buf) ;
633
+ }
634
+
635
+ #[ cfg( feature = "std" ) ]
636
+ pub fn write_ascii_to < W : std:: io:: Write > ( & self , w : W ) -> std:: io:: Result < ( ) > {
637
+ self . append_to ( & mut crate :: util:: WriteAscii ( w) )
638
+ }
574
639
}
575
640
576
641
impl From < Setup > for Epd {
@@ -595,7 +660,7 @@ impl FromStr for Epd {
595
660
596
661
impl Display for Epd {
597
662
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
598
- fmt_epd ( f , & self . 0 )
663
+ self . append_to ( f )
599
664
}
600
665
}
601
666
0 commit comments