use phf::phf_map;
use std::collections::HashMap;
use crate::error::{call_site_error, Error};
pub fn get_variadic_type_suffix(n: &[u32]) -> String {
n.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>()
.join("_")
}
pub fn concrete_name(name: &str, n: &[u32]) -> String {
format!("{}_{}", name, get_variadic_type_suffix(n))
}
#[derive(Debug, Clone, PartialEq)]
pub enum DimType {
Static,
Mixed,
}
#[derive(Debug, Clone)]
pub struct VariadicTypeData {
pub name: &'static str,
pub cga_names: &'static [&'static str],
pub cga_dim_types: &'static [DimType],
pub cga_index_types: &'static [&'static str],
}
impl VariadicTypeData {
pub fn concrete_name(&self, n: &[u32]) -> String {
concrete_name(self.name, n)
}
pub fn concrete_name_from_cga_type(&self, cga_type: &ConstGenericArrayType) -> String {
self.concrete_name(&cga_type.n)
}
pub fn num_cgas(&self) -> u32 {
self.cga_names.len() as u32
}
pub fn iter(&self, n_vec: &[u32]) -> ConstGenericArrayTypeIterator {
ConstGenericArrayTypeIterator::new(n_vec)
}
}
static VARIADIC_TYPES: phf::Map<&'static str, VariadicTypeData> = phf_map! {
"Array" => VariadicTypeData {name: "Array", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Mixed]},
"Shape" => VariadicTypeData {name: "Shape", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Mixed]},
"PointerTile" => VariadicTypeData {name: "PointerTile", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Static]},
"Tensor" => VariadicTypeData {name: "Tensor", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Mixed]},
"Partition" => VariadicTypeData {name: "Partition", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Static]},
"PartitionMut" => VariadicTypeData {name: "PartitionMut", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Static]},
"Tile" => VariadicTypeData {name: "Tile", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Static]},
"BroadcastScalar" => VariadicTypeData {name: "BroadcastScalar", cga_index_types: &["i32"], cga_names: &["D"], cga_dim_types: &[DimType::Static]},
};
pub fn get_variadic_trait_type_data(
maybe_primitive: &str,
method_name: &str,
) -> Option<VariadicTypeData> {
match (maybe_primitive, method_name) {
("T", "broadcast") => get_variadic_type_data("BroadcastScalar"),
("f32", "broadcast") => get_variadic_type_data("BroadcastScalar"),
("i32", "broadcast") => get_variadic_type_data("BroadcastScalar"),
("u32", "broadcast") => get_variadic_type_data("BroadcastScalar"),
("bool", "broadcast") => get_variadic_type_data("BroadcastScalar"),
_ => None,
}
}
pub fn get_variadic_type_data(type_name: &str) -> Option<VariadicTypeData> {
VARIADIC_TYPES.get(type_name).cloned()
}
#[derive(Debug, Clone)]
pub struct VariadicOpData {
pub const_length_vars: &'static [&'static str], pub cga_map: HashMap<&'static str, &'static str>, pub input_map: Vec<(usize, &'static str, &'static [&'static str])>, pub output_map: (&'static str, &'static [&'static str]), pub return_type: (&'static str, &'static [&'static str]),
}
pub fn get_variadic_method_data(
vtd: &VariadicTypeData,
method_name: &str,
) -> Result<Option<(&'static str, VariadicOpData)>, Error> {
let method2op = match vtd.name {
"Array" => HashMap::from([]),
"Shape" => HashMap::from([]),
"PointerTile" => {
HashMap::from([("broadcast", "broadcast_ptr"), ("reshape", "reshape_ptr")])
}
"Tensor" => HashMap::from([
("partition", "make_partition_view"),
("partition_permuted", "make_partition_view_permuted"),
("partition_mut", "make_partition_view_mut"),
("load_tile", "load_tile"),
("load", "load_tile_mut"),
("store", "store_tile"),
("shape", "get_tensor_shape"),
]),
"Partition" => HashMap::from([("load", "load_from_view")]),
"PartitionMut" => HashMap::from([
("load", "load_from_view_mut"),
("store", "store_to_view_mut"),
]),
"Tile" => HashMap::from([("reshape", "reshape"), ("broadcast", "broadcast")]),
"BroadcastScalar" => HashMap::from([("broadcast", "broadcast_scalar")]),
_ => return call_site_error(&format!("Unexpected variadic type: {}", vtd.name)),
};
match method2op.get(method_name) {
Some(op_name) => Ok(Some((
op_name,
get_variadic_op_data(op_name)
.unwrap_or_else(|| panic!("{op_name} is not a variadic op.")),
))),
None => Ok(None),
}
}
pub fn get_variadic_op_data(op_name: &str) -> Option<VariadicOpData> {
match op_name {
"addptr" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PointerTile", &["D"])],
output_map: ("PointerTile", &["D"]),
return_type: ("PointerTile", &["_", "D"]),
}),
"addptr_tile" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PointerTile", &["D"]), (1, "Tile", &["D"])],
output_map: ("PointerTile", &["D"]),
return_type: ("PointerTile", &["_", "D"]),
}),
"make_tensor_view" => Some(VariadicOpData {
const_length_vars: &["ZERO", "N"],
cga_map: HashMap::from([("EMPTY", "ZERO"), ("D", "N"), ("C", "N")]),
input_map: vec![
(0, "PointerTile", &["EMPTY"]),
(1, "Shape", &["D"]),
(2, "Array", &["C"]),
],
output_map: ("Tensor", &["D"]),
return_type: ("Tensor", &["_", "D"]),
}),
"get_tensor_shape" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tensor", &["S"])],
output_map: ("Shape", &["S"]),
return_type: ("Shape", &["'_", "S"]),
}),
"get_shape_dim" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Shape", &["S"])],
output_map: ("i32", &[]),
return_type: ("i32", &[]),
}),
"get_tensor_token" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tensor", &["S"])],
output_map: ("Token", &[]),
return_type: ("Token", &[]),
}),
"set_tensor_token" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tensor", &["S"])],
output_map: ("()", &[]),
return_type: ("()", &[]),
}),
"make_partition_view" | "make_partition_view_padded" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("TENSOR_SHAPE", "N"), ("TILE_SHAPE", "N")]),
input_map: vec![
(0, "Tensor", &["TENSOR_SHAPE"]),
(1, "Shape", &["TILE_SHAPE"]),
],
output_map: ("Partition", &["TILE_SHAPE"]),
return_type: ("Partition", &["'_", "_", "TILE_SHAPE"]),
}),
"make_partition_view_permuted" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("TENSOR_SHAPE", "N"), ("TILE_SHAPE", "N")]),
input_map: vec![
(0, "Tensor", &["TENSOR_SHAPE"]),
(1, "Shape", &["TILE_SHAPE"]),
],
output_map: ("Partition", &["TILE_SHAPE"]),
return_type: ("Partition", &["'_", "_", "TILE_SHAPE"]),
}),
"get_partition_token" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "Partition", &["D"])],
output_map: ("Token", &[]),
return_type: ("Token", &[]),
}),
"load_from_view" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "Partition", ["D"].as_slice())],
output_map: ("Tile", &["D"]),
return_type: ("Tile", &["_", "D"]),
}),
"make_partition_view_mut" | "make_partition_view_mut_padded" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("TENSOR_SHAPE", "N"), ("TILE_SHAPE", "N")]),
input_map: vec![
(0, "Tensor", &["TENSOR_SHAPE"]),
(1, "Shape", &["TILE_SHAPE"]),
],
output_map: ("PartitionMut", &["TILE_SHAPE"]),
return_type: ("PartitionMut", &["'_", "_", "TILE_SHAPE"]),
}),
"get_partition_token_mut" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PartitionMut", &["D"])],
output_map: ("Token", &[]),
return_type: ("Token", &[]),
}),
"set_partition_tensor_token" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PartitionMut", &["D"])],
output_map: ("()", &[]),
return_type: ("()", &[]),
}),
"load_from_view_mut" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PartitionMut", &["D"])],
output_map: ("Tile", &["D"]),
return_type: ("Tile", &["_", "D"]),
}),
"store_to_view_mut" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("D", "N")]),
input_map: vec![(0, "PartitionMut", &["D"]), (1, "Tile", &["D"])],
output_map: ("()", &[]),
return_type: ("()", &[]),
}),
"reshape" => Some(VariadicOpData {
const_length_vars: &["N", "M"],
cga_map: HashMap::from([("S", "N"), ("R", "M")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Shape", &["R"])],
output_map: ("Tile", &["R"]),
return_type: ("Tile", &["_", "R"]),
}),
"broadcast_ptr" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N"), ("R", "N")]),
input_map: vec![(0, "PointerTile", &["S"]), (1, "Shape", &["R"])],
output_map: ("PointerTile", &["R"]),
return_type: ("PointerTile", &["_", "R"]),
}),
"reshape_ptr" => Some(VariadicOpData {
const_length_vars: &["N", "M"],
cga_map: HashMap::from([("S", "N"), ("R", "M")]),
input_map: vec![(0, "PointerTile", &["S"]), (1, "Shape", &["R"])],
output_map: ("PointerTile", &["R"]),
return_type: ("PointerTile", &["_", "R"]),
}),
"broadcast" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N"), ("R", "N")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Shape", &["R"])],
output_map: ("Tile", &["R"]),
return_type: ("Tile", &["_", "R"]),
}),
"permute" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("A", "N"), ("I", "N"), ("R", "N")]),
input_map: vec![(0, "Tile", &["A"]), (1, "Array", &["I"])],
output_map: ("Tile", &["R"]),
return_type: ("Tile", &["_", "R"]),
}),
"constant" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(1, "Shape", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"broadcast_scalar" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(1, "Shape", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"load_tile" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N"), ("R", "N")]),
input_map: vec![(0, "Tensor", &["S"]), (1, "Shape", &["R"])],
output_map: ("Tile", &["R"]),
return_type: ("Tile", &["_", "R"]),
}),
"load_tile_mut" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tensor", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"store_tile" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tensor", &["S"]), (1, "Tile", &["S"])],
output_map: ("()", &[]),
return_type: ("()", &[]),
}),
"convert_tile" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"check_partition_access" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Partition", &["S"])],
output_map: ("()", &[]),
return_type: ("()", &[]),
}),
"fma" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![
(0, "Tile", &["S"]),
(1, "Tile", &["S"]),
(2, "Tile", &["S"]),
],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"min_tile" | "max_tile" | "true_div" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"reduce_min" | "reduce_max" | "reduce_sum" | "reduce_prod" => Some(VariadicOpData {
const_length_vars: &["N", "M"],
cga_map: HashMap::from([("S", "N"), ("R", "M")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["R"]),
return_type: ("Tile", &["_", "R"]),
}),
"ceil" | "cosh" | "cos" | "exp" | "exp2" | "log" | "log2" | "rsqrt" | "sinh" | "sin"
| "sqrt" | "tanh" | "tan" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"select" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![
(0, "Tile", &["S"]),
(1, "Tile", &["S"]),
(2, "Tile", &["S"]),
],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"eq_tile" | "ne_tile" | "gt_tile" | "ge_tile" | "lt_tile" | "le_tile" => {
Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
})
}
"absf" | "absi" | "negf" | "negi" | "floor" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"pow" | "maxf" | "minf" | "addf" | "subf" | "mulf" | "divf" | "andi" | "ori" | "xori"
| "shli" | "shri" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"bitcast" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"atomic_rmw_tko" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "PointerTile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]), }),
"atomic_cas_tko" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![
(0, "PointerTile", &["S"]),
(1, "Tile", &["S"]),
(2, "Tile", &["S"]),
],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]), }),
"load_ptr_tko" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "PointerTile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"store_ptr_tko" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "PointerTile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Token", &[]),
return_type: ("Token", &[]),
}),
"maxi" | "mulhii" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"]), (1, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"exti" | "trunci" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"scan_sum" | "reduce" | "scan" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"int_to_ptr" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "Tile", &["S"])],
output_map: ("PointerTile", &["S"]),
return_type: ("PointerTile", &["_", "S"]),
}),
"ptr_to_int" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "PointerTile", &["S"])],
output_map: ("Tile", &["S"]),
return_type: ("Tile", &["_", "S"]),
}),
"ptr_to_ptr" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("S", "N")]),
input_map: vec![(0, "PointerTile", &["S"])],
output_map: ("PointerTile", &["S"]),
return_type: ("PointerTile", &["_", "S"]),
}),
"extract" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("SIn", "N"), ("SOut", "N")]),
input_map: vec![(0, "Tile", &["SIn"])],
output_map: ("Tile", &["SOut"]),
return_type: ("Tile", &["_", "SOut"]),
}),
"cat" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("SLhs", "N"), ("SRhs", "N"), ("SOut", "N")]),
input_map: vec![(0, "Tile", &["SLhs"]), (1, "Tile", &["SRhs"])],
output_map: ("Tile", &["SOut"]),
return_type: ("Tile", &["_", "SOut"]),
}),
"load_tensor" => Some(VariadicOpData {
const_length_vars: &["N", "M"],
cga_map: HashMap::from([("S", "N"), ("R", "M")]),
input_map: vec![(0, "Tensor", &["S"]), (2, "Shape", &["R"])],
output_map: ("Tensor", &["R"]),
return_type: ("Tensor", &["_", "R"]),
}),
"permute_array" => Some(VariadicOpData {
const_length_vars: &["N"],
cga_map: HashMap::from([("I", "N")]),
input_map: vec![(1, "Array", &["I"])],
output_map: ("()", &[]),
return_type: ("[i32; N]", &[]),
}),
_ => None,
}
}
pub fn is_variadic_op(op_name: &str) -> bool {
get_variadic_op_data(op_name).is_some()
}
#[derive(Debug, Clone)]
pub struct ConstGenericArrayType {
pub cga_arg_strings: Vec<Option<String>>,
pub n: Vec<u32>,
}
pub fn get_variadic_function_suffix(const_ga_lengths: &[u32]) -> String {
const_ga_lengths
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join("__")
}
#[derive(Debug, Clone)]
pub struct ConstGenericArrayTypeIterator {
i: u32,
i_max: u32,
n_vec: Vec<u32>,
}
impl ConstGenericArrayTypeIterator {
pub fn new(n_vec: &[u32]) -> Self {
Self {
i: 0,
n_vec: n_vec.to_vec(),
i_max: n_vec.iter().product(),
}
}
pub fn renew(&self) -> ConstGenericArrayTypeIterator {
Self {
i: 0,
n_vec: self.n_vec.clone(),
i_max: self.i_max,
}
}
}
impl Iterator for ConstGenericArrayTypeIterator {
type Item = ConstGenericArrayType;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.i_max {
None
} else {
let mut result: Vec<u32> = vec![];
let mut i = self.i;
self.i += 1;
for n in &self.n_vec {
let r = i % n;
i /= n;
result.push(r);
}
let var_names = vec![None; self.n_vec.len()];
Some(ConstGenericArrayType {
cga_arg_strings: var_names,
n: result,
})
}
}
}
#[derive(Debug, Clone)]
pub struct ConstGenericArrayTypeListIterator {
iterators: Vec<ConstGenericArrayTypeIterator>,
state: Vec<ConstGenericArrayType>,
done: bool,
}
impl ConstGenericArrayTypeListIterator {
pub fn new(iterators: Vec<ConstGenericArrayTypeIterator>) -> Self {
Self {
iterators,
state: vec![],
done: false,
}
}
}
impl Iterator for ConstGenericArrayTypeListIterator {
type Item = Result<Vec<ConstGenericArrayType>, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.state.is_empty() {
for item in &mut self.iterators {
match item.next() {
Some(item) => {
self.state.push(item);
}
None => {
return Some(call_site_error(
"ConstGenericArrayTypeListIterator: iterator was empty on first pass.",
))
}
}
}
Some(Ok(self.state.clone()))
} else if self.done {
None
} else {
for _i in 0..self.iterators.len() {
let i = (self.iterators.len() - 1) - _i;
let iter = &mut self.iterators[i];
let item: Option<ConstGenericArrayType> = iter.next();
match item {
Some(item) => {
self.state[i] = item;
break;
}
None => {
if i == 0 {
self.done = true;
return None;
}
self.iterators[i] = iter.renew();
self.state[i] = self.iterators[i].next().unwrap();
}
}
}
Some(Ok(self.state.clone()))
}
}
}
#[cfg(test)]
mod tests {
use crate::types::{ConstGenericArrayTypeIterator, ConstGenericArrayTypeListIterator};
#[test]
fn test_cg_arr_iter() -> () {
for item in ConstGenericArrayTypeIterator::new(&vec![3]) {
println!("{:?}", item);
}
for item in ConstGenericArrayTypeIterator::new(&vec![3, 3]) {
println!("{:?}", item);
}
}
#[test]
fn test_multi_cg_arr_iter() -> () {
println!("[{}]", 3);
let a = ConstGenericArrayTypeIterator::new(&vec![3]);
for item in ConstGenericArrayTypeListIterator::new(vec![a]) {
let item = item.unwrap();
println!("{:?}", item);
}
println!("[{}, {}]", 3, 3);
let a = ConstGenericArrayTypeIterator::new(&vec![3]);
let b = ConstGenericArrayTypeIterator::new(&vec![3]);
for item in ConstGenericArrayTypeListIterator::new(vec![a, b]) {
let item = item.unwrap();
println!("{:?}", item);
}
println!("[{}, {}]", 3, 3);
let a = ConstGenericArrayTypeIterator::new(&vec![2, 3]);
let b = ConstGenericArrayTypeIterator::new(&vec![4, 5]);
for item in ConstGenericArrayTypeListIterator::new(vec![a, b]) {
let item = item.unwrap();
println!("{:?}", item);
}
}
}