use alloc::vec::Vec;
use crate::compressor::core::codecs::FnEncoder;
use crate::compressor::core::data::{Stream, Type};
use crate::compressor::core::error::NodeError;
use crate::compressor::core::exec::NodeCx;
pub(crate) static CONCAT: FnEncoder = FnEncoder(concat);
fn concat<'a>(cx: &mut NodeCx<'_, 'a>, inputs: &[Stream<'a>]) -> Result<(), NodeError> {
let ty = inputs[0].ty();
let width = inputs[0].width();
let mut nb_elts = 0usize;
for input in inputs {
if input.ty() != ty {
return Err(NodeError::InvalidInput("concat types must be homogenous"));
}
if input.width() != width {
return Err(NodeError::InvalidInput("concat widths must be homogenous"));
}
let count = input.n_elts();
if count as u64 >= u64::from(u32::MAX) {
return Err(NodeError::InvalidInput("too many elements to concatenate"));
}
nb_elts = nb_elts
.checked_add(count)
.ok_or(NodeError::InvalidInput("too many elements to concatenate"))?;
}
let mut sizes = Vec::with_capacity(inputs.len() * 4);
let mut content = Vec::new();
for input in inputs {
sizes.extend_from_slice(&(input.n_elts() as u32).to_le_bytes());
content.extend_from_slice(input.bytes());
}
cx.emit(0, 4, sizes)?;
if ty == Type::String {
let lens: Vec<u32> = inputs
.iter()
.flat_map(|input| input.lens().iter().copied())
.collect();
cx.emit_strings(1, content, lens)?;
} else {
cx.emit(1, width, content)?;
}
Ok(())
}