use crate::{ WriteFn, ReadFn, read, write, BinError };
use std::io::{ Read, Write, Error };
use byteorder::{ ReadBytesExt, WriteBytesExt, BigEndian };
pub fn null_ascii<R: Read, W: Write>()
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(|r: &mut R| {
let s = read(r, null_utf8())?;
match s.is_ascii() {
true => Ok(s),
false => Err(Error::from(BinError::CheckFail))
}
},
|w: &mut W, s: &String| {
match s.is_ascii() {
true => write(w, s, null_utf8()),
false => panic!("String is not ascii")
}
})
}
pub fn len_ascii<R: Read, W: Write>(len: usize)
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(move |r: &mut R| {
let s = read(r, len_utf8(len))?;
match s.is_ascii() {
true => Ok(s),
false => Err(Error::from(BinError::CheckFail))
}
},
move |w: &mut W, s: &String| {
match s.is_ascii() {
true => write(w, s, len_utf8(len)),
false => panic!("String is not ascii")
}
})
}
pub fn null_utf8<R: Read, W: Write>()
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(|r: &mut R| {
let mut s = Vec::new();
loop {
let c = r.read_u8()?;
match c {
0 => break,
_ => s.push(c)
}
}
String::from_utf8(s)
.map_err(|e| Error::from(BinError::from(e)))
},
|w: &mut W, s: &String| {
w.write_all(&s.as_bytes()[..])
})
}
pub fn len_utf8<R: Read, W: Write>(len: usize)
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(move |r: &mut R| {
let mut s = vec![0; len];
r.read_exact(&mut s[..])?;
String::from_utf8(s)
.map_err(|e| Error::from(BinError::from(e)))
},
move |w: &mut W, s: &String| {
match s.len() == len {
true => w.write_all(&s.as_bytes()[..]),
false => panic!("String's length is invalid")
}
})
}
pub fn null_utf16<R: Read, W: Write>()
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(|r: &mut R| {
let mut s = Vec::new();
loop {
let c = r.read_u16::<BigEndian>()?;
match c {
0 => break,
_ => s.push(c)
}
}
String::from_utf16(&s[..])
.map_err(|e| Error::from(BinError::from(e)))
},
|w: &mut W, s: &String| {
for c in s.encode_utf16() {
w.write_u16::<BigEndian>(c)?;
}
w.write_u16::<BigEndian>(0)
})
}
pub fn len_utf16<R: Read, W: Write>(len: usize)
-> (impl ReadFn<R, String>, impl WriteFn<W, String>) {
(move |r: &mut R| {
let mut s = Vec::new();
for _ in (0..len).step_by(2) {
let c = r.read_u16::<BigEndian>()?;
s.push(c);
}
String::from_utf16(&s[..])
.map_err(|e| Error::from(BinError::from(e)))
},
move |w: &mut W, s: &String| {
match s.len() == len {
true => {
for c in s.encode_utf16() {
w.write_u16::<BigEndian>(c)?;
}
Ok(())
},
false => panic!("String's length is invalid")
}
})
}