@@ -231,6 +231,133 @@ 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
276
+ Self :: new_uninit ( unsafe { mem:: transmute ( buf) } )
277
+ }
278
+
279
+ /// Creates a new cursor wrapping the provided uninitialized buffer.
280
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
281
+ pub fn new_uninit ( buf : & ' a mut [ mem:: MaybeUninit < u8 > ] ) -> WriteCursor < ' a > {
282
+ WriteCursor { buf, utf8_len : 0 }
283
+ }
284
+
285
+ /// Returns the total capacity of the cursor's underlying buffer, in bytes.
286
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
287
+ pub fn capacity ( & self ) -> usize {
288
+ self . buf . len ( )
289
+ }
290
+
291
+ /// Returns how many bytes have been written to the cursor's underlying buffer.
292
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
293
+ pub fn written ( & self ) -> usize {
294
+ self . utf8_len
295
+ }
296
+
297
+ /// Returns the written portion of the cursor's underlying buffer as a
298
+ /// byte slice.
299
+ ///
300
+ /// The returned slice contains valid UTF-8.
301
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
302
+ pub fn as_bytes ( & self ) -> & [ u8 ] {
303
+ let utf8 = & self . buf [ ..self . utf8_len ] ;
304
+ // SAFETY: The buffer is incrementally initialized by `write_str`, which
305
+ // updates `utf8_len`.
306
+ unsafe { mem:: MaybeUninit :: slice_assume_init_ref ( utf8) }
307
+ }
308
+
309
+ /// Consumes the cursor and returns the written portion of the cursor's
310
+ /// underlying buffer as a byte slice.
311
+ ///
312
+ /// The returned slice contains valid UTF-8.
313
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
314
+ pub fn into_bytes ( self ) -> & ' a [ u8 ] {
315
+ let utf8 = & self . buf [ ..self . utf8_len ] ;
316
+ // SAFETY: The buffer is incrementally initialized by `write_str`, which
317
+ // updates `utf8_len`.
318
+ unsafe { mem:: MaybeUninit :: slice_assume_init_ref ( utf8) }
319
+ }
320
+
321
+ /// Returns the written portion of the cursor's underlying buffer as a `&str`.
322
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
323
+ pub fn as_str ( & self ) -> & str {
324
+ // SAFETY: The buffer is only initialized by copying from `str` values.
325
+ unsafe { str:: from_utf8_unchecked ( self . as_bytes ( ) ) }
326
+ }
327
+
328
+ /// Consumes the cursor and returns the written portion of the cursor's
329
+ /// underlying buffer as a `&str`.
330
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
331
+ pub fn into_str ( self ) -> & ' a str {
332
+ // SAFETY: The buffer is only initialized by copying from `str` values.
333
+ unsafe { str:: from_utf8_unchecked ( self . into_bytes ( ) ) }
334
+ }
335
+
336
+ /// Allows the [`write!`] macro to write to a `WriteCursor`.
337
+ ///
338
+ /// This method should generally not be invoked manually. It exists so that
339
+ /// the `write!` macro can write to a `WriteCursor` without needing a
340
+ /// `use std::fmt::Write` declaration.
341
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
342
+ pub fn write_fmt ( & mut self , args : Arguments < ' _ > ) -> Result {
343
+ Write :: write_fmt ( self , args)
344
+ }
345
+ }
346
+
347
+ #[ unstable( feature = "fmt_write_cursor" , issue = "none" ) ]
348
+ impl Write for WriteCursor < ' _ > {
349
+ fn write_str ( & mut self , s : & str ) -> Result {
350
+ let b = s. as_bytes ( ) ;
351
+ let avail = & mut self . buf [ self . utf8_len ..] ;
352
+ if b. len ( ) > avail. len ( ) {
353
+ return Err ( Error ) ;
354
+ }
355
+ mem:: MaybeUninit :: write_slice ( & mut avail[ ..b. len ( ) ] , b) ;
356
+ self . utf8_len += b. len ( ) ;
357
+ Ok ( ( ) )
358
+ }
359
+ }
360
+
234
361
/// Configuration for formatting.
235
362
///
236
363
/// A `Formatter` represents various options related to formatting. Users do not
0 commit comments