use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use super::types::{ComprehensionMode, LiteralOrRegister, LoopMode};
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoopStartParams {
pub mode: LoopMode,
pub collection: u8,
pub key_reg: u8,
pub value_reg: u8,
pub result_reg: u8,
pub body_start: u16,
pub loop_end: u16,
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BuiltinCallParams {
pub dest: u8,
pub builtin_index: u16,
pub num_args: u8,
pub args: [u8; 8],
}
impl BuiltinCallParams {
pub fn arg_count(&self) -> usize {
usize::from(self.num_args)
}
pub fn arg_registers(&self) -> &[u8] {
let count = usize::from(self.num_args).min(self.args.len());
self.args.get(..count).unwrap_or(&[])
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCallParams {
pub dest: u8,
pub func_rule_index: u16,
pub num_args: u8,
pub args: [u8; 8],
}
impl FunctionCallParams {
pub fn arg_count(&self) -> usize {
usize::from(self.num_args)
}
pub fn arg_registers(&self) -> &[u8] {
let count = usize::from(self.num_args).min(self.args.len());
self.args.get(..count).unwrap_or(&[])
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObjectCreateParams {
pub dest: u8,
pub template_literal_idx: u16,
pub literal_key_fields: Vec<(u16, u8)>,
pub fields: Vec<(u8, u8)>,
}
impl ObjectCreateParams {
pub const fn field_count(&self) -> usize {
self.literal_key_fields
.len()
.saturating_add(self.fields.len())
}
pub fn literal_key_field_pairs(&self) -> &[(u16, u8)] {
&self.literal_key_fields
}
pub fn field_pairs(&self) -> &[(u8, u8)] {
&self.fields
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArrayCreateParams {
pub dest: u8,
pub elements: Vec<u8>,
}
impl ArrayCreateParams {
pub const fn element_count(&self) -> usize {
self.elements.len()
}
pub fn element_registers(&self) -> &[u8] {
&self.elements
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SetCreateParams {
pub dest: u8,
pub elements: Vec<u8>,
}
impl SetCreateParams {
pub const fn element_count(&self) -> usize {
self.elements.len()
}
pub fn element_registers(&self) -> &[u8] {
&self.elements
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VirtualDataDocumentLookupParams {
pub dest: u8,
pub path_components: Vec<LiteralOrRegister>,
}
impl VirtualDataDocumentLookupParams {
pub const fn component_count(&self) -> usize {
self.path_components.len()
}
pub fn all_literals(&self) -> bool {
self.path_components
.iter()
.all(|c| matches!(c, LiteralOrRegister::Literal(_)))
}
pub fn literal_indices(&self) -> Vec<u16> {
self.path_components
.iter()
.filter_map(|c| match *c {
LiteralOrRegister::Literal(idx) => Some(idx),
_ => None,
})
.collect()
}
pub fn register_numbers(&self) -> Vec<u8> {
self.path_components
.iter()
.filter_map(|c| match *c {
LiteralOrRegister::Register(reg) => Some(reg),
_ => None,
})
.collect()
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChainedIndexParams {
pub dest: u8,
pub root: u8,
pub path_components: Vec<LiteralOrRegister>,
}
impl ChainedIndexParams {
pub const fn component_count(&self) -> usize {
self.path_components.len()
}
pub fn all_literals(&self) -> bool {
self.path_components
.iter()
.all(|c| matches!(c, LiteralOrRegister::Literal(_)))
}
pub fn literal_indices(&self) -> Vec<u16> {
self.path_components
.iter()
.filter_map(|c| match *c {
LiteralOrRegister::Literal(idx) => Some(idx),
_ => None,
})
.collect()
}
pub fn register_numbers(&self) -> Vec<u8> {
self.path_components
.iter()
.filter_map(|c| match *c {
LiteralOrRegister::Register(reg) => Some(reg),
_ => None,
})
.collect()
}
}
#[repr(C)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComprehensionBeginParams {
pub mode: ComprehensionMode,
pub collection_reg: u8,
pub result_reg: u8,
pub key_reg: u8,
pub value_reg: u8,
pub body_start: u16,
pub comprehension_end: u16,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstructionData {
pub loop_params: Vec<LoopStartParams>,
pub builtin_call_params: Vec<BuiltinCallParams>,
pub function_call_params: Vec<FunctionCallParams>,
pub object_create_params: Vec<ObjectCreateParams>,
pub array_create_params: Vec<ArrayCreateParams>,
pub set_create_params: Vec<SetCreateParams>,
pub virtual_data_document_lookup_params: Vec<VirtualDataDocumentLookupParams>,
pub chained_index_params: Vec<ChainedIndexParams>,
pub comprehension_begin_params: Vec<ComprehensionBeginParams>,
}
impl InstructionData {
fn ensure_u16_index(len: usize) -> u16 {
debug_assert!(len <= usize::from(u16::MAX));
u16::try_from(len).unwrap_or(u16::MAX)
}
pub const fn new() -> Self {
Self {
loop_params: Vec::new(),
builtin_call_params: Vec::new(),
function_call_params: Vec::new(),
object_create_params: Vec::new(),
array_create_params: Vec::new(),
set_create_params: Vec::new(),
virtual_data_document_lookup_params: Vec::new(),
chained_index_params: Vec::new(),
comprehension_begin_params: Vec::new(),
}
}
pub fn add_loop_params(&mut self, params: LoopStartParams) -> u16 {
let index = Self::ensure_u16_index(self.loop_params.len());
self.loop_params.push(params);
index
}
pub fn add_builtin_call_params(&mut self, params: BuiltinCallParams) -> u16 {
let index = Self::ensure_u16_index(self.builtin_call_params.len());
self.builtin_call_params.push(params);
index
}
pub fn add_function_call_params(&mut self, params: FunctionCallParams) -> u16 {
let index = Self::ensure_u16_index(self.function_call_params.len());
self.function_call_params.push(params);
index
}
pub fn add_object_create_params(&mut self, params: ObjectCreateParams) -> u16 {
let index = Self::ensure_u16_index(self.object_create_params.len());
self.object_create_params.push(params);
index
}
pub fn add_array_create_params(&mut self, params: ArrayCreateParams) -> u16 {
let index = Self::ensure_u16_index(self.array_create_params.len());
self.array_create_params.push(params);
index
}
pub fn add_set_create_params(&mut self, params: SetCreateParams) -> u16 {
let index = Self::ensure_u16_index(self.set_create_params.len());
self.set_create_params.push(params);
index
}
pub fn get_loop_params(&self, index: u16) -> Option<&LoopStartParams> {
self.loop_params.get(usize::from(index))
}
pub fn get_builtin_call_params(&self, index: u16) -> Option<&BuiltinCallParams> {
self.builtin_call_params.get(usize::from(index))
}
pub fn get_function_call_params(&self, index: u16) -> Option<&FunctionCallParams> {
self.function_call_params.get(usize::from(index))
}
pub fn get_object_create_params(&self, index: u16) -> Option<&ObjectCreateParams> {
self.object_create_params.get(usize::from(index))
}
pub fn get_array_create_params(&self, index: u16) -> Option<&ArrayCreateParams> {
self.array_create_params.get(usize::from(index))
}
pub fn get_set_create_params(&self, index: u16) -> Option<&SetCreateParams> {
self.set_create_params.get(usize::from(index))
}
pub fn add_virtual_data_document_lookup_params(
&mut self,
params: VirtualDataDocumentLookupParams,
) -> u16 {
let index = Self::ensure_u16_index(self.virtual_data_document_lookup_params.len());
self.virtual_data_document_lookup_params.push(params);
index
}
pub fn get_virtual_data_document_lookup_params(
&self,
index: u16,
) -> Option<&VirtualDataDocumentLookupParams> {
self.virtual_data_document_lookup_params
.get(usize::from(index))
}
pub fn add_chained_index_params(&mut self, params: ChainedIndexParams) -> u16 {
let index = Self::ensure_u16_index(self.chained_index_params.len());
self.chained_index_params.push(params);
index
}
pub fn get_chained_index_params(&self, index: u16) -> Option<&ChainedIndexParams> {
self.chained_index_params.get(usize::from(index))
}
pub fn get_loop_params_mut(&mut self, index: u16) -> Option<&mut LoopStartParams> {
self.loop_params.get_mut(usize::from(index))
}
pub fn add_comprehension_begin_params(&mut self, params: ComprehensionBeginParams) -> u16 {
let index = Self::ensure_u16_index(self.comprehension_begin_params.len());
self.comprehension_begin_params.push(params);
index
}
pub fn get_comprehension_begin_params(&self, index: u16) -> Option<&ComprehensionBeginParams> {
self.comprehension_begin_params.get(usize::from(index))
}
pub fn get_comprehension_begin_params_mut(
&mut self,
index: u16,
) -> Option<&mut ComprehensionBeginParams> {
self.comprehension_begin_params.get_mut(usize::from(index))
}
}
impl Default for InstructionData {
fn default() -> Self {
Self::new()
}
}