Feedback on Code That Reads a File Header

Hello, I'm a very inexperienced Rustacean and I'm currently writing a program that reads .shp files. So far, I've put together a module to read the header of the file which is always 100 bytes in length. I'd like to get some feedback before I move on to writing additional modules that read the contents of the files.

use std::fmt;
use std::fs::File;
use std::io::prelude::*;

use byteorder::{ BigEndian, LittleEndian, ReadBytesExt };

pub struct Header {
    file_length: i32,
    version: i32,
    shape_type: i32,
    bbox_xmin: f64,
    bbox_ymin: f64,
    bbox_xmax: f64,
    bbox_ymax: f64,

pub fn read_header(filename: &str) -> Result<Header, std::io::Error> {
    const BUFFER_SIZE: usize = 100;

    let mut file = File::open(&filename)?;
    let mut buffer = [0; BUFFER_SIZE]; buffer)?;

    let mut file_length = &buffer[24..28];
    let mut version = &buffer[28..32];
    let mut shape_type = &buffer[32..36];
    let mut bbox_xmin = &buffer[36..44];
    let mut bbox_ymin = &buffer[44..52];
    let mut bbox_xmax = &buffer[52..60];
    let mut bbox_ymax = &buffer[60..68];

    Ok(Header {
        file_length: file_length.read_i32::<BigEndian>().unwrap(),
        version: version.read_i32::<LittleEndian>().unwrap(),
        shape_type: shape_type.read_i32::<LittleEndian>().unwrap(),
        bbox_xmin: bbox_xmin.read_f64::<LittleEndian>().unwrap(),
        bbox_ymin: bbox_ymin.read_f64::<LittleEndian>().unwrap(),
        bbox_xmax: bbox_xmax.read_f64::<LittleEndian>().unwrap(),
        bbox_ymax: bbox_ymax.read_f64::<LittleEndian>().unwrap(),

Specific questions I have are:

  1. Is it normal to have use statements in each module file or is it possible/idiomatic to have them all in the file and then export them to the modules as needed?
  2. I've defined file_length, version, etc., which point to borrowed slices of my buffer array. I can then call file_length.read_i32, for example, and it works fine. However, I originally tried to do &buffer[24..28].read_i32 and I get an unsatisfied trait bounds error. What's going on there? Why do I have to assign it to a variable first?
  3. When I call, is it just reading the first 100 bytes of the file into my buffer or is it reading the whole file but just keeping the first 100 bytes?

Thanks in advance! I love this community! :heart_eyes:


is the same as &(buffer[24..28].read_i32), not (&buffer[24..28]).read_i32. Please consult the operator precedence table.

This can easily be answered by reading the relevant documentation. It reads at most 100 bytes; you have to check the return value in order to ensure it actually did read that many.

1 Like
  1. Yes, it is normal to have imports in each file.
  2. I believe this should work, though you need to remove the ampersand.
  3. The read call will read between 1 and 100 bytes, and it returns how many bytes it read. Use read_exact to make sure that you are really reading exactly 100 bytes.

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.