use core::str::FromStr;
use anyhow::bail;
use quote::__private::TokenStream;
use quote::quote;
use protokit_desc::{DataType, FieldDef, Frequency};
use protokit_proto::translate::TranslateCtx;
use crate::filegen::Options;
pub fn tabular_parser(ctx: &TranslateCtx, opts: &Options, f: &FieldDef, i: usize) -> Result<TokenStream> {
use crate::BuiltinType::*;
let str = TokenStream::from_str(&type_to_str(ctx, opts, &f.typ)?).unwrap();
Ok(match &f.typ {
DataType::Builtin(String_ | Bytes_) if f.is_repeated() => quote!( Bytes::<Vec<#str>, #i> ),
DataType::Builtin(String_ | Bytes_) => quote!( Bytes::<#str, #i> ),
DataType::Builtin(bt) if bt.is_varint() && bt.is_zigzag() && f.is_repeated_packed() => {
quote! { PackedSInt::<#str, #i> }
}
DataType::Builtin(bt) if bt.is_varint() && bt.is_zigzag() => {
quote! { SInt::<#str, #i> }
}
DataType::Builtin(bt) if bt.is_varint() && f.is_repeated_packed() => {
quote! { PackedVInt::<#str, #i> }
}
DataType::Builtin(bt) if bt.is_varint() => {
quote! { VInt::<#str, #i> }
}
DataType::Builtin(_bt) if f.is_repeated_packed() => {
quote! { PackedFixed::<#str, #i> }
}
DataType::Builtin(_bt) => {
quote! { Fixed::<#str, #i> }
}
DataType::Message(_m) if f.is_repeated() => {
quote! { Repeated::<#str, #i> }
}
DataType::Message(_m) => {
quote! { Nested::<#str, #i> }
}
DataType::Enum(_m) if f.is_repeated() => {
quote! { Enum::<#str, #i> }
}
DataType::Enum(_m) => {
quote! { Enum::<#str, #i> }
}
DataType::Map(m) => {
let kf = FieldDef {
name: Default::default(),
frequency: Frequency::Normal,
typ: DataType::Builtin(m.0.clone()),
num: 0,
#[cfg(feature = "descriptors")]
options: Default::default(),
};
let kp = tabular_parser(ctx, opts, &kf, 1)?;
let _vf = FieldDef {
name: Default::default(),
frequency: Frequency::Normal,
typ: m.1.clone(),
num: 0,
#[cfg(feature = "descriptors")]
options: Default::default(),
};
let vp = tabular_parser(ctx, opts, &kf, 1)?;
quote! { Mapped::<binformat::tabular::#kp, binformat::tabular::#vp, #i> }
}
other => bail!("Unknown: {other:?}"),
})
}
pub fn gnerate_tabular_field() {
let taglen = u64::required_space(normal_tag as u64);
let tabular = tabular_parser(ctx, opts, &field, taglen).unwrap();
let encoded_tag = protokit_binformat::tabular::tag(normal_tag);
let field_num = field_idx as u32;
out.tabular_fields.insert(encoded_tag,quote! {
binformat::tabular::FieldInfo {
tag: #encoded_tag,
offset: binformat::tabular::offset_of!(#msg_name, #name) as isize,
parser: <binformat::tabular::#tabular as binformat::tabular::Format>::decode,
number: #field_num,
}
});
}