Weird behaviour of impl<const N: usize> Write for Cursor<[u8; N]>

Hello y'all

I've been writing some test code and encountered this gem:
link to playground

use std::io::Write;
fn main() {
    let buff = [0u8; 1024];
    let mut crs = std::io::Cursor::new(buff);
    
    let _ = write!(&mut crs, "Hello there");
    let _ = crs.flush();
    
    let mut buff2 = [0u8; 1024];
    let mut crs2 = std::io::Cursor::new(&mut buff2[..]);
    
    let _ = write!(&mut crs2, "Hello there");
    let _ = crs2.flush();
    
    println!("Result: {} :<", String::from_utf8_lossy(&buff));
// Result:  :<
    println!("Expected: {} :)", String::from_utf8_lossy(&buff2));
// Expected: Hello there :)
}

Would you agree this behaviour is unexpected?
Does Cursor::new(buff) crate a copy of that buffer internally?
If not why doesn't rustc complain the buff was moved when used again in println!?

You move buff into the Cursor, then print a copy of the original zeroed buff, since [u8; 1024] is Copy.

not at all.

are you coming from C/C++ background? it's importantly to note, a rust array is a value; in rust, an array does NOT decay into a pointer when passed as function arguments.

yes. Cursor<T> is a wrapper that owns (as opposed to borrows) T.

because an array is Copy if the element type is Copy:

2 Likes

I suppose the reason for having impl Write for Cursor<[u8; N]> is to finally call into_inner(), for use in a case where the Cursor should be static (not borrowing the buffer from somewhere else).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.