use std::collections::HashMap;
use super::types::ConcatAggregatorInput;
use super::utils::get_program_input_value;
use cairo_vm::{
hint_processor::{
builtin_hint_processor::hint_utils::{
get_integer_from_var_name, get_ptr_from_var_name, insert_value_from_var_name,
},
hint_processor_definition::HintReference,
},
serde::deserialize_program::ApTracking,
types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use num_traits::ToPrimitive;
const TASKS_OUTPUTS: &str = "tasks_outputs";
pub fn concat_aggregator_parse_task(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let concat_aggregator_input: ConcatAggregatorInput = get_program_input_value(exec_scopes)?;
let bl_numbers = concat_aggregator_input
.bootloader_output
.iter()
.map(|number| {
Felt252::from_dec_str(&number.to_string())
.map(|felt| felt.into())
.map_err(|e| HintError::CustomHint(format!("Conversion failed: {e:?}").into()))
})
.collect::<Result<Vec<_>, _>>()?;
let mut iter = bl_numbers.into_iter();
let mut next_item = || {
iter.next()
.ok_or_else(|| HintError::CustomHint("Unexpected end of bootloader output.".into()))
};
let extract_usize = |mr: MaybeRelocatable| -> Result<usize, HintError> {
match mr {
MaybeRelocatable::Int(felt) => felt
.to_usize()
.ok_or_else(|| HintError::CustomHint("Failed to convert value to usize.".into())),
_ => Err(HintError::CustomHint("Expected Int variant.".into())),
}
};
for _ in 0..3 {
next_item()?;
}
let n_tasks = extract_usize(next_item()?)?;
let tasks_outputs = (0..n_tasks)
.map(|_| -> Result<Vec<MaybeRelocatable>, HintError> {
let task_size = extract_usize(next_item()?)?;
(0..task_size.saturating_sub(1))
.map(|_| next_item())
.collect()
})
.collect::<Result<Vec<_>, _>>()?;
if iter.next().is_some() {
return Err(HintError::CustomHint(
"Bootloader output wasn't fully consumed.".into(),
));
}
if tasks_outputs.is_empty() {
return Err(HintError::CustomHint(
"No tasks found in the bootloader output.".into(),
));
}
insert_value_from_var_name("n_tasks", tasks_outputs.len(), vm, ids_data, ap_tracking)?;
exec_scopes.insert_value(TASKS_OUTPUTS, tasks_outputs);
Ok(())
}
pub fn concat_aggregator_get_handle_task_output(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
size_offset: usize,
) -> Result<(), HintError> {
let tasks_outputs: &Vec<Vec<MaybeRelocatable>> = exec_scopes.get_ref(TASKS_OUTPUTS)?;
let n_tasks = get_integer_from_var_name("n_tasks", vm, ids_data, ap_tracking)?
.to_usize()
.ok_or_else(|| HintError::CustomHint("Failed to convert value to usize.".into()))?;
let task_index = tasks_outputs.len() - n_tasks;
let output_ptr = get_ptr_from_var_name("output_ptr", vm, ids_data, ap_tracking)?;
vm.segments
.load_data(output_ptr, &tasks_outputs[task_index])?;
insert_value_from_var_name(
"output_size",
tasks_outputs[task_index].len() + size_offset,
vm,
ids_data,
ap_tracking,
)
}