1#![forbid(unsafe_code)]
2#![warn(unreachable_pub)]
3#![warn(clippy::semicolon_if_nothing_returned)]
4#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))]
5
6pub mod circuit;
9pub mod native_types;
10
11pub use acir_field;
12pub use acir_field::FieldElement;
13pub use brillig;
14pub use circuit::black_box_functions::BlackBoxFunc;
15
16#[cfg(test)]
17mod reflection {
18 use std::{
29 fs::File,
30 io::Write,
31 path::{Path, PathBuf},
32 };
33
34 use brillig::{
35 BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapValueType, Opcode as BrilligOpcode,
36 ValueOrArray,
37 };
38 use serde_reflection::{Tracer, TracerConfig};
39
40 use crate::{
41 circuit::{
42 brillig::{BrilligInputs, BrilligOutputs},
43 directives::Directive,
44 opcodes::BlackBoxFuncCall,
45 AssertionPayload, Circuit, ExpressionOrMemory, ExpressionWidth, Opcode, OpcodeLocation,
46 Program,
47 },
48 native_types::{Witness, WitnessMap, WitnessStack},
49 };
50
51 #[test]
52 fn serde_acir_cpp_codegen() {
53 let path = PathBuf::from("./codegen/acir.cpp");
54
55 let old_hash = if path.is_file() {
56 let old_source = std::fs::read(&path).unwrap();
57 Some(fxhash::hash64(&old_source))
58 } else {
59 None
60 };
61
62 let mut tracer = Tracer::new(TracerConfig::default());
63 tracer.trace_simple_type::<Program>().unwrap();
64 tracer.trace_simple_type::<Circuit>().unwrap();
65 tracer.trace_simple_type::<ExpressionWidth>().unwrap();
66 tracer.trace_simple_type::<Opcode>().unwrap();
67 tracer.trace_simple_type::<OpcodeLocation>().unwrap();
68 tracer.trace_simple_type::<BinaryFieldOp>().unwrap();
69 tracer.trace_simple_type::<BlackBoxFuncCall>().unwrap();
70 tracer.trace_simple_type::<BrilligInputs>().unwrap();
71 tracer.trace_simple_type::<BrilligOutputs>().unwrap();
72 tracer.trace_simple_type::<BrilligOpcode>().unwrap();
73 tracer.trace_simple_type::<BinaryIntOp>().unwrap();
74 tracer.trace_simple_type::<BlackBoxOp>().unwrap();
75 tracer.trace_simple_type::<Directive>().unwrap();
76 tracer.trace_simple_type::<ValueOrArray>().unwrap();
77 tracer.trace_simple_type::<HeapValueType>().unwrap();
78 tracer.trace_simple_type::<AssertionPayload>().unwrap();
79 tracer.trace_simple_type::<ExpressionOrMemory>().unwrap();
80
81 let registry = tracer.registry().unwrap();
82
83 let mut source = Vec::new();
85 let config = serde_generate::CodeGeneratorConfig::new("Program".to_string())
86 .with_encodings(vec![serde_generate::Encoding::Bincode]);
87 let generator = serde_generate::cpp::CodeGenerator::new(&config);
88 generator.output(&mut source, ®istry).unwrap();
89
90 if let Some(old_hash) = old_hash {
92 let new_hash = fxhash::hash64(&source);
93 assert_eq!(new_hash, old_hash, "Serialization format has changed");
94 }
95
96 write_to_file(&source, &path);
97 }
98
99 #[test]
100 fn serde_witness_map_cpp_codegen() {
101 let path = PathBuf::from("./codegen/witness.cpp");
102
103 let old_hash = if path.is_file() {
104 let old_source = std::fs::read(&path).unwrap();
105 Some(fxhash::hash64(&old_source))
106 } else {
107 None
108 };
109
110 let mut tracer = Tracer::new(TracerConfig::default());
111 tracer.trace_simple_type::<Witness>().unwrap();
112 tracer.trace_simple_type::<WitnessMap>().unwrap();
113 tracer.trace_simple_type::<WitnessStack>().unwrap();
114
115 let registry = tracer.registry().unwrap();
116
117 let mut source = Vec::new();
119 let config = serde_generate::CodeGeneratorConfig::new("WitnessStack".to_string())
120 .with_encodings(vec![serde_generate::Encoding::Bincode]);
121 let generator = serde_generate::cpp::CodeGenerator::new(&config);
122 generator.output(&mut source, ®istry).unwrap();
123
124 if let Some(old_hash) = old_hash {
126 let new_hash = fxhash::hash64(&source);
127 assert_eq!(new_hash, old_hash, "Serialization format has changed");
128 }
129
130 write_to_file(&source, &path);
131 }
132
133 fn write_to_file(bytes: &[u8], path: &Path) -> String {
134 let display = path.display();
135
136 let parent_dir = path.parent().unwrap();
137 if !parent_dir.is_dir() {
138 std::fs::create_dir_all(parent_dir).unwrap();
139 }
140
141 let mut file = match File::create(path) {
142 Err(why) => panic!("couldn't create {display}: {why}"),
143 Ok(file) => file,
144 };
145
146 match file.write_all(bytes) {
147 Err(why) => panic!("couldn't write to {display}: {why}"),
148 Ok(_) => display.to_string(),
149 }
150 }
151}