1use crate::instruction::Instruction;
7use crate::term::TermKind;
8use beamcode_derive::{Decode, Encode};
9use byteorder::ReadBytesExt as _;
10use num::BigInt;
11use std::io::{Read, Write};
12
13pub mod instruction;
14pub mod term;
15
16pub trait Decode: Sized {
18 fn decode<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
19 let tag = reader.read_u8()?;
20 Self::decode_with_tag(reader, tag)
21 }
22
23 fn decode_with_tag<R: Read>(reader: &mut R, tag: u8) -> Result<Self, DecodeError>;
24}
25
26pub trait Encode {
28 fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError>;
29}
30
31#[derive(Debug, thiserror::Error)]
33pub enum DecodeError {
34 #[error("unknown term tag: {tag}")]
35 UnknownTermTag { tag: u8 },
36
37 #[error("unexpected term: expected={expected:?}, actual={actual:?}")]
38 UnexpectedTerm {
39 expected: Vec<TermKind>,
40 actual: TermKind,
41 },
42
43 #[error("unknown allocation list item tag: {tag}")]
44 UnknownAllocationListItemTag { tag: usize },
45
46 #[error("unknown opcode: {opcode}")]
47 UnknownOpcode { opcode: u8 },
48
49 #[error("invalid Unicode codepoint: {value}")]
50 InvalidUnicodeCodepoint { value: u32 },
51
52 #[error(transparent)]
53 NumError(#[from] num::bigint::TryFromBigIntError<BigInt>),
54
55 #[error(transparent)]
56 IoError(#[from] std::io::Error),
57}
58
59#[derive(Debug, thiserror::Error)]
61pub enum EncodeError {
62 #[error(transparent)]
63 IoError(#[from] std::io::Error),
64}
65
66pub fn decode_instructions(bytecode: &[u8]) -> Result<Vec<Instruction>, DecodeError> {
68 let mut reader = bytecode;
69 let mut instructions = Vec::new();
70 while !reader.is_empty() {
71 let instruction = Instruction::decode(&mut reader)?;
72 instructions.push(instruction);
73 }
74 Ok(instructions)
75}
76
77pub fn encode_instructions(instructions: &[Instruction]) -> Result<Vec<u8>, EncodeError> {
79 let mut buf = Vec::new();
80 for instruction in instructions {
81 instruction.encode(&mut buf)?;
82 }
83 Ok(buf)
84}