How to write 16 bytes to a file?

I am having an issue writing to a file where I want to output 16 bytes. I'm converting a program from C into rust on Linux. In my C program I use fwrite function with the second argument (size_t size) as 2. Here is the C function which outputs the file.

// Write binary to path                                                                                                                                                                                                                       
void WriteBinary(const char *path, const void *data, const unsigned int dataSize)                                                                                                                                                             
{                                                                                                                                                                                                                                             
  FILE *fp = fopen(path, "wb");                                                                                                                                                                                                               
  if (!fp)                                                                                                                                                                                                                                    
    {                                                                                                                                                                                                                                         
      fprintf(stderr, "fopen() failed for '%hn'\n", firstEpromFile);                                                                                                                                                                          
    }                                                                                                                                                                                                                                         
  fwrite(data, 2, dataSize, fp);                                                                                                                                                                                                              
  fclose(fp);                                                                                                                                                                                                                                 
  printf("%d bytes written to \"%s\"\n", dataSize, path);                                                                                                                                                                                     
}     

I have written the "almost" equivalent in Rust but it appears to be outputing only 8 bit values. I can't figure out where I'm going wrong.

 fn main() {                                                                                                                                                                                                                                   
    println!("Build LCD control EPROM Data");                                                                                                                                                                                                 
                                                                                                                                                                                                                                              
    let mut first_eprom_file = vec![0u16; SC_ROM1024];                                                                                                                                                                                        
    for (i, elem) in first_eprom_file.iter_mut().enumerate() {                                                                                                                                                                                
        *elem = build_data(i as u16);                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                              
    let mut file = File::create("eprom_lcd.bin").unwrap();                                                                                                                                                                                    
    file.write_all(unsafe {                                                                                                                                                                                                                   
        std::slice::from_raw_parts(first_eprom_file.as_ptr() as *const u8,                                                                                                                                                                    
                                   first_eprom_file.len() * size_of::<u16>())                                                                                                                                                                 
    }).unwrap();                                                                                                                                                                                                                              
    println!("{} bytes written to \"eprom_lcd.bin\"", first_eprom_file.len() * size_of::<u16>());                                                                                                                                             
}   

I'm fairly certain that the problem is in the file.write_all() with the *const u8 but I'm not 100% sure where it is going wrong. I haven't posted the build_data() but it is just returning 16 bytes based on a simple match statement, and the values are all valid.

hmm, I can't reproduce your error, unfortunately. If I translate your function into a minimal reproducible example on the playground, it writes 16 bytes to the the sink:

use std::io::Write;
use std::mem::size_of;

fn main() {
    const SC_ROM1024: usize = 8;
    
    // 2 bytes * 8 elements = 16 bytes
    let first_eprom_file = vec![0b01000001_01000001_u16; SC_ROM1024];

    let mut file = Vec::new();
    
    let len = size_of::<u16>() * first_eprom_file.len();
    
    file.write_all(unsafe {
        std::slice::from_raw_parts(first_eprom_file.as_ptr() as *const u8, len)
    })
    .unwrap();
    
    assert_eq!(String::from_utf8(file).unwrap(), "AAAAAAAAAAAAAAAA".to_owned());
}

Playground.

2 Likes

I've posted the entire program. I suspect you might have given me the answer with the use std::io::Write;

use std::io::Write;                                                                                                                                                                                                                           
use std::fs::File;                                                                                                                                                                                                                            
use std::mem::size_of;                                                                                                                                                                                                                        
                                                                                                                                                                                                                                              
const SC_ROM1024: usize = 262140;                                                                                                                                                                                                             
const DIGITS: [u16; 10] = [                                                                                                                                                                                                                   
    0x130, //0                                                                                                                                                                                                                                
    0x131, //1                                                                                                                                                                                                                                
    0x132, //2                                                                                                                                                                                                                                
    0x133, //3                                                                                                                                                                                                                                
    0x134, //4                                                                                                                                                                                                                                
    0x135, //5                                                                                                                                                                                                                                
    0x136, //6                                                                                                                                                                                                                                
    0x137, //7                                                                                                                                                                                                                                
    0x138, //8                                                                                                                                                                                                                                
    0x139, //9                                                                                                                                                                                                                                
];                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                              
fn build_data(code: u16) -> u16 {                                                                                                                                                                                                             
    const DISPLAY_ON: u16 = 0x00E; // Turn on display                                                                                                                                                                                         
    const CLEAR_DISPLAY: u16 = 0x001; // Clear screen move cursor home                                                                                                                                                                        
    const NOP: u16 = 0xF00; // Read from LCD (Effectively a NOP instruction)                                                                                                                                                                  
    const SET_FUNCTION: u16 = 0x038; // 8-bit & 1 line & font 5x8                                                                                                                                                                             
    const ENTRY_MODE_SET: u16 = 0x006; // (cursor movement) (direction) (shift)                                                                                                                                                               
                                                                                                                                                                                                                                              
    match code {                                                                                                                                                                                                                              
        0x000..=0x0ff => DISPLAY_ON,                                                                                                                                                                                                          
        0x100..=0x1FF => SET_FUNCTION,                                                                                                                                                                                                        
        0x200..=0x2FF => ENTRY_MODE_SET,                                                                                                                                                                                                      
        0x300..=0x3FF => DIGITS[((code - 0x300) / 100) as usize % 10],                                                                                                                                                                        
        0x400..=0x4FF => DIGITS[((code - 0x400) / 10) as usize % 10],                                                                                                                                                                         
        0x500..=0x5ff => DIGITS[(code - 0x500) as usize % 10],                                                                                                                                                                                
        0xA00..=0xFFF => CLEAR_DISPLAY,                                                                                                                                                                                                       
        _ => NOP,                                                                                                                                                                                                                             
    }                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                              
fn main() {                                                                                                                                                                                                                                   
    println!("Build LCD control EPROM Data");                                                                                                                                                                                                 
                                                                                                                                                                                                                                              
    let mut first_eprom_file = vec![0u16; SC_ROM1024];                                                                                                                                                                                        
    for (i, elem) in first_eprom_file.iter_mut().enumerate() {                                                                                                                                                                                
        *elem = build_data(i as u16);                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                              
    let mut file = File::create("eprom_lcd.bin").unwrap();                                                                                                                                                                                    
    file.write_all(unsafe {                                                                                                                                                                                                                   
        std::slice::from_raw_parts(first_eprom_file.as_ptr() as *const u8,                                                                                                                                                                    
                                   first_eprom_file.len() * size_of::<u16>())                                                                                                                                                                 
    }).unwrap();                                                                                                                                                                                                                              
    println!("{} bytes written to \"eprom_lcd.bin\"", first_eprom_file.len() * size_of::<u16>());                                                                                                                                             
}                                                                                                                                                                                                                                             

But I can't check until I have blanked my eprom again. :slight_smile:

BTW, you don't need the combo of use std::io::Write + File::create + write_all separately. There's std::fs::write(filename, data) function that does all of this in one go.

2 Likes

OK. The issue with the file writing 16 byte data seems to be resolved. Although the C program only writes 262140 bytes as per the constant I defined. However, the Rust version seems to be ignoring the ```
const SC_ROM1024: usize = 262140;

In vec![0u16; SC_ROM1024], SC_ROM1024 is the number of u16 elements, which makes it 2 × SC_ROM1024 bytes.

1 Like

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.