use std::error;
use std::fmt;
use std::io;
use std::result;
use std::slice;
use std::string;
pub struct JavaDataInput<R> {
reader: R,
buf: Option<u8>,
}
pub struct JavaDataOutput<W> {
writer: W,
}
pub type JavaChar = u16;
pub type JavaString = Vec<JavaChar>;
pub type JavaCharSequence = [JavaChar];
pub fn to_java_string(s: &str) -> JavaString {
s.encode_utf16().collect()
}
pub fn from_java_string(s: &JavaCharSequence) -> result::Result<String, string::FromUtf16Error> {
String::from_utf16(s)
}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
IoError(io::Error),
UtfDataFormatError,
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::IoError(error)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
match self {
IoError(ref e) => fmt::Display::fmt(e, f),
UtfDataFormatError => write!(f, "UtfDataFormatError"),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
use Error::*;
match self {
IoError(ref e) => Some(e),
UtfDataFormatError => None,
}
}
}
impl<R: io::Read> JavaDataInput<R> {
pub fn new(reader: R) -> Self {
Self { reader, buf: None }
}
pub fn read_fully(&mut self, buf: &mut [u8]) -> Result<()> {
if let Some(c) = self.buf.take() {
if buf.is_empty() {
self.buf = Some(c);
return Ok(());
}
buf[0] = c;
self.reader.read_exact(&mut buf[1..])?;
} else {
self.reader.read_exact(buf)?;
}
Ok(())
}
pub fn read_double(&mut self) -> Result<f64> {
let mut buf = [0; 8];
self.read_fully(&mut buf)?;
Ok(f64::from_be_bytes(buf))
}
pub fn read_float(&mut self) -> Result<f32> {
let mut buf = [0; 4];
self.read_fully(&mut buf)?;
Ok(f32::from_be_bytes(buf))
}
pub fn read_long(&mut self) -> Result<i64> {
let mut buf = [0; 8];
self.read_fully(&mut buf)?;
Ok(i64::from_be_bytes(buf))
}
pub fn read_int(&mut self) -> Result<i32> {
let mut buf = [0; 4];
self.read_fully(&mut buf)?;
Ok(i32::from_be_bytes(buf))
}
pub fn read_short(&mut self) -> Result<i16> {
let mut buf = [0; 2];
self.read_fully(&mut buf)?;
Ok(i16::from_be_bytes(buf))
}
pub fn read_unsigned_short(&mut self) -> Result<u16> {
let mut buf = [0; 2];
self.read_fully(&mut buf)?;
Ok(u16::from_be_bytes(buf))
}
pub fn read_byte(&mut self) -> Result<i8> {
let mut b = 0;
self.read_fully(slice::from_mut(&mut b))?;
Ok(b as i8)
}
pub fn read_unsigned_byte(&mut self) -> Result<u8> {
let mut b = 0;
self.read_fully(slice::from_mut(&mut b))?;
Ok(b)
}
pub fn read_boolean(&mut self) -> Result<bool> {
let mut b = 0;
self.read_fully(slice::from_mut(&mut b))?;
Ok(b != 0)
}
pub fn read_char(&mut self) -> Result<JavaChar> {
let mut buf = [0; 2];
self.read_fully(&mut buf)?;
Ok(JavaChar::from_be_bytes(buf))
}
fn get_byte(&mut self) -> Result<u8> {
let mut b: u8 = 0;
self.reader.read_exact(slice::from_mut(&mut b))?;
Ok(b)
}
pub fn read_utf(&mut self) -> Result<JavaString> {
let size = self.read_unsigned_short()?;
let mut ret = JavaString::new();
let mut len = 0;
while len < size {
let a = self.get_byte()? as JavaChar;
if (a & 0xF0) == 0xF0 {
return Err(Error::UtfDataFormatError);
}
if (a & 0xC0) == 0x80 {
return Err(Error::UtfDataFormatError);
}
if a < 0x80 {
ret.push(a);
len += 1;
} else if a < (0x80 | 0x40 | 0x20) {
let b = self.get_byte()? as JavaChar;
if (b & 0xC0) != 0x80 {
return Err(Error::UtfDataFormatError);
}
ret.push(((a & 0x1f) << 6) | (b & 0x3f));
len += 2;
} else {
let b = self.get_byte()? as JavaChar;
if (b & 0xC0) != 0x80 {
return Err(Error::UtfDataFormatError);
}
let c = self.get_byte()? as JavaChar;
if (c & 0xC0) != 0x80 {
return Err(Error::UtfDataFormatError);
}
ret.push(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
len += 3;
}
}
if len > size {
return Err(Error::UtfDataFormatError);
}
Ok(ret)
}
pub fn read_line(&mut self) -> Result<Option<JavaString>> {
let mut b: u8 = 0;
let mut ret = JavaString::new();
if let Some(c) = self.buf.take() {
if c == b'\r' {
return Ok(Some(ret));
}
ret.push(c as JavaChar);
}
loop {
let size = self.reader.read(slice::from_mut(&mut b))?;
if size == 0 {
if ret.is_empty() {
return Ok(None);
}
break;
}
if b == b'\n' {
break;
}
if b == b'\r' {
let size = self.reader.read(slice::from_mut(&mut b))?;
if size > 0 && b != b'\n' {
self.buf = Some(b);
}
break;
}
ret.push(b as JavaChar);
}
Ok(Some(ret))
}
pub fn skip_bytes(&mut self, n: i32) -> Result<i32> {
if n == 0 {
return Ok(0);
}
let mut b: u8 = 0;
let s = if self.buf.take().is_some() { 1 } else { 0 };
for i in s..n {
let size = self.reader.read(slice::from_mut(&mut b))?;
if size == 0 {
return Ok(i);
}
}
Ok(n)
}
}
impl<W: io::Write> JavaDataOutput<W> {
pub fn new(writer: W) -> Self {
Self { writer }
}
pub fn flush(&mut self) -> Result<()> {
self.writer.flush()?;
Ok(())
}
pub fn write(&mut self, buf: &[u8]) -> Result<()> {
self.writer.write_all(buf)?;
Ok(())
}
pub fn write_double(&mut self, v: f64) -> Result<()> {
self.write(&v.to_be_bytes())
}
pub fn write_float(&mut self, v: f32) -> Result<()> {
self.write(&v.to_be_bytes())
}
pub fn write_long(&mut self, v: i64) -> Result<()> {
self.write(&v.to_be_bytes())
}
pub fn write_int(&mut self, v: i32) -> Result<()> {
self.write(&v.to_be_bytes())
}
pub fn write_short(&mut self, v: i32) -> Result<()> {
let v: i16 = (v & 0xFFFF) as i16;
self.write(&v.to_be_bytes())
}
pub fn write_byte(&mut self, v: i32) -> Result<()> {
let v: u8 = (v & 0xFF) as u8;
self.write(slice::from_ref(&v))
}
pub fn write_boolean(&mut self, v: bool) -> Result<()> {
self.write_byte(i32::from(v))
}
pub fn write_char(&mut self, v: i32) -> Result<()> {
let v: JavaChar = (v & 0xFFFF) as JavaChar;
self.write(&v.to_be_bytes())
}
pub fn write_bytes(&mut self, s: &JavaCharSequence) -> Result<()> {
for c in s.iter() {
self.write_byte(*c as i32)?;
}
Ok(())
}
pub fn write_chars(&mut self, s: &JavaCharSequence) -> Result<()> {
for c in s.iter() {
self.write_char(*c as i32)?;
}
Ok(())
}
pub fn write_utf(&mut self, s: &JavaCharSequence) -> Result<()> {
let mut size: u64 = 0;
for &c in s.iter() {
if 0x0000 < c && c < 0x0080 {
size += 1;
} else if c < 0x0800 {
size += 2;
} else {
size += 3;
}
}
if size > 0xFFFF {
return Err(Error::UtfDataFormatError);
}
self.write_short(size as i32)?;
for &c in s.iter() {
if 0x0000 < c && c < 0x0080 {
self.write_byte(c as i32)?;
} else if c < 0x0800 {
self.write_byte(0xC0 | (0x1F & (c >> 6)) as i32)?;
self.write_byte(0x80 | (0x3F & c) as i32)?;
} else {
self.write_byte(0xE0 | (0x0F & (c >> 12)) as i32)?;
self.write_byte(0x80 | (0x3F & (c >> 6)) as i32)?;
self.write_byte(0x80 | (0x3F & c) as i32)?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
use std::io;
let b = [
0_i8, 11, -29, -127, -126, -29, -127, -124, -29, -127, -122, 68, 120, -56, 66, 35, -19,
-94, 68, -7, -66, -80, -121, -67, -1, 0, 0, 18, 8, 0, 1, -122, -89, 0, 1, -122, -89,
-79, -41, -3, -23, -128, -6, 1, 0, 97, 98, 99, 100, 101, 49, 50, 51, 52, 53, 83, 65,
77, 80, 76, 69, 10, 115, 97, 109, 112, 108, 101, 10, 65, 66, 67, 68, 69,
]
.iter()
.map(|x| *x as u8)
.collect::<Vec<_>>();
{
let cur = io::Cursor::new(b.as_slice());
let mut jdi = crate::JavaDataInput::new(cur);
let utf = jdi.read_utf().unwrap();
let st = crate::from_java_string(&utf).unwrap();
assert_eq!(st.as_str(), "あいうDx");
let db = jdi.read_double().unwrap();
assert_eq!(db, -1.23456789e40);
let fl = jdi.read_float().unwrap();
assert_eq!(fl, -9.87654321e-10);
let lg = jdi.read_long().unwrap();
assert_eq!(lg, 100007 + (1 << 35) + (1 << 41) + (1 << 44));
let it = jdi.read_int().unwrap();
assert_eq!(it, 100007);
let sh = jdi.read_short().unwrap();
assert_eq!(sh, -20009);
let us = jdi.read_unsigned_short().unwrap();
assert_eq!(us, 65001);
let bt = jdi.read_byte().unwrap();
assert_eq!(bt, -128);
let ub = jdi.read_unsigned_byte().unwrap();
assert_eq!(ub, 250);
let tb = jdi.read_boolean().unwrap();
assert_eq!(tb, true);
let fb = jdi.read_boolean().unwrap();
assert_eq!(fb, false);
let mut bs = [0; 10];
jdi.read_fully(&mut bs).unwrap();
assert_eq!(bs.as_ref(), b"abcde12345");
let ln1 = jdi.read_line().unwrap().unwrap();
let ln1 = crate::from_java_string(&ln1).unwrap();
assert_eq!(ln1.as_str(), "SAMPLE");
let ln2 = jdi.read_line().unwrap().unwrap();
let ln2 = crate::from_java_string(&ln2).unwrap();
assert_eq!(ln2.as_str(), "sample");
let ln3 = jdi.read_line().unwrap().unwrap();
let ln3 = crate::from_java_string(&ln3).unwrap();
assert_eq!(ln3.as_str(), "ABCDE");
}
let mut d = Vec::new();
{
let mut jdo = crate::JavaDataOutput::new(&mut d);
let utf = crate::to_java_string("あいうDx");
jdo.write_utf(&utf).unwrap();
jdo.write_double(-1.23456789e40).unwrap();
jdo.write_float(-9.87654321e-10).unwrap();
let lg: i64 = 100007 + (1 << 35) + (1 << 41) + (1 << 44);
jdo.write_long(lg).unwrap();
jdo.write_int(100007).unwrap();
jdo.write_short(-20009).unwrap();
jdo.write_char(65001).unwrap();
jdo.write_byte(-128).unwrap();
jdo.write_byte(250).unwrap();
jdo.write_boolean(true).unwrap();
jdo.write_boolean(false).unwrap();
let bs = crate::to_java_string("abcde12345");
jdo.write_bytes(&bs).unwrap();
let ln = crate::to_java_string("SAMPLE\nsample\nABCDE");
jdo.write_bytes(&ln).unwrap();
jdo.flush().unwrap();
}
assert_eq!(d, b);
let b2 = [
48_i8, -94, 48, -85, 48, -75, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 48, -65, 48, -54, 48, -49, 48,
-34, 48, -28, 48, -23, 48, -17,
]
.iter()
.map(|x| *x as u8)
.collect::<Vec<_>>();
{
let cur2 = io::Cursor::new(b2.as_slice());
let mut jdi2 = crate::JavaDataInput::new(cur2);
for ch in crate::to_java_string("アカサ").iter() {
let c = jdi2.read_char().unwrap();
assert_eq!(c, *ch);
}
let sb = jdi2.skip_bytes(31).unwrap();
assert_eq!(sb, 31);
for ch in crate::to_java_string("タナハマヤラワ").iter() {
let c = jdi2.read_char().unwrap();
assert_eq!(c, *ch);
}
}
let mut d2 = Vec::new();
{
let mut jdo2 = crate::JavaDataOutput::new(&mut d2);
for ch in crate::to_java_string("アカサ").iter() {
jdo2.write_char(*ch as i32).unwrap();
}
let sb: Vec<_> = (0_u8..31).into_iter().collect();
jdo2.write(&sb).unwrap();
let s = crate::to_java_string("タナハマヤラワ");
jdo2.write_chars(&s).unwrap();
}
assert_eq!(d2, b2);
}
}