Search code examples
pythonrustconcatenationbyte

Python like b-string concatenation in rust


I am currently working on a side project where I am converting some code from python to rust. In python, we can do something like:

Python code->

data = b'commit'+b' '+b'\x00'
print(data)

Output->

b'commit \x00'

Is there any way to achieve this in rust? As I need to concatenate some b'' and store them in a file. Thanks in advance.

I tried using + operator but didn't work and shown error like: cannot add &[u8;6] with &[u8;1]


Solution

  • You have a number of options for combining binary strings. However it sounds the best option for your use case is to use the write! macro. It lets you write bytes the same way you would use the format! and println! macros. This has the benefit of requiring no additional allocation. The write! macro uses UTF-8 encoding (the same as strings in Rust).

    One thing to keep in mind though is that the write! will perform lots of small calls using the std::io::Write trait. To prevent your program from slowing down due to the frequent calls to the OS when writing files you will want to buffer your data using a BufWriter.

    As for zlip this is defiantly doable. In Rust, the most popular library for handling deflate, gzip, and zlib is the flate2 crate. Using this we can wrap a writer to do the compression inline with the rest of the writing process. This lets us save memory and keeps our code tidy.

    use std::fs::File;
    use std::io::{self, BufWriter, Write};
    use flate2::write::ZlibEncoder;
    use flate2::Compression;
    
    pub fn save_commits(path: &str, results: &[&str]) -> io::Result<()> {
        // Open file and wrap it in a buffered writer
        let file = BufWriter::new(File::create(path)?);
        
        // We can then wrap the file in a Zlib encoder so the data we write will
        // be compressed with zlib as we go
        let mut writer = ZlibEncoder::new(file, Compression::best());
        
        // Write our header
        write!(&mut writer, "commit {}\0", results.len())?;
        
        // Write commit hashes
        for hash in results {
            write!(&mut writer, "{}\0", hash);
        }
        
        // This step is not required, but it lets us propogate the error instead of
        // letting the final bytes buffered in the BufferedWriter from being flushed
        // when it gets dropped.writer is dropped.
        writer.by_ref().flush()?;
        
        Ok(())
    }
    

    Additionally, you may find it helpful to read this answer to learn more about how binary strings work in Rust: https://stackoverflow.com/a/68231883/5987669