Refactor internal I/O helpers into traits
This commit is contained in:
parent
e509969033
commit
9ca398af11
5 changed files with 496 additions and 494 deletions
|
|
@ -27,9 +27,9 @@ impl ComponentData for CircuitBoard {
|
|||
const TYPE_STRING: &'static str = "MHG.CircuitBoard";
|
||||
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let color = read_array(|| read_u8(reader))?;
|
||||
let size_x = read_u32(reader)?;
|
||||
let size_z = read_u32(reader)?;
|
||||
let color = ReadFrom::read_from(reader)?;
|
||||
let size_x = ReadFrom::read_from(reader)?;
|
||||
let size_z = ReadFrom::read_from(reader)?;
|
||||
Ok(Self {
|
||||
color,
|
||||
size_x,
|
||||
|
|
@ -38,11 +38,9 @@ impl ComponentData for CircuitBoard {
|
|||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
for x in self.color {
|
||||
write_u8(x, writer)?;
|
||||
}
|
||||
write_u32(self.size_x, writer)?;
|
||||
write_u32(self.size_z, writer)?;
|
||||
self.color.write_to(writer)?;
|
||||
self.size_x.write_to(writer)?;
|
||||
self.size_z.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
178
src/io.rs
178
src/io.rs
|
|
@ -1,104 +1,112 @@
|
|||
use crate::error::Error;
|
||||
use std::io::{Read, Write};
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
iter::repeat_with,
|
||||
};
|
||||
|
||||
pub fn read_u8<R: Read>(reader: &mut R) -> Result<u8, Error> {
|
||||
let mut bytes = [0u8; 1];
|
||||
pub trait ReadFrom: Sized {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
pub trait ReadFromSeed<Seed>: Sized {
|
||||
fn read_from_seed<R: Read>(reader: &mut R, seed: Seed) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
impl<T: ReadFrom> ReadFromSeed<()> for T {
|
||||
fn read_from_seed<R: Read>(reader: &mut R, seed: ()) -> Result<Self, Error> {
|
||||
let _ = seed;
|
||||
Self::read_from(reader)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WriteTo {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
macro_rules! primitive_io {
|
||||
($($t:ty: $len:literal,)*) => {$(
|
||||
impl ReadFrom for $t {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let mut bytes = [0u8; $len];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
Ok(u8::from_le_bytes(bytes))
|
||||
Ok(<$t>::from_le_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_u8<W: Write>(v: u8, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&v.to_le_bytes())?;
|
||||
impl WriteTo for $t {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&self.to_le_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_u16<R: Read>(reader: &mut R) -> Result<u16, Error> {
|
||||
let mut bytes = [0u8; 2];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
Ok(u16::from_le_bytes(bytes))
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
pub fn write_u16<W: Write>(v: u16, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&v.to_le_bytes())?;
|
||||
Ok(())
|
||||
primitive_io! {
|
||||
u8: 1,
|
||||
u16: 2,
|
||||
i32: 4,
|
||||
u32: 4,
|
||||
f32: 4,
|
||||
}
|
||||
|
||||
pub fn read_i32<R: Read>(reader: &mut R) -> Result<i32, Error> {
|
||||
let mut bytes = [0u8; 4];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
Ok(i32::from_le_bytes(bytes))
|
||||
impl ReadFrom for usize {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
i32::read_from(reader).and_then(|x| Self::try_from(x).map_err(|_| Error::InvalidSave))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_i32<W: Write>(v: i32, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&v.to_le_bytes())?;
|
||||
Ok(())
|
||||
impl WriteTo for usize {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
i32::try_from(*self)
|
||||
.map_err(|_| Error::InvalidSave)
|
||||
.and_then(|x| x.write_to(writer))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_u32<R: Read>(reader: &mut R) -> Result<u32, Error> {
|
||||
let mut bytes = [0u8; 4];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
Ok(u32::from_le_bytes(bytes))
|
||||
pub struct Length(pub usize);
|
||||
|
||||
impl<T: ReadFrom> ReadFromSeed<Length> for Vec<T> {
|
||||
fn read_from_seed<R: Read>(reader: &mut R, seed: Length) -> Result<Self, Error> {
|
||||
repeat_with(|| T::read_from(reader)).take(seed.0).collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_u32<W: Write>(v: u32, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&v.to_le_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_f32<R: Read>(reader: &mut R) -> Result<f32, Error> {
|
||||
let mut bytes = [0u8; 4];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
Ok(f32::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
pub fn write_f32<W: Write>(v: f32, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(&v.to_le_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_usize<R: Read>(reader: &mut R) -> Result<usize, Error> {
|
||||
read_i32(reader)?.try_into().map_err(|_| Error::InvalidSave)
|
||||
}
|
||||
|
||||
pub fn write_usize<W: Write>(v: usize, writer: &mut W) -> Result<(), Error> {
|
||||
let v: i32 = v.try_into().map_err(|_| Error::InvalidSave)?;
|
||||
write_i32(v, writer)
|
||||
}
|
||||
|
||||
pub fn read_string<R: Read>(reader: &mut R) -> Result<String, Error> {
|
||||
let string_len = read_usize(reader)?;
|
||||
let bytes = read_bytevec(reader, string_len)?;
|
||||
String::from_utf8(bytes).map_err(|_| Error::InvalidSave)
|
||||
}
|
||||
|
||||
pub fn write_str<W: Write>(s: &str, writer: &mut W) -> Result<(), Error> {
|
||||
write_usize(s.len(), writer)?;
|
||||
writer.write_all(s.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_vec<F, T>(len: usize, mut reader: F) -> Result<Vec<T>, Error>
|
||||
where
|
||||
F: FnMut() -> Result<T, Error>,
|
||||
{
|
||||
let mut vec = Vec::with_capacity(len);
|
||||
for _ in 0..len {
|
||||
vec.push(reader()?);
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub fn read_array<F, T, const LEN: usize>(mut reader: F) -> Result<[T; LEN], Error>
|
||||
where
|
||||
F: FnMut() -> Result<T, Error>,
|
||||
T: Default + Copy,
|
||||
{
|
||||
let mut arr = [Default::default(); LEN];
|
||||
impl<T: ReadFrom + Default + Copy, const N: usize> ReadFrom for [T; N] {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let mut arr = [Default::default(); N];
|
||||
for slot in &mut arr {
|
||||
*slot = reader()?;
|
||||
*slot = T::read_from(reader)?;
|
||||
}
|
||||
Ok(arr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: WriteTo> WriteTo for [T] {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
for x in self {
|
||||
x.write_to(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ReadFrom for String {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let string_len = usize::read_from(reader)?;
|
||||
let mut bytes = vec![0u8; string_len];
|
||||
reader.read_exact(&mut bytes)?;
|
||||
String::from_utf8(bytes).map_err(|_| Error::InvalidSave)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for str {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.len().write_to(writer)?;
|
||||
writer.write_all(self.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_magic<R: Read>(reader: &mut R, magic_bytes: &[u8]) -> Result<(), Error> {
|
||||
let mut header = [0u8; 16];
|
||||
|
|
@ -108,13 +116,3 @@ pub fn read_magic<R: Read>(reader: &mut R, magic_bytes: &[u8]) -> Result<(), Err
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_version<R: Read>(reader: &mut R) -> Result<[i32; 4], Error> {
|
||||
read_array(|| read_i32(reader))
|
||||
}
|
||||
|
||||
pub fn read_bytevec<R: Read>(reader: &mut R, len: usize) -> Result<Vec<u8>, Error> {
|
||||
let mut vec = vec![0u8; len];
|
||||
reader.read_exact(&mut vec)?;
|
||||
Ok(vec)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ pub(crate) mod io;
|
|||
pub mod v5;
|
||||
pub mod v6;
|
||||
|
||||
use io::read_u8;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::io::read_magic;
|
||||
use crate::io::{read_magic, ReadFrom};
|
||||
|
||||
pub use v6 as latest;
|
||||
|
||||
|
|
@ -21,8 +20,8 @@ pub enum BlotterFile {
|
|||
|
||||
impl BlotterFile {
|
||||
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
read_magic(reader, b"Logic World save")?;
|
||||
let save_version = read_u8(reader)?;
|
||||
read_magic(reader, latest::SAVE_HEADER)?;
|
||||
let save_version = u8::read_from(reader)?;
|
||||
match save_version {
|
||||
v5::SAVE_VERSION => v5::BlotterFile::read_after_save_version(reader).map(Self::V5),
|
||||
v6::SAVE_VERSION => v6::BlotterFile::read_after_save_version(reader).map(Self::V6),
|
||||
|
|
|
|||
485
src/v5.rs
485
src/v5.rs
|
|
@ -3,6 +3,8 @@ use crate::io::*;
|
|||
use std::io::{Read, Write};
|
||||
|
||||
pub const SAVE_VERSION: u8 = 5;
|
||||
pub const SAVE_HEADER: &[u8; 16] = b"Logic World save";
|
||||
pub const SAVE_FOOTER: &[u8; 16] = b"redstone sux lol";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum SaveType {
|
||||
|
|
@ -10,28 +12,116 @@ pub enum SaveType {
|
|||
Subassembly,
|
||||
}
|
||||
|
||||
impl ReadFrom for SaveType {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let id = u8::read_from(reader)?;
|
||||
match id {
|
||||
1 => Ok(Self::World),
|
||||
2 => Ok(Self::Subassembly),
|
||||
_ => Err(Error::InvalidSave),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for SaveType {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
let id: u8 = match self {
|
||||
Self::World => 1,
|
||||
Self::Subassembly => 2,
|
||||
};
|
||||
id.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModInfo {
|
||||
pub mod_id: String,
|
||||
pub mod_version: [i32; 4],
|
||||
}
|
||||
|
||||
impl ReadFrom for ModInfo {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let mod_id = ReadFrom::read_from(reader)?;
|
||||
let mod_version = ReadFrom::read_from(reader)?;
|
||||
Ok(Self {
|
||||
mod_id,
|
||||
mod_version,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for ModInfo {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.mod_id.write_to(writer)?;
|
||||
self.mod_version.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ComponentType {
|
||||
pub numeric_id: u16,
|
||||
pub text_id: String,
|
||||
}
|
||||
|
||||
impl ReadFrom for ComponentType {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let numeric_id = ReadFrom::read_from(reader)?;
|
||||
let text_id = ReadFrom::read_from(reader)?;
|
||||
Ok(Self {
|
||||
numeric_id,
|
||||
text_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for ComponentType {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.numeric_id.write_to(writer)?;
|
||||
self.text_id.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Input {
|
||||
pub circuit_state_id: i32,
|
||||
}
|
||||
|
||||
impl ReadFrom for Input {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let circuit_state_id = ReadFrom::read_from(reader)?;
|
||||
Ok(Self { circuit_state_id })
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for Input {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.circuit_state_id.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Output {
|
||||
pub circuit_state_id: i32,
|
||||
}
|
||||
|
||||
impl ReadFrom for Output {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let circuit_state_id = ReadFrom::read_from(reader)?;
|
||||
Ok(Self { circuit_state_id })
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for Output {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.circuit_state_id.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Component {
|
||||
pub address: u32,
|
||||
|
|
@ -44,13 +134,127 @@ pub struct Component {
|
|||
pub custom_data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl ReadFrom for Component {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let address = ReadFrom::read_from(reader)?;
|
||||
let parent = ReadFrom::read_from(reader)?;
|
||||
let type_id = ReadFrom::read_from(reader)?;
|
||||
let position = ReadFrom::read_from(reader)?;
|
||||
let rotation = ReadFrom::read_from(reader)?;
|
||||
|
||||
let num_inputs = usize::read_from(reader)?;
|
||||
let inputs = ReadFromSeed::read_from_seed(reader, Length(num_inputs))?;
|
||||
|
||||
let num_outputs = usize::read_from(reader)?;
|
||||
let outputs = ReadFromSeed::read_from_seed(reader, Length(num_outputs))?;
|
||||
|
||||
let custom_data_len = i32::read_from(reader)?;
|
||||
let custom_data = if custom_data_len < 0 {
|
||||
None
|
||||
} else {
|
||||
let mut data = vec![0u8; custom_data_len as usize];
|
||||
reader.read_exact(&mut data)?;
|
||||
Some(data)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
address,
|
||||
parent,
|
||||
type_id,
|
||||
position,
|
||||
rotation,
|
||||
inputs,
|
||||
outputs,
|
||||
custom_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for Component {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.address.write_to(writer)?;
|
||||
self.parent.write_to(writer)?;
|
||||
self.type_id.write_to(writer)?;
|
||||
self.position.write_to(writer)?;
|
||||
self.rotation.write_to(writer)?;
|
||||
|
||||
self.inputs.len().write_to(writer)?;
|
||||
self.inputs.write_to(writer)?;
|
||||
|
||||
self.outputs.len().write_to(writer)?;
|
||||
self.outputs.write_to(writer)?;
|
||||
|
||||
match &self.custom_data {
|
||||
None => {
|
||||
(-1_i32).write_to(writer)?;
|
||||
}
|
||||
Some(data) => {
|
||||
data.len().write_to(writer)?;
|
||||
writer.write_all(&data)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PegType {
|
||||
Output,
|
||||
Input,
|
||||
}
|
||||
|
||||
impl ReadFrom for PegType {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let id = u8::read_from(reader)?;
|
||||
match id {
|
||||
0 => Ok(Self::Output),
|
||||
1 => Ok(Self::Input),
|
||||
_ => Err(Error::InvalidSave),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for PegType {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
let id: u8 = match self {
|
||||
Self::Output => 0,
|
||||
Self::Input => 1,
|
||||
};
|
||||
id.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PegAddress {
|
||||
pub is_input: bool,
|
||||
pub peg_type: PegType,
|
||||
pub component_address: u32,
|
||||
pub peg_index: i32,
|
||||
}
|
||||
|
||||
impl ReadFrom for PegAddress {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let peg_type = ReadFrom::read_from(reader)?;
|
||||
let component_address = ReadFrom::read_from(reader)?;
|
||||
let peg_index = ReadFrom::read_from(reader)?;
|
||||
|
||||
Ok(Self {
|
||||
peg_type,
|
||||
component_address,
|
||||
peg_index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for PegAddress {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.peg_type.write_to(writer)?;
|
||||
self.component_address.write_to(writer)?;
|
||||
self.peg_index.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Wire {
|
||||
pub start_peg: PegAddress,
|
||||
|
|
@ -59,12 +263,71 @@ pub struct Wire {
|
|||
pub rotation: f32,
|
||||
}
|
||||
|
||||
impl ReadFrom for Wire {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let start_peg = ReadFrom::read_from(reader)?;
|
||||
let end_peg = ReadFrom::read_from(reader)?;
|
||||
let circuit_state_id = ReadFrom::read_from(reader)?;
|
||||
let rotation = ReadFrom::read_from(reader)?;
|
||||
Ok(Self {
|
||||
start_peg,
|
||||
end_peg,
|
||||
circuit_state_id,
|
||||
rotation,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for Wire {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.start_peg.write_to(writer)?;
|
||||
self.end_peg.write_to(writer)?;
|
||||
self.circuit_state_id.write_to(writer)?;
|
||||
self.rotation.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CircuitStates {
|
||||
WorldFormat { circuit_states: Vec<u8> },
|
||||
SubassemblyFormat { on_states: Vec<i32> },
|
||||
}
|
||||
|
||||
impl ReadFromSeed<SaveType> for CircuitStates {
|
||||
fn read_from_seed<R: Read>(reader: &mut R, seed: SaveType) -> Result<Self, Error> {
|
||||
match seed {
|
||||
SaveType::World => {
|
||||
let num_bytes = usize::read_from(reader)?;
|
||||
let mut circuit_states = vec![0u8; num_bytes];
|
||||
reader.read_exact(&mut circuit_states)?;
|
||||
Ok(Self::WorldFormat { circuit_states })
|
||||
}
|
||||
SaveType::Subassembly => {
|
||||
let num_on_states = usize::read_from(reader)?;
|
||||
let on_states = Vec::read_from_seed(reader, Length(num_on_states))?;
|
||||
Ok(Self::SubassemblyFormat { on_states })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for CircuitStates {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
match self {
|
||||
Self::WorldFormat { circuit_states } => {
|
||||
circuit_states.len().write_to(writer)?;
|
||||
writer.write_all(&circuit_states)?;
|
||||
}
|
||||
Self::SubassemblyFormat { on_states } => {
|
||||
on_states.len().write_to(writer)?;
|
||||
on_states.write_to(writer)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlotterFile {
|
||||
pub game_version: [i32; 4],
|
||||
|
|
@ -92,9 +355,9 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
read_magic(reader, b"Logic World save")?;
|
||||
read_magic(reader, SAVE_HEADER)?;
|
||||
|
||||
let save_version = read_u8(reader)?;
|
||||
let save_version = u8::read_from(reader)?;
|
||||
if save_version != SAVE_VERSION {
|
||||
return Err(Error::IncompatibleVersion(save_version));
|
||||
}
|
||||
|
|
@ -102,106 +365,24 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub(crate) fn read_after_save_version<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let game_version = read_version(reader)?;
|
||||
let game_version = ReadFrom::read_from(reader)?;
|
||||
|
||||
let save_type_id = read_u8(reader)?;
|
||||
let save_type = match save_type_id {
|
||||
1 => SaveType::World,
|
||||
2 => SaveType::Subassembly,
|
||||
_ => {
|
||||
return Err(Error::InvalidSave);
|
||||
}
|
||||
};
|
||||
let save_type = SaveType::read_from(reader)?;
|
||||
let num_components = usize::read_from(reader)?;
|
||||
let num_wires = usize::read_from(reader)?;
|
||||
|
||||
let num_components = read_usize(reader)?;
|
||||
let num_wires = read_usize(reader)?;
|
||||
let num_mods = usize::read_from(reader)?;
|
||||
let mods = Vec::read_from_seed(reader, Length(num_mods))?;
|
||||
|
||||
let num_mods = read_usize(reader)?;
|
||||
let mods = read_vec(num_mods, || {
|
||||
let mod_id = read_string(reader)?;
|
||||
let mod_version = read_version(reader)?;
|
||||
Ok(ModInfo {
|
||||
mod_id,
|
||||
mod_version,
|
||||
})
|
||||
})?;
|
||||
let num_component_types: usize = usize::read_from(reader)?;
|
||||
let component_types = Vec::read_from_seed(reader, Length(num_component_types))?;
|
||||
|
||||
let num_component_types: usize = read_usize(reader)?;
|
||||
let component_types = read_vec(num_component_types, || {
|
||||
let numeric_id = read_u16(reader)?;
|
||||
let text_id = read_string(reader)?;
|
||||
Ok(ComponentType {
|
||||
numeric_id,
|
||||
text_id,
|
||||
})
|
||||
})?;
|
||||
let components = Vec::read_from_seed(reader, Length(num_components))?;
|
||||
let wires = Vec::read_from_seed(reader, Length(num_wires))?;
|
||||
|
||||
let components = read_vec(num_components, || {
|
||||
let address = read_u32(reader)?;
|
||||
let parent = read_u32(reader)?;
|
||||
let type_id = read_u16(reader)?;
|
||||
let position = read_array(|| read_f32(reader))?;
|
||||
let rotation = read_array(|| read_f32(reader))?;
|
||||
let circuit_states = CircuitStates::read_from_seed(reader, save_type)?;
|
||||
|
||||
let num_inputs = read_usize(reader)?;
|
||||
let inputs = read_vec(num_inputs, || {
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
Ok(Input { circuit_state_id })
|
||||
})?;
|
||||
|
||||
let num_outputs = read_usize(reader)?;
|
||||
let outputs = read_vec(num_outputs, || {
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
Ok(Output { circuit_state_id })
|
||||
})?;
|
||||
|
||||
let custom_data_len = read_i32(reader)?;
|
||||
let custom_data = if custom_data_len < 0 {
|
||||
None
|
||||
} else {
|
||||
Some(read_bytevec(reader, custom_data_len as usize)?)
|
||||
};
|
||||
|
||||
Ok(Component {
|
||||
address,
|
||||
parent,
|
||||
type_id,
|
||||
position,
|
||||
rotation,
|
||||
inputs,
|
||||
outputs,
|
||||
custom_data,
|
||||
})
|
||||
})?;
|
||||
|
||||
let wires = read_vec(num_wires, || {
|
||||
let start_peg = read_peg_address(reader)?;
|
||||
let end_peg = read_peg_address(reader)?;
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
let rotation = read_f32(reader)?;
|
||||
|
||||
Ok(Wire {
|
||||
start_peg,
|
||||
end_peg,
|
||||
circuit_state_id,
|
||||
rotation,
|
||||
})
|
||||
})?;
|
||||
|
||||
let circuit_states = match save_type {
|
||||
SaveType::World => {
|
||||
let num_bytes = read_usize(reader)?;
|
||||
let circuit_states = read_bytevec(reader, num_bytes)?;
|
||||
CircuitStates::WorldFormat { circuit_states }
|
||||
}
|
||||
SaveType::Subassembly => {
|
||||
let num_on_states = read_usize(reader)?;
|
||||
let on_states = read_vec(num_on_states, || read_i32(reader))?;
|
||||
CircuitStates::SubassemblyFormat { on_states }
|
||||
}
|
||||
};
|
||||
|
||||
read_magic(reader, b"redstone sux lol")?;
|
||||
read_magic(reader, SAVE_FOOTER)?;
|
||||
|
||||
Ok(Self {
|
||||
game_version,
|
||||
|
|
@ -215,112 +396,34 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(b"Logic World save")?;
|
||||
writer.write_all(SAVE_HEADER)?;
|
||||
|
||||
write_u8(SAVE_VERSION, writer)?;
|
||||
for &v in &self.game_version {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
let save_type_id = match self.save_type {
|
||||
SaveType::World => 1,
|
||||
SaveType::Subassembly => 2,
|
||||
};
|
||||
write_u8(save_type_id, writer)?;
|
||||
SAVE_VERSION.write_to(writer)?;
|
||||
self.game_version.write_to(writer)?;
|
||||
self.save_type.write_to(writer)?;
|
||||
|
||||
write_usize(self.components.len(), writer)?;
|
||||
write_usize(self.wires.len(), writer)?;
|
||||
self.components.len().write_to(writer)?;
|
||||
self.wires.len().write_to(writer)?;
|
||||
|
||||
write_usize(self.mods.len(), writer)?;
|
||||
for mod_info in &self.mods {
|
||||
write_str(&mod_info.mod_id, writer)?;
|
||||
for &v in &mod_info.mod_version {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
}
|
||||
self.mods.len().write_to(writer)?;
|
||||
self.mods.write_to(writer)?;
|
||||
|
||||
write_usize(self.component_types.len(), writer)?;
|
||||
for component_type in &self.component_types {
|
||||
write_u16(component_type.numeric_id, writer)?;
|
||||
write_str(&component_type.text_id, writer)?;
|
||||
}
|
||||
self.component_types.len().write_to(writer)?;
|
||||
self.component_types.write_to(writer)?;
|
||||
|
||||
for component in &self.components {
|
||||
write_u32(component.address, writer)?;
|
||||
write_u32(component.parent, writer)?;
|
||||
write_u16(component.type_id, writer)?;
|
||||
for &v in &component.position {
|
||||
write_f32(v, writer)?;
|
||||
}
|
||||
for &v in &component.rotation {
|
||||
write_f32(v, writer)?;
|
||||
}
|
||||
write_usize(component.inputs.len(), writer)?;
|
||||
for input in &component.inputs {
|
||||
write_i32(input.circuit_state_id, writer)?;
|
||||
}
|
||||
write_usize(component.outputs.len(), writer)?;
|
||||
for output in &component.outputs {
|
||||
write_i32(output.circuit_state_id, writer)?;
|
||||
}
|
||||
if let Some(bytes) = &component.custom_data {
|
||||
write_usize(bytes.len(), writer)?;
|
||||
writer.write_all(&bytes)?;
|
||||
} else {
|
||||
write_i32(-1, writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
for wire in &self.wires {
|
||||
write_peg_address(&wire.start_peg, writer)?;
|
||||
write_peg_address(&wire.end_peg, writer)?;
|
||||
write_i32(wire.circuit_state_id, writer)?;
|
||||
write_f32(wire.rotation, writer)?;
|
||||
}
|
||||
self.components.write_to(writer)?;
|
||||
self.wires.write_to(writer)?;
|
||||
|
||||
match (self.save_type, &self.circuit_states) {
|
||||
(SaveType::World, CircuitStates::WorldFormat { circuit_states }) => {
|
||||
write_usize(circuit_states.len(), writer)?;
|
||||
writer.write_all(&circuit_states)?;
|
||||
}
|
||||
(SaveType::Subassembly, CircuitStates::SubassemblyFormat { on_states }) => {
|
||||
write_usize(on_states.len(), writer)?;
|
||||
for &v in on_states {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
}
|
||||
(SaveType::World, CircuitStates::WorldFormat { .. }) => {}
|
||||
(SaveType::Subassembly, CircuitStates::SubassemblyFormat { .. }) => {}
|
||||
_ => {
|
||||
return Err(Error::InvalidSave);
|
||||
}
|
||||
}
|
||||
self.circuit_states.write_to(writer)?;
|
||||
|
||||
writer.write_all(b"redstone sux lol")?;
|
||||
writer.write_all(SAVE_FOOTER)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_peg_address<R: Read>(reader: &mut R) -> Result<PegAddress, Error> {
|
||||
let peg_kind = read_u8(reader)?;
|
||||
let is_input = match peg_kind {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => return Err(Error::InvalidSave),
|
||||
};
|
||||
let component_address = read_u32(reader)?;
|
||||
let peg_index = read_i32(reader)?;
|
||||
Ok(PegAddress {
|
||||
is_input,
|
||||
component_address,
|
||||
peg_index,
|
||||
})
|
||||
}
|
||||
|
||||
fn write_peg_address<W: Write>(address: &PegAddress, writer: &mut W) -> Result<(), Error> {
|
||||
let peg_type_id = match address.is_input {
|
||||
false => 0,
|
||||
true => 1,
|
||||
};
|
||||
write_u8(peg_type_id, writer)?;
|
||||
write_u32(address.component_address, writer)?;
|
||||
write_i32(address.peg_index, writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
286
src/v6.rs
286
src/v6.rs
|
|
@ -6,7 +6,8 @@ pub const SAVE_VERSION: u8 = 6;
|
|||
|
||||
// Unchanged from previous version:
|
||||
pub use crate::v5::{
|
||||
CircuitStates, ComponentType, Input, ModInfo, Output, PegAddress, SaveType, Wire,
|
||||
CircuitStates, ComponentType, Input, ModInfo, Output, PegAddress, SaveType, Wire, SAVE_FOOTER,
|
||||
SAVE_HEADER,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -21,6 +22,69 @@ pub struct Component {
|
|||
pub custom_data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl ReadFrom for Component {
|
||||
fn read_from<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let address = ReadFrom::read_from(reader)?;
|
||||
let parent = ReadFrom::read_from(reader)?;
|
||||
let type_id = ReadFrom::read_from(reader)?;
|
||||
let position = ReadFrom::read_from(reader)?;
|
||||
let rotation = ReadFrom::read_from(reader)?;
|
||||
|
||||
let num_inputs = usize::read_from(reader)?;
|
||||
let inputs = ReadFromSeed::read_from_seed(reader, Length(num_inputs))?;
|
||||
|
||||
let num_outputs = usize::read_from(reader)?;
|
||||
let outputs = ReadFromSeed::read_from_seed(reader, Length(num_outputs))?;
|
||||
|
||||
let custom_data_len = i32::read_from(reader)?;
|
||||
let custom_data = if custom_data_len < 0 {
|
||||
None
|
||||
} else {
|
||||
let mut data = vec![0u8; custom_data_len as usize];
|
||||
reader.read_exact(&mut data)?;
|
||||
Some(data)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
address,
|
||||
parent,
|
||||
type_id,
|
||||
position,
|
||||
rotation,
|
||||
inputs,
|
||||
outputs,
|
||||
custom_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTo for Component {
|
||||
fn write_to<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.address.write_to(writer)?;
|
||||
self.parent.write_to(writer)?;
|
||||
self.type_id.write_to(writer)?;
|
||||
self.position.write_to(writer)?;
|
||||
self.rotation.write_to(writer)?;
|
||||
|
||||
self.inputs.len().write_to(writer)?;
|
||||
self.inputs.write_to(writer)?;
|
||||
|
||||
self.outputs.len().write_to(writer)?;
|
||||
self.outputs.write_to(writer)?;
|
||||
|
||||
match &self.custom_data {
|
||||
None => {
|
||||
(-1_i32).write_to(writer)?;
|
||||
}
|
||||
Some(data) => {
|
||||
data.len().write_to(writer)?;
|
||||
writer.write_all(&data)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlotterFile {
|
||||
pub game_version: [i32; 4],
|
||||
|
|
@ -48,9 +112,9 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
read_magic(reader, b"Logic World save")?;
|
||||
read_magic(reader, SAVE_HEADER)?;
|
||||
|
||||
let save_version = read_u8(reader)?;
|
||||
let save_version = u8::read_from(reader)?;
|
||||
if save_version != SAVE_VERSION {
|
||||
return Err(Error::IncompatibleVersion(save_version));
|
||||
}
|
||||
|
|
@ -58,106 +122,24 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub(crate) fn read_after_save_version<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let game_version = read_version(reader)?;
|
||||
let game_version = ReadFrom::read_from(reader)?;
|
||||
|
||||
let save_type_id = read_u8(reader)?;
|
||||
let save_type = match save_type_id {
|
||||
1 => SaveType::World,
|
||||
2 => SaveType::Subassembly,
|
||||
_ => {
|
||||
return Err(Error::InvalidSave);
|
||||
}
|
||||
};
|
||||
let save_type = SaveType::read_from(reader)?;
|
||||
let num_components = usize::read_from(reader)?;
|
||||
let num_wires = usize::read_from(reader)?;
|
||||
|
||||
let num_components = read_usize(reader)?;
|
||||
let num_wires = read_usize(reader)?;
|
||||
let num_mods = usize::read_from(reader)?;
|
||||
let mods = Vec::read_from_seed(reader, Length(num_mods))?;
|
||||
|
||||
let num_mods = read_usize(reader)?;
|
||||
let mods = read_vec(num_mods, || {
|
||||
let mod_id = read_string(reader)?;
|
||||
let mod_version = read_version(reader)?;
|
||||
Ok(ModInfo {
|
||||
mod_id,
|
||||
mod_version,
|
||||
})
|
||||
})?;
|
||||
let num_component_types: usize = usize::read_from(reader)?;
|
||||
let component_types = Vec::read_from_seed(reader, Length(num_component_types))?;
|
||||
|
||||
let num_component_types: usize = read_usize(reader)?;
|
||||
let component_types = read_vec(num_component_types, || {
|
||||
let numeric_id = read_u16(reader)?;
|
||||
let text_id = read_string(reader)?;
|
||||
Ok(ComponentType {
|
||||
numeric_id,
|
||||
text_id,
|
||||
})
|
||||
})?;
|
||||
let components = Vec::read_from_seed(reader, Length(num_components))?;
|
||||
let wires = Vec::read_from_seed(reader, Length(num_wires))?;
|
||||
|
||||
let components = read_vec(num_components, || {
|
||||
let address = read_u32(reader)?;
|
||||
let parent = read_u32(reader)?;
|
||||
let type_id = read_u16(reader)?;
|
||||
let position = read_array(|| read_i32(reader))?;
|
||||
let rotation = read_array(|| read_f32(reader))?;
|
||||
let circuit_states = CircuitStates::read_from_seed(reader, save_type)?;
|
||||
|
||||
let num_inputs = read_usize(reader)?;
|
||||
let inputs = read_vec(num_inputs, || {
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
Ok(Input { circuit_state_id })
|
||||
})?;
|
||||
|
||||
let num_outputs = read_usize(reader)?;
|
||||
let outputs = read_vec(num_outputs, || {
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
Ok(Output { circuit_state_id })
|
||||
})?;
|
||||
|
||||
let custom_data_len = read_i32(reader)?;
|
||||
let custom_data = if custom_data_len < 0 {
|
||||
None
|
||||
} else {
|
||||
Some(read_bytevec(reader, custom_data_len as usize)?)
|
||||
};
|
||||
|
||||
Ok(Component {
|
||||
address,
|
||||
parent,
|
||||
type_id,
|
||||
position,
|
||||
rotation,
|
||||
inputs,
|
||||
outputs,
|
||||
custom_data,
|
||||
})
|
||||
})?;
|
||||
|
||||
let wires = read_vec(num_wires, || {
|
||||
let start_peg = read_peg_address(reader)?;
|
||||
let end_peg = read_peg_address(reader)?;
|
||||
let circuit_state_id = read_i32(reader)?;
|
||||
let rotation = read_f32(reader)?;
|
||||
|
||||
Ok(Wire {
|
||||
start_peg,
|
||||
end_peg,
|
||||
circuit_state_id,
|
||||
rotation,
|
||||
})
|
||||
})?;
|
||||
|
||||
let circuit_states = match save_type {
|
||||
SaveType::World => {
|
||||
let num_bytes = read_usize(reader)?;
|
||||
let circuit_states = read_bytevec(reader, num_bytes)?;
|
||||
CircuitStates::WorldFormat { circuit_states }
|
||||
}
|
||||
SaveType::Subassembly => {
|
||||
let num_on_states = read_usize(reader)?;
|
||||
let on_states = read_vec(num_on_states, || read_i32(reader))?;
|
||||
CircuitStates::SubassemblyFormat { on_states }
|
||||
}
|
||||
};
|
||||
|
||||
read_magic(reader, b"redstone sux lol")?;
|
||||
read_magic(reader, SAVE_FOOTER)?;
|
||||
|
||||
Ok(Self {
|
||||
game_version,
|
||||
|
|
@ -171,112 +153,34 @@ impl BlotterFile {
|
|||
}
|
||||
|
||||
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
writer.write_all(b"Logic World save")?;
|
||||
writer.write_all(SAVE_HEADER)?;
|
||||
|
||||
write_u8(SAVE_VERSION, writer)?;
|
||||
for &v in &self.game_version {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
let save_type_id = match self.save_type {
|
||||
SaveType::World => 1,
|
||||
SaveType::Subassembly => 2,
|
||||
};
|
||||
write_u8(save_type_id, writer)?;
|
||||
SAVE_VERSION.write_to(writer)?;
|
||||
self.game_version.write_to(writer)?;
|
||||
self.save_type.write_to(writer)?;
|
||||
|
||||
write_usize(self.components.len(), writer)?;
|
||||
write_usize(self.wires.len(), writer)?;
|
||||
self.components.len().write_to(writer)?;
|
||||
self.wires.len().write_to(writer)?;
|
||||
|
||||
write_usize(self.mods.len(), writer)?;
|
||||
for mod_info in &self.mods {
|
||||
write_str(&mod_info.mod_id, writer)?;
|
||||
for &v in &mod_info.mod_version {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
}
|
||||
self.mods.len().write_to(writer)?;
|
||||
self.mods.write_to(writer)?;
|
||||
|
||||
write_usize(self.component_types.len(), writer)?;
|
||||
for component_type in &self.component_types {
|
||||
write_u16(component_type.numeric_id, writer)?;
|
||||
write_str(&component_type.text_id, writer)?;
|
||||
}
|
||||
self.component_types.len().write_to(writer)?;
|
||||
self.component_types.write_to(writer)?;
|
||||
|
||||
for component in &self.components {
|
||||
write_u32(component.address, writer)?;
|
||||
write_u32(component.parent, writer)?;
|
||||
write_u16(component.type_id, writer)?;
|
||||
for &v in &component.position {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
for &v in &component.rotation {
|
||||
write_f32(v, writer)?;
|
||||
}
|
||||
write_usize(component.inputs.len(), writer)?;
|
||||
for input in &component.inputs {
|
||||
write_i32(input.circuit_state_id, writer)?;
|
||||
}
|
||||
write_usize(component.outputs.len(), writer)?;
|
||||
for output in &component.outputs {
|
||||
write_i32(output.circuit_state_id, writer)?;
|
||||
}
|
||||
if let Some(bytes) = &component.custom_data {
|
||||
write_usize(bytes.len(), writer)?;
|
||||
writer.write_all(&bytes)?;
|
||||
} else {
|
||||
write_i32(-1, writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
for wire in &self.wires {
|
||||
write_peg_address(&wire.start_peg, writer)?;
|
||||
write_peg_address(&wire.end_peg, writer)?;
|
||||
write_i32(wire.circuit_state_id, writer)?;
|
||||
write_f32(wire.rotation, writer)?;
|
||||
}
|
||||
self.components.write_to(writer)?;
|
||||
self.wires.write_to(writer)?;
|
||||
|
||||
match (self.save_type, &self.circuit_states) {
|
||||
(SaveType::World, CircuitStates::WorldFormat { circuit_states }) => {
|
||||
write_usize(circuit_states.len(), writer)?;
|
||||
writer.write_all(&circuit_states)?;
|
||||
}
|
||||
(SaveType::Subassembly, CircuitStates::SubassemblyFormat { on_states }) => {
|
||||
write_usize(on_states.len(), writer)?;
|
||||
for &v in on_states {
|
||||
write_i32(v, writer)?;
|
||||
}
|
||||
}
|
||||
(SaveType::World, CircuitStates::WorldFormat { .. }) => {}
|
||||
(SaveType::Subassembly, CircuitStates::SubassemblyFormat { .. }) => {}
|
||||
_ => {
|
||||
return Err(Error::InvalidSave);
|
||||
}
|
||||
}
|
||||
self.circuit_states.write_to(writer)?;
|
||||
|
||||
writer.write_all(b"redstone sux lol")?;
|
||||
writer.write_all(SAVE_FOOTER)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_peg_address<R: Read>(reader: &mut R) -> Result<PegAddress, Error> {
|
||||
let peg_kind = read_u8(reader)?;
|
||||
let is_input = match peg_kind {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => return Err(Error::InvalidSave),
|
||||
};
|
||||
let component_address = read_u32(reader)?;
|
||||
let peg_index = read_i32(reader)?;
|
||||
Ok(PegAddress {
|
||||
is_input,
|
||||
component_address,
|
||||
peg_index,
|
||||
})
|
||||
}
|
||||
|
||||
fn write_peg_address<W: Write>(address: &PegAddress, writer: &mut W) -> Result<(), Error> {
|
||||
let peg_type_id = match address.is_input {
|
||||
false => 0,
|
||||
true => 1,
|
||||
};
|
||||
write_u8(peg_type_id, writer)?;
|
||||
write_u32(address.component_address, writer)?;
|
||||
write_i32(address.peg_index, writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue