summaryrefslogtreecommitdiff
path: root/matrix-lang/src/binary/prim.rs
diff options
context:
space:
mode:
Diffstat (limited to 'matrix-lang/src/binary/prim.rs')
-rw-r--r--matrix-lang/src/binary/prim.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/matrix-lang/src/binary/prim.rs b/matrix-lang/src/binary/prim.rs
new file mode 100644
index 0000000..44e6898
--- /dev/null
+++ b/matrix-lang/src/binary/prim.rs
@@ -0,0 +1,109 @@
+use super::Primitive;
+use std::io::{self, Read, Write};
+
+macro_rules! marshal_number {
+ ($type:ident, $byte:expr) => {
+ impl Primitive for $type {
+ fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
+ write.write(&self.to_le_bytes())?;
+ Ok(())
+ }
+
+ fn read<R: Read>(read: &mut R) -> io::Result<Self> {
+ let mut bytes = [0u8; $byte];
+ read.read_exact(&mut bytes)?;
+ Ok(Self::from_le_bytes(bytes))
+ }
+ }
+ };
+}
+
+marshal_number!(u8, 1);
+marshal_number!(u16, 2);
+marshal_number!(i16, 2);
+marshal_number!(u32, 4);
+marshal_number!(i64, 8);
+marshal_number!(f64, 8);
+
+impl Primitive for bool {
+ fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
+ if *self {
+ write.write(&[1u8; 1])?;
+ } else {
+ write.write(&[0u8; 1])?;
+ }
+ Ok(())
+ }
+
+ fn read<R: Read>(read: &mut R) -> io::Result<Self> {
+ let mut bytes = [0u8; 1];
+ read.read_exact(&mut bytes)?;
+ if bytes[0] == 1 {
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+}
+
+impl Primitive for String {
+ fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
+ let bytes = self.as_bytes();
+ let len = bytes.len();
+ write.write(&(len as u32).to_le_bytes())?;
+ write.write(&bytes)?;
+ Ok(())
+ }
+
+ fn read<R: Read>(read: &mut R) -> io::Result<Self> {
+ let len = usize::read(read)?;
+ let mut bytes = vec![0u8; len];
+ read.read_exact(&mut bytes)?;
+ Ok(String::from_utf8_lossy(bytes.as_slice()).to_string())
+ }
+}
+
+impl Primitive for usize {
+ fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
+ (*self as u32).write(write)
+ }
+
+ fn read<R: Read>(read: &mut R) -> io::Result<Self> {
+ Ok(u32::read(read)? as usize)
+ }
+}
+
+pub struct VarInt(pub usize);
+
+impl Primitive for VarInt {
+ fn write<W: Write>(&self, write: &mut W) -> io::Result<()> {
+ let mut data = self.0;
+ loop {
+ let mut byte = (data & 0x7F) as u8;
+ data >>= 7;
+ if data != 0 {
+ byte += 0x80;
+ }
+ write.write(&[byte; 1])?;
+ if data == 0 {
+ return Ok(())
+ }
+ }
+ }
+
+ fn read<R: Read>(read: &mut R) -> io::Result<Self> {
+ let mut buf = [0];
+ let mut result = 0usize;
+ for count in 0..8 {
+ if read.read(&mut buf)? != 1 {
+ return Ok(Self(0))
+ }
+ let byte = buf[0];
+ result |= ((byte & 0x7F) as usize) << (7 * count);
+ if byte & 0x80 == 0 {
+ return Ok(Self(result))
+ }
+ }
+ Ok(Self(0))
+ }
+}