@@ -231,6 +231,134 @@ impl<W: Write + ?Sized> Write for &mut W {
231
231
}
232
232
}
233
233
234
+ /// A `WriteCursor` implements [`fmt::Write`] by writing to an in-memory buffer.
235
+ ///
236
+ /// [`fmt::Write`]: self::Write
237
+ ///
238
+ /// # Examples
239
+ ///
240
+ /// ```
241
+ /// #![feature(fmt_write_cursor)]
242
+ /// use std::fmt::WriteCursor;
243
+ ///
244
+ /// # fn test_write_cursor() -> std::fmt::Result {
245
+ /// let mut buf = [0u8; 5];
246
+ /// let mut cursor = WriteCursor::new(&mut buf);
247
+ /// write!(cursor, "{}", 12345)?;
248
+ /// assert_eq!(cursor.as_str(), "12345");
249
+ /// assert_eq!(&buf, b"12345");
250
+ /// # Ok(())
251
+ /// # }
252
+ /// ```
253
+ #[ doc( alias = "sprintf" ) ]
254
+ #[ doc( alias = "snprintf" ) ]
255
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
256
+ pub struct WriteCursor < ' a > {
257
+ buf : & ' a mut [ mem:: MaybeUninit < u8 > ] ,
258
+ utf8_len : usize ,
259
+ }
260
+
261
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
262
+ impl Debug for WriteCursor < ' _ > {
263
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
264
+ f. debug_struct ( "WriteCursor" )
265
+ . field ( "capacity" , & self . capacity ( ) )
266
+ . field ( "written" , & self . written ( ) )
267
+ . finish ( )
268
+ }
269
+ }
270
+
271
+ impl < ' a > WriteCursor < ' a > {
272
+ /// Creates a new cursor wrapping the provided buffer.
273
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
274
+ pub fn new ( buf : & ' a mut [ u8 ] ) -> WriteCursor < ' a > {
275
+ // SAFETY: [T] and [MaybeUninit<T>] have the same layout, and this
276
+ // code never writes uninitialized data to the buffer.
277
+ Self :: new_uninit ( unsafe { mem:: transmute ( buf) } )
278
+ }
279
+
280
+ /// Creates a new cursor wrapping the provided uninitialized buffer.
281
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
282
+ pub fn new_uninit ( buf : & ' a mut [ mem:: MaybeUninit < u8 > ] ) -> WriteCursor < ' a > {
283
+ WriteCursor { buf, utf8_len : 0 }
284
+ }
285
+
286
+ /// Returns the total capacity of the cursor's underlying buffer, in bytes.
287
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
288
+ pub fn capacity ( & self ) -> usize {
289
+ self . buf . len ( )
290
+ }
291
+
292
+ /// Returns how many bytes have been written to the cursor's underlying buffer.
293
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
294
+ pub fn written ( & self ) -> usize {
295
+ self . utf8_len
296
+ }
297
+
298
+ /// Returns the written portion of the cursor's underlying buffer as a
299
+ /// byte slice.
300
+ ///
301
+ /// The returned slice contains valid UTF-8.
302
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
303
+ pub fn as_bytes ( & self ) -> & [ u8 ] {
304
+ let utf8 = & self . buf [ ..self . utf8_len ] ;
305
+ // SAFETY: The buffer is incrementally initialized by `write_str`, which
306
+ // updates `utf8_len`.
307
+ unsafe { mem:: MaybeUninit :: slice_assume_init_ref ( utf8) }
308
+ }
309
+
310
+ /// Consumes the cursor and returns the written portion of the cursor's
311
+ /// underlying buffer as a byte slice.
312
+ ///
313
+ /// The returned slice contains valid UTF-8.
314
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
315
+ pub fn into_bytes ( self ) -> & ' a mut [ u8 ] {
316
+ let utf8 = & mut self . buf [ ..self . utf8_len ] ;
317
+ // SAFETY: The buffer is incrementally initialized by `write_str`, which
318
+ // updates `utf8_len`.
319
+ unsafe { mem:: MaybeUninit :: slice_assume_init_mut ( utf8) }
320
+ }
321
+
322
+ /// Returns the written portion of the cursor's underlying buffer as a `&str`.
323
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
324
+ pub fn as_str ( & self ) -> & str {
325
+ // SAFETY: The buffer is only initialized by copying from `str` values.
326
+ unsafe { str:: from_utf8_unchecked ( self . as_bytes ( ) ) }
327
+ }
328
+
329
+ /// Consumes the cursor and returns the written portion of the cursor's
330
+ /// underlying buffer as a `&str`.
331
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
332
+ pub fn into_str ( self ) -> & ' a mut str {
333
+ // SAFETY: The buffer is only initialized by copying from `str` values.
334
+ unsafe { str:: from_utf8_unchecked_mut ( self . into_bytes ( ) ) }
335
+ }
336
+
337
+ /// Allows the [`write!`] macro to write to a `WriteCursor`.
338
+ ///
339
+ /// This method should generally not be invoked manually. It exists so that
340
+ /// the `write!` macro can write to a `WriteCursor` without needing a
341
+ /// `use std::fmt::Write` declaration.
342
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
343
+ pub fn write_fmt ( & mut self , args : Arguments < ' _ > ) -> Result {
344
+ Write :: write_fmt ( self , args)
345
+ }
346
+ }
347
+
348
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
349
+ impl Write for WriteCursor < ' _ > {
350
+ fn write_str ( & mut self , s : & str ) -> Result {
351
+ let b = s. as_bytes ( ) ;
352
+ let avail = & mut self . buf [ self . utf8_len ..] ;
353
+ if b. len ( ) > avail. len ( ) {
354
+ return Err ( Error ) ;
355
+ }
356
+ mem:: MaybeUninit :: write_slice ( & mut avail[ ..b. len ( ) ] , b) ;
357
+ self . utf8_len += b. len ( ) ;
358
+ Ok ( ( ) )
359
+ }
360
+ }
361
+
234
362
/// Configuration for formatting.
235
363
///
236
364
/// A `Formatter` represents various options related to formatting. Users do not
0 commit comments