acir/circuit/opcodes/
memory_operation.rs1use std::marker::PhantomData;
2
3use crate::native_types::{Expression, Witness};
4use acir_field::AcirField;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Copy, Default)]
9#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
10pub struct BlockId(pub u32);
11
12impl std::fmt::Display for BlockId {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 write!(f, "b{}", self.0)
15 }
16}
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy)]
20#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
21pub enum MemOpKind {
22 Read,
23 Write,
24}
25
26#[derive(Clone, PartialEq, Eq, Debug, Hash)]
29#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
30pub struct MemOp<F> {
31 pub operation: MemOpKind,
32 pub index: Witness,
34 pub value: Witness,
36 #[cfg_attr(feature = "arb", proptest(value = "PhantomData"))]
37 _phantom: PhantomData<F>,
38}
39
40#[derive(Serialize, Deserialize)]
44#[serde(rename = "MemOp")]
45struct MemOpWire<F> {
46 operation: Expression<F>,
47 index: Expression<F>,
48 value: Expression<F>,
49}
50
51impl<F: AcirField + Serialize> Serialize for MemOp<F> {
52 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53 MemOpWire {
54 operation: match self.operation {
55 MemOpKind::Read => Expression::<F>::zero(),
56 MemOpKind::Write => Expression::<F>::one(),
57 },
58 index: Expression::<F>::from(self.index),
59 value: Expression::<F>::from(self.value),
60 }
61 .serialize(serializer)
62 }
63}
64
65impl<'de, F: AcirField + Deserialize<'de>> Deserialize<'de> for MemOp<F> {
66 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
67 let wire = MemOpWire::<F>::deserialize(deserializer)?;
68
69 let operation = if wire.operation.is_zero() {
70 MemOpKind::Read
71 } else if wire.operation.is_one() {
72 MemOpKind::Write
73 } else {
74 return Err(serde::de::Error::custom(
75 "MemOp operation must be either 0 (Read) or 1 (Write)",
76 ));
77 };
78 let index = wire
79 .index
80 .to_witness()
81 .ok_or_else(|| serde::de::Error::custom("MemOp index must be a single witness"))?;
82 let value = wire
83 .value
84 .to_witness()
85 .ok_or_else(|| serde::de::Error::custom("MemOp value must be a single witness"))?;
86
87 Ok(MemOp { operation, index, value, _phantom: PhantomData })
88 }
89}
90
91impl<F> MemOp<F> {
92 pub fn read_at_mem_index(index: Witness, value: Witness) -> Self {
95 MemOp { operation: MemOpKind::Read, index, value, _phantom: PhantomData }
96 }
97
98 pub fn write_to_mem_index(index: Witness, value: Witness) -> Self {
100 MemOp { operation: MemOpKind::Write, index, value, _phantom: PhantomData }
101 }
102}