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