use prost_reflect::{Cardinality, Kind};
use super::super::FieldOrExt;
use super::output::{write_dec_i32, write_dec_u64};
#[inline]
pub(in super::super) fn push_tag_modifiers(
aw: &mut AnnWriter,
out: &mut Vec<u8>,
tag_ohb: Option<u64>,
tag_oor: bool,
len_ohb: Option<u64>,
) {
if let Some(v) = tag_ohb {
aw.push_u64_mod(out, b"tag_ohb: ", v);
}
if tag_oor {
aw.push(out, b"TAG_OOR");
}
if let Some(v) = len_ohb {
aw.push_u64_mod(out, b"len_ohb: ", v);
}
}
#[inline]
pub(in super::super) fn proto_type_str(kind: &Kind) -> &'static str {
match kind {
Kind::Double => "double",
Kind::Float => "float",
Kind::Int64 => "int64",
Kind::Uint64 => "uint64",
Kind::Int32 => "int32",
Kind::Fixed64 => "fixed64",
Kind::Fixed32 => "fixed32",
Kind::Bool => "bool",
Kind::String => "string",
Kind::Message(_) => "message", Kind::Bytes => "bytes",
Kind::Uint32 => "uint32",
Kind::Enum(_) => "enum",
Kind::Sfixed32 => "sfixed32",
Kind::Sfixed64 => "sfixed64",
Kind::Sint32 => "sint32",
Kind::Sint64 => "sint64",
}
}
pub(in super::super) fn field_decl(
field_number: u64,
field_schema: Option<&FieldOrExt>,
) -> Option<String> {
let fi = field_schema?;
let label_prefix = match fi.cardinality() {
Cardinality::Required => "required ",
Cardinality::Repeated => "repeated ",
Cardinality::Optional => "",
};
let kind = fi.kind();
let type_str = proto_type_str(&kind);
let type_display = match &kind {
Kind::Message(msg_desc) => msg_desc.name().to_string(),
Kind::Enum(enum_desc) => enum_desc.name().to_string(),
_ => type_str.to_string(),
};
let packed = if fi.is_packed() { " [packed=true]" } else { "" };
Some(format!(
"{}{}{} = {}",
label_prefix, type_display, packed, field_number
))
}
pub(in super::super) struct AnnWriter {
started: bool,
no_leading_spaces: bool,
}
impl AnnWriter {
#[inline]
pub(in super::super) fn new() -> Self {
Self {
started: false,
no_leading_spaces: false,
}
}
#[inline]
pub(in super::super) fn new_no_leading_spaces() -> Self {
Self {
started: false,
no_leading_spaces: true,
}
}
#[inline]
pub(in super::super) fn sep(&mut self, out: &mut Vec<u8>) {
if self.started {
out.extend_from_slice(b"; ");
} else {
if self.no_leading_spaces {
out.extend_from_slice(b"#@ ");
} else {
out.extend_from_slice(b" #@ ");
}
self.started = true;
}
}
#[inline]
pub(in super::super) fn push(&mut self, out: &mut Vec<u8>, s: &[u8]) {
self.sep(out);
out.extend_from_slice(s);
}
#[inline]
pub(in super::super) fn push_wire(&mut self, out: &mut Vec<u8>, name: &str) {
self.sep(out);
out.extend_from_slice(name.as_bytes());
}
#[inline]
pub(in super::super) fn push_u64_mod(&mut self, out: &mut Vec<u8>, key: &[u8], v: u64) {
self.sep(out);
out.extend_from_slice(key);
write_dec_u64(v, out);
}
#[inline]
pub(in super::super) fn push_field_decl(
&mut self,
out: &mut Vec<u8>,
num: u64,
fs: Option<&FieldOrExt>,
enum_raw: Option<i32>,
enum_packed_nums: Option<&[i32]>,
) {
let Some(fi) = fs else { return };
self.sep(out);
match fi.cardinality() {
Cardinality::Required => {
out.extend_from_slice(b"required ");
}
Cardinality::Repeated => {
out.extend_from_slice(b"repeated ");
}
Cardinality::Optional => {}
}
let kind = fi.kind();
if let Kind::Enum(ref enum_desc) = kind {
let type_display = enum_desc.name();
out.extend_from_slice(type_display.as_bytes());
if let Some(nums) = enum_packed_nums {
out.push(b'(');
out.push(b'[');
for (i, &n) in nums.iter().enumerate() {
if i > 0 {
out.extend_from_slice(b", ");
}
write_dec_i32(n, out);
}
out.push(b']');
out.push(b')');
} else if let Some(n) = enum_raw {
out.push(b'(');
write_dec_i32(n, out);
out.push(b')');
}
} else {
let type_display = match &kind {
Kind::Message(msg_desc) => msg_desc.name().to_string(),
_ => proto_type_str(&kind).to_string(),
};
out.extend_from_slice(type_display.as_bytes());
}
if fi.is_packed() {
out.extend_from_slice(b" [packed=true]");
}
out.extend_from_slice(b" = ");
write_dec_u64(num, out);
}
}