1 //! This module contains code to read and write fileformats that are used by Jagged Alliance 2 2 3 use std::io::ErrorKind::{InvalidData, InvalidInput}; 4 use std::io::{Error, Read, Result, Write}; 5 6 pub mod slf; 7 8 /// Trait that adds extra functions to Read. 9 pub trait StracciatellaReadExt: Read { 10 /// Reads and discards unused bytes. read_unused(&mut self, num_bytes: usize) -> Result<()>11 fn read_unused(&mut self, num_bytes: usize) -> Result<()> { 12 let mut buffer = vec![0u8; num_bytes]; 13 self.read_exact(&mut buffer)?; 14 Ok(()) 15 } 16 17 /// Reads a nul terminated fixed size string. read_fixed_string(&mut self, num_bytes: usize) -> Result<String>18 fn read_fixed_string(&mut self, num_bytes: usize) -> Result<String> { 19 let mut buffer = vec![0u8; num_bytes]; 20 self.read_exact(&mut buffer)?; 21 // must be nul terminated and valid utf8 22 match buffer.iter().position(|&byte| byte == 0) { 23 Some(position) => match ::std::str::from_utf8(&buffer[..position]) { 24 Ok(s) => Ok(s.to_string()), 25 Err(e) => Err(Error::new(InvalidData, e)), 26 }, 27 None => Err(Error::new(InvalidData, "string is not nul terminated")), 28 } 29 } 30 } 31 32 /// Trait that adds extra functions to Write. 33 pub trait StracciatellaWriteExt: Write { 34 /// Writes zeroed unused bytes. write_unused(&mut self, num_bytes: usize) -> Result<()>35 fn write_unused(&mut self, num_bytes: usize) -> Result<()> { 36 let buffer = vec![0u8; num_bytes]; 37 self.write_all(&buffer) 38 } 39 40 /// Write a nul terminated fixed size string, unused space is zeroed. write_fixed_string(&mut self, num_bytes: usize, string: &str) -> Result<()>41 fn write_fixed_string(&mut self, num_bytes: usize, string: &str) -> Result<()> { 42 let mut buffer = vec![0u8; num_bytes]; 43 let string_bytes = string.as_bytes(); 44 if string_bytes.len() >= buffer.len() { 45 return Err(Error::new(InvalidInput, "string is too long")); 46 } 47 buffer[..string_bytes.len()].copy_from_slice(&string_bytes); 48 self.write_all(&buffer)?; 49 Ok(()) 50 } 51 } 52 53 /// Everything that implements Read gets Ja2WriteExt for free. 54 impl<T: Read + ?Sized> StracciatellaReadExt for T {} 55 56 /// Everything that implements Write gets Ja2WriteExt for free. 57 impl<T: Write + ?Sized> StracciatellaWriteExt for T {} 58