Saturday, 15 September 2012

io - How should I read the contents of a file respecting endianess? -



io - How should I read the contents of a file respecting endianess? -

ok stupid noob question i'm missing in docs.

i can see in rust can read file byte array with:

file::open(&path::new("fid")).read_to_end();

i can read 1 u32 in either big endian or little endian format with:

file::open(&path::new("fid")).read_be_u32(); file::open(&path::new("fid")).read_le_u32();

but far can see i'm going have (simplified):

let path = path::new("fid"); allow mut file = file::open(&path); allow mut v = vec![]; n in range(1u64, path.stat().unwrap().size/4u64){ v.push(if big { file.read_be_u32() } else { file.read_le_u32() }); }

but that's ugly hell , i'm wondering if there's nicer way this.

ok if in loop big part of ugly hoisted suggested, new version follows:

let path = path::new("fid"); allow mut file = file::open(&path); allow mut v = vec![]; allow fun = if big { ||->ioresult<u32>{file.read_be_u32()} } else { ||->ioresult<u32>{file.read_le_u32()} }; n in range(1u64, path.stat().unwrap().size/4u64){ v.push(fun()); }

learned range_step , using _ index, i'm left with:

let path = path::new("fid"); allow mut file = file::open(&path); allow mut v = vec![]; allow fun = if big { ||->ioresult<u32>{file.read_be_u32()} } else { ||->ioresult<u32>{file.read_le_u32()} }; _ in range_step(0u64, path.stat().unwrap().size,4u64){ v.push(fun().unwrap()); }

any more advice? looking much better.

this solution reads whole file buffer, creates view of buffer words, maps words vector, converting endianness. collect() avoids reallocations of growing mutable vector. mmap file rather reading buffer.

use std::io::file; utilize std::num::{int, num}; fn from_bytes<'a, t: num>(buf: &'a [u8]) -> &'a [t] { unsafe { std::mem::transmute(std::raw::slice { data: buf.as_ptr(), len: buf.len() / std::mem::size_of::<t>() }) } } fn main() { allow buf = file::open(&path::new("fid")).read_to_end().unwrap(); allow words: &[u32] = from_bytes(buf.as_slice()); allow big = true; allow v: vec<u32> = words.iter().map(if big { |&n| { int::from_be(n) } } else { |&n| { int::from_le(n) } }).collect(); println!("{}", v); }

io coding-style rust endianness idiomatic

No comments:

Post a Comment