Storing and modifying an optional within a struct

I'm writing some code that writes content to files that are rotated hourly. My current approach has a struct that holds an Option<std::io::BufWriter<std::fs::File>> and a number representing the current hour.

I wish to make the current_file optional so that it doesn't create an empty file when the struct is created, in case there is no content written to it later.

I've come up with this code on the Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=84f959f2ee8fad82990dcadd1b1c64d2

This compiles and appears to run fine, I'm just looking to see if there are any other/better approaches to this kind of thing?

Note that the code in the Playground is altered from the real code - in the real code, the content is passed to write_some_content and the hour comes from a DateTime<Local> from chrono. In the real code, the path to the file is worked out based on the date/time and a base path string, creating files like /tmp/2020/08/07/10.txt - this is done in a separate function, but I wanted to keep the playground simple.

In the real code, the FileWriter is only used on a single thread, so I'm not worried about any threading issues - the FileWriter completely owns the BufWriter.

How about this?

fn write_some_content(&mut self, hour: u32) -> Result<(), std::io::Error> {
    if self.current_hour != hour {
        if let Some(writer) = self.current_file.as_mut() {
            writer.flush()?;
        }
        self.current_file = None;
        self.current_hour = hour;
    }

    let writer = match &mut self.current_file {
        Some(writer) => writer,
        None => {
            let new = BufWriter::with_capacity(
                Self::BUFFER_SIZE,
                OpenOptions::new()
                    .create(true)
                    .append(true)
                    .open("/tmp/test.txt")?
            );
            self.current_file.get_or_insert(new)
        }
    };
    
    writer.write(b"test")?;
    
    Ok(())
}
1 Like

Ah, I'd missed that get_or_insert is a thing - that could make it much cleaner! Thanks very much, I shall give it a go.

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.