forked from lambdaclass/cairo-vm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hint_processor_utils.rs
133 lines (124 loc) · 4.15 KB
/
hint_processor_utils.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::stdlib::prelude::*;
use crate::types::{errors::math_errors::MathError, relocatable::Relocatable};
use crate::vm::errors::{hint_errors::HintError, vm_errors::VirtualMachineError};
use crate::vm::vm_core::VirtualMachine;
use cairo_lang_casm::operand::{CellRef, DerefOrImmediate, Operation, Register, ResOperand};
use felt::Felt252;
/// Extracts a parameter assumed to be a buffer.
pub(crate) fn extract_buffer(buffer: &ResOperand) -> Result<(&CellRef, Felt252), HintError> {
let (cell, base_offset) = match buffer {
ResOperand::Deref(cell) => (cell, 0.into()),
ResOperand::BinOp(bin_op) => {
if let DerefOrImmediate::Immediate(val) = &bin_op.b {
(&bin_op.a, val.clone().value.into())
} else {
return Err(HintError::CustomHint(
"Failed to extract buffer, expected ResOperand of BinOp type to have Inmediate b value".to_owned().into_boxed_str()
));
}
}
_ => {
return Err(HintError::CustomHint(
"Illegal argument for a buffer."
.to_string()
.into_boxed_str(),
))
}
};
Ok((cell, base_offset))
}
pub(crate) fn cell_ref_to_relocatable(
cell_ref: &CellRef,
vm: &VirtualMachine,
) -> Result<Relocatable, MathError> {
let base = match cell_ref.register {
Register::AP => vm.get_ap(),
Register::FP => vm.get_fp(),
};
base + (cell_ref.offset as i32)
}
pub(crate) fn get_cell_val(
vm: &VirtualMachine,
cell: &CellRef,
) -> Result<Felt252, VirtualMachineError> {
Ok(vm
.get_integer(cell_ref_to_relocatable(cell, vm)?)?
.as_ref()
.clone())
}
pub(crate) fn get_ptr(
vm: &VirtualMachine,
cell: &CellRef,
offset: &Felt252,
) -> Result<Relocatable, VirtualMachineError> {
Ok((vm.get_relocatable(cell_ref_to_relocatable(cell, vm)?)? + offset)?)
}
#[cfg(feature = "std")]
pub(crate) fn as_relocatable(
vm: &mut VirtualMachine,
value: &ResOperand,
) -> Result<Relocatable, HintError> {
let (base, offset) = extract_buffer(value)?;
get_ptr(vm, base, &offset).map_err(HintError::from)
}
pub(crate) fn get_double_deref_val(
vm: &VirtualMachine,
cell: &CellRef,
offset: &Felt252,
) -> Result<Felt252, VirtualMachineError> {
Ok(vm.get_integer(get_ptr(vm, cell, offset)?)?.as_ref().clone())
}
/// Fetches the value of `res_operand` from the vm.
pub(crate) fn res_operand_get_val(
vm: &VirtualMachine,
res_operand: &ResOperand,
) -> Result<Felt252, VirtualMachineError> {
match res_operand {
ResOperand::Deref(cell) => get_cell_val(vm, cell),
ResOperand::DoubleDeref(cell, offset) => get_double_deref_val(vm, cell, &(*offset).into()),
ResOperand::Immediate(x) => Ok(Felt252::from(x.value.clone())),
ResOperand::BinOp(op) => {
let a = get_cell_val(vm, &op.a)?;
let b = match &op.b {
DerefOrImmediate::Deref(cell) => get_cell_val(vm, cell)?,
DerefOrImmediate::Immediate(x) => Felt252::from(x.value.clone()),
};
match op.op {
Operation::Add => Ok(a + b),
Operation::Mul => Ok(a * b),
}
}
}
}
#[cfg(feature = "std")]
pub(crate) fn as_cairo_short_string(value: &Felt252) -> Option<String> {
let mut as_string = String::default();
let mut is_end = false;
for byte in value
.to_be_bytes()
.into_iter()
.skip_while(num_traits::Zero::is_zero)
{
if byte == 0 {
is_end = true;
} else if is_end || !byte.is_ascii() {
return None;
} else {
as_string.push(byte as char);
}
}
Some(as_string)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_as_cairo_short_string() {
// Values extracted from cairo book example
let s = "Hello, Scarb!";
let x = Felt252::new(5735816763073854913753904210465_u128);
assert!(s.is_ascii());
let cairo_string = as_cairo_short_string(&x).expect("call to as_cairo_short_string failed");
assert_eq!(cairo_string, s);
}
}