1#![deny(unsafe_code)]
9#![warn(missing_docs)]
10
11mod ops;
12mod program;
13mod version;
14
15pub use ops::{BinaryOperator, CompareOperator, Operand, PcirOp, UnaryOperator, ValueId};
16pub use program::{PcirBlock, PcirFunction, PcirModule, PcirProgram};
17pub use version::{check_pcir_schema, PCIR_SCHEMA_VERSION};
18
19use parallax_core::{ErrorCode, ParallaxError};
20
21pub type Result<T> = parallax_core::Result<T>;
23
24pub fn to_json_bytes(program: &PcirProgram) -> Result<Vec<u8>> {
26 serde_json::to_vec_pretty(program).map_err(|e| {
27 ParallaxError::new(ErrorCode::SerializationFailure, e.to_string())
28 .with_source("parallax-pcir")
29 .with_operation("to_json_bytes")
30 })
31}
32
33pub fn to_json_bytes_compact(program: &PcirProgram) -> Result<Vec<u8>> {
35 serde_json::to_vec(program).map_err(|e| {
36 ParallaxError::new(ErrorCode::SerializationFailure, e.to_string())
37 .with_source("parallax-pcir")
38 .with_operation("to_json_bytes_compact")
39 })
40}
41
42pub fn from_json_bytes(bytes: &[u8]) -> Result<PcirProgram> {
44 let program: PcirProgram = serde_json::from_slice(bytes).map_err(|e| {
45 ParallaxError::new(ErrorCode::SerializationFailure, e.to_string())
46 .with_source("parallax-pcir")
47 .with_operation("from_json_bytes")
48 })?;
49 program.validate()?;
50 Ok(program)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::ops::{BinaryOperator, Operand, PcirOp, ValueId};
57
58 #[test]
59 fn round_trip_straight_line() {
60 let mut prog = PcirProgram::new();
61 let mut func = PcirFunction::new("main");
62 let mut block = PcirBlock::new("entry");
63 block.ops.push(PcirOp::Constant {
64 dest: ValueId(0),
65 value: serde_json::json!({"t":"int","v":{"decimal":"1"}}),
66 });
67 block.ops.push(PcirOp::Constant {
68 dest: ValueId(1),
69 value: serde_json::json!({"t":"int","v":{"decimal":"2"}}),
70 });
71 block.ops.push(PcirOp::BinaryOp {
72 dest: ValueId(2),
73 op: BinaryOperator::Add,
74 lhs: Operand::Value(ValueId(0)),
75 rhs: Operand::Value(ValueId(1)),
76 });
77 block.ops.push(PcirOp::Return {
78 value: Some(Operand::Value(ValueId(2))),
79 });
80 func.blocks.push(block);
81 prog.functions.push(func);
82 let bytes = to_json_bytes(&prog).unwrap();
83 let back = from_json_bytes(&bytes).unwrap();
84 assert_eq!(back.schema, PCIR_SCHEMA_VERSION);
85 assert_eq!(back.functions[0].blocks[0].ops.len(), 4);
86 }
87
88 #[test]
89 fn rejects_future_schema() {
90 let raw = br#"{"schema":99,"functions":[],"metadata":{}}"#;
91 let err = from_json_bytes(raw).unwrap_err();
92 assert_eq!(err.code, ErrorCode::InvalidSnapshot);
93 assert!(err.message.contains("unsupported PCIR schema"));
94 }
95}