diff --git a/Cargo.lock b/Cargo.lock index 68048f5..f34f795 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,6 +478,10 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protos" +version = "0.1.0" + [[package]] name = "quote" version = "1.0.45" @@ -537,15 +541,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "roto" +name = "roto-benches" version = "0.1.0" dependencies = [ "clap", "criterion", "env_logger", "log", + "roto-runtime", ] +[[package]] +name = "roto-codegen" +version = "0.1.0" +dependencies = [ + "clap", + "env_logger", + "log", + "roto-runtime", +] + +[[package]] +name = "roto-runtime" +version = "0.1.0" + [[package]] name = "rustversion" version = "1.0.22" diff --git a/Cargo.toml b/Cargo.toml index 97bd00c..44e1d9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,11 @@ -[package] -name = "roto" -version = "0.1.0" -edition = "2024" +[workspace] +members = [ + "runtime", + "codegen", + "protos", + "benches", +] -[dependencies] -clap = { version = "4", features = ["derive"] } -log = "0.4" -env_logger = "0.11" - -[dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } - -[[bench]] -name = "hackers_bench" -harness = false +exclude = [ + "test_gen_project" +] diff --git a/benches/.gitignore b/benches/.gitignore new file mode 100644 index 0000000..1269488 --- /dev/null +++ b/benches/.gitignore @@ -0,0 +1 @@ +data diff --git a/benches/Cargo.toml b/benches/Cargo.toml new file mode 100644 index 0000000..a8bbb74 --- /dev/null +++ b/benches/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "roto-benches" +version = "0.1.0" +edition = "2024" + +[dependencies] +roto-runtime = { path = "../runtime" } +clap = { version = "4", features = ["derive"] } +log = "0.4" +env_logger = "0.11" + + +[dev-dependencies] +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "hackers_bench" +harness = false diff --git a/benches/hackers_bench.rs b/benches/benches/hackers_bench.rs similarity index 99% rename from benches/hackers_bench.rs rename to benches/benches/hackers_bench.rs index 34fe054..9f6509b 100644 --- a/benches/hackers_bench.rs +++ b/benches/benches/hackers_bench.rs @@ -27,7 +27,7 @@ //! - `iterate` — counting repeated fields at different nesting depths use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; -use roto::hackers::{Campaign, Hacker, Operation, Worm}; +use roto_benches::hackers::{Campaign, Hacker, Operation, Worm}; use std::hint::black_box; // ============================================================================= diff --git a/src/bin/gen_bench_data.rs b/benches/src/bin/gen_bench_data.rs similarity index 98% rename from src/bin/gen_bench_data.rs rename to benches/src/bin/gen_bench_data.rs index ad0d558..3273938 100644 --- a/src/bin/gen_bench_data.rs +++ b/benches/src/bin/gen_bench_data.rs @@ -17,7 +17,7 @@ //! Files land in `data/bench/` by default. use clap::Parser; -use roto::hackers::{ +use roto_benches::hackers::{ CampaignBuilder, ConnectionBuilder, HackerBuilder, OperationBuilder, ToolBuilder, WormBuilder, }; use std::io::{self, Write}; @@ -449,10 +449,11 @@ fn main() { ); // Default output: data/bench/.pb, or stdout if no output and no preset - let out_path = args - .output - .clone() - .or_else(|| args.preset.as_ref().map(|p| format!("data/bench/{}.pb", p))); + let out_path = args.output.clone().or_else(|| { + args.preset + .as_ref() + .map(|p| format!("benches/data/bench/{}.pb", p)) + }); match out_path { Some(ref path) => { diff --git a/src/google/mod.rs b/benches/src/google/mod.rs similarity index 100% rename from src/google/mod.rs rename to benches/src/google/mod.rs diff --git a/src/google/protobuf/compiler/mod.rs b/benches/src/google/protobuf/compiler/mod.rs similarity index 100% rename from src/google/protobuf/compiler/mod.rs rename to benches/src/google/protobuf/compiler/mod.rs diff --git a/src/google/protobuf/compiler/plugin.rs b/benches/src/google/protobuf/compiler/plugin.rs similarity index 100% rename from src/google/protobuf/compiler/plugin.rs rename to benches/src/google/protobuf/compiler/plugin.rs diff --git a/src/google/protobuf/descriptor.rs b/benches/src/google/protobuf/descriptor.rs similarity index 100% rename from src/google/protobuf/descriptor.rs rename to benches/src/google/protobuf/descriptor.rs diff --git a/src/google/protobuf/mod.rs b/benches/src/google/protobuf/mod.rs similarity index 100% rename from src/google/protobuf/mod.rs rename to benches/src/google/protobuf/mod.rs diff --git a/src/hackers.rs b/benches/src/hackers.rs similarity index 50% rename from src/hackers.rs rename to benches/src/hackers.rs index aadad46..e395e34 100644 --- a/src/hackers.rs +++ b/benches/src/hackers.rs @@ -1,12 +1,13 @@ // @generated by protoc-gen-roto — do not edit #![allow(unused_imports)] -use crate::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator}; +use roto_runtime::{ + ProtoAccessor, ProtoBuilder, RepeatedFieldIterator, Result, RotoError, read_varint, +}; use std::str; - pub struct Tool<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, version_offset: Option, payload_offset: Option, @@ -15,8 +16,8 @@ pub struct Tool<'a> { } impl<'a> Tool<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut name_offset = None; let mut version_offset = None; let mut payload_offset = None; @@ -24,61 +25,84 @@ impl<'a> Tool<'a> { let mut exploit_count_offset = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { name_offset = Some(offset); } - if tag.field_number == 2 { version_offset = Some(offset); } - if tag.field_number == 3 { payload_offset = Some(offset); } - if tag.field_number == 4 { is_active_offset = Some(offset); } - if tag.field_number == 5 { exploit_count_offset = Some(offset); } + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + version_offset = Some(offset); + } + if tag.field_number == 3 { + payload_offset = Some(offset); + } + if tag.field_number == 4 { + is_active_offset = Some(offset); + } + if tag.field_number == 5 { + exploit_count_offset = Some(offset); + } } Ok(Self { accessor, -name_offset, -version_offset, -payload_offset, -is_active_offset, -exploit_count_offset, + name_offset, + version_offset, + payload_offset, + is_active_offset, + exploit_count_offset, }) } - pub fn name(&self) -> crate::Result<&'a str> { - let offset = self.name_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn version(&self) -> crate::Result<&'a str> { - let offset = self.version_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn version(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .version_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn payload(&self) -> crate::Result<&'a [u8]> { - let offset = self.payload_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn payload(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .payload_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn is_active(&self) -> crate::Result { - let offset = self.is_active_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn is_active(&self) -> roto_runtime::Result { + let offset = self + .is_active_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn exploit_count(&self) -> crate::Result { - let offset = self.exploit_count_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn exploit_count(&self) -> roto_runtime::Result { + let offset = self + .exploit_count_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct ToolBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, name_written: bool, version_written: bool, payload_written: bool, @@ -89,7 +113,7 @@ pub struct ToolBuilder<'b> { impl<'b> ToolBuilder<'b> { pub fn builder(buf: &mut [u8]) -> ToolBuilder<'_> { ToolBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), name_written: false, version_written: false, payload_written: false, @@ -98,37 +122,37 @@ impl<'b> ToolBuilder<'b> { } } - pub fn name(mut self, value: &str) -> crate::Result { + pub fn name(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.name_written = true; Ok(self) } - pub fn version(mut self, value: &str) -> crate::Result { + pub fn version(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(2, value)?; self.version_written = true; Ok(self) } - pub fn payload(mut self, value: &[u8]) -> crate::Result { + pub fn payload(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(3, value)?; self.payload_written = true; Ok(self) } - pub fn is_active(mut self, value: u64) -> crate::Result { + pub fn is_active(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(4, value)?; self.is_active_written = true; Ok(self) } - pub fn exploit_count(mut self, value: i32) -> crate::Result { + pub fn exploit_count(mut self, value: i32) -> roto_runtime::Result { self.builder.write_int32(5, value)?; self.exploit_count_written = true; Ok(self) } - pub fn with(mut self, msg: &Tool<'_>) -> crate::Result { + pub fn with(mut self, msg: &Tool<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -146,13 +170,13 @@ impl<'b> ToolBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } pub struct Connection<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, host_offset: Option, port_offset: Option, encrypted_offset: Option, @@ -161,8 +185,8 @@ pub struct Connection<'a> { } impl<'a> Connection<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut host_offset = None; let mut port_offset = None; let mut encrypted_offset = None; @@ -170,61 +194,86 @@ impl<'a> Connection<'a> { let mut session_key_offset = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { host_offset = Some(offset); } - if tag.field_number == 2 { port_offset = Some(offset); } - if tag.field_number == 3 { encrypted_offset = Some(offset); } - if tag.field_number == 4 { bandwidth_bps_offset = Some(offset); } - if tag.field_number == 5 { session_key_offset = Some(offset); } + if tag.field_number == 1 { + host_offset = Some(offset); + } + if tag.field_number == 2 { + port_offset = Some(offset); + } + if tag.field_number == 3 { + encrypted_offset = Some(offset); + } + if tag.field_number == 4 { + bandwidth_bps_offset = Some(offset); + } + if tag.field_number == 5 { + session_key_offset = Some(offset); + } } Ok(Self { accessor, -host_offset, -port_offset, -encrypted_offset, -bandwidth_bps_offset, -session_key_offset, + host_offset, + port_offset, + encrypted_offset, + bandwidth_bps_offset, + session_key_offset, }) } - pub fn host(&self) -> crate::Result<&'a str> { - let offset = self.host_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn host(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .host_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn port(&self) -> crate::Result { - let offset = self.port_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn port(&self) -> roto_runtime::Result { + let offset = self + .port_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn encrypted(&self) -> crate::Result { - let offset = self.encrypted_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn encrypted(&self) -> roto_runtime::Result { + let offset = self + .encrypted_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn bandwidth_bps(&self) -> crate::Result { - let offset = self.bandwidth_bps_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn bandwidth_bps(&self) -> roto_runtime::Result { + let offset = self + .bandwidth_bps_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn session_key(&self) -> crate::Result<&'a [u8]> { - let offset = self.session_key_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn session_key(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .session_key_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct ConnectionBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, host_written: bool, port_written: bool, encrypted_written: bool, @@ -235,7 +284,7 @@ pub struct ConnectionBuilder<'b> { impl<'b> ConnectionBuilder<'b> { pub fn builder(buf: &mut [u8]) -> ConnectionBuilder<'_> { ConnectionBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), host_written: false, port_written: false, encrypted_written: false, @@ -244,37 +293,37 @@ impl<'b> ConnectionBuilder<'b> { } } - pub fn host(mut self, value: &str) -> crate::Result { + pub fn host(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.host_written = true; Ok(self) } - pub fn port(mut self, value: i32) -> crate::Result { + pub fn port(mut self, value: i32) -> roto_runtime::Result { self.builder.write_int32(2, value)?; self.port_written = true; Ok(self) } - pub fn encrypted(mut self, value: u64) -> crate::Result { + pub fn encrypted(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(3, value)?; self.encrypted_written = true; Ok(self) } - pub fn bandwidth_bps(mut self, value: u64) -> crate::Result { + pub fn bandwidth_bps(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(4, value)?; self.bandwidth_bps_written = true; Ok(self) } - pub fn session_key(mut self, value: &[u8]) -> crate::Result { + pub fn session_key(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(5, value)?; self.session_key_written = true; Ok(self) } - pub fn with(mut self, msg: &Connection<'_>) -> crate::Result { + pub fn with(mut self, msg: &Connection<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -292,13 +341,13 @@ impl<'b> ConnectionBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } pub struct Hacker<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, handle_offset: Option, real_name_offset: Option, age_offset: Option, @@ -313,8 +362,8 @@ pub struct Hacker<'a> { } impl<'a> Hacker<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut handle_offset = None; let mut real_name_offset = None; let mut age_offset = None; @@ -328,101 +377,144 @@ impl<'a> Hacker<'a> { let mut active_connection_offset = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { handle_offset = Some(offset); } - if tag.field_number == 2 { real_name_offset = Some(offset); } - if tag.field_number == 3 { age_offset = Some(offset); } - if tag.field_number == 4 { skill_level_offset = Some(offset); } - if tag.field_number == 5 { is_elite_offset = Some(offset); } - if tag.field_number == 6 { crew_id_offset = Some(offset); } + if tag.field_number == 1 { + handle_offset = Some(offset); + } + if tag.field_number == 2 { + real_name_offset = Some(offset); + } + if tag.field_number == 3 { + age_offset = Some(offset); + } + if tag.field_number == 4 { + skill_level_offset = Some(offset); + } + if tag.field_number == 5 { + is_elite_offset = Some(offset); + } + if tag.field_number == 6 { + crew_id_offset = Some(offset); + } if tag.field_number == 7 { - if exploits_start.is_none() { exploits_start = Some(offset); } + if exploits_start.is_none() { + exploits_start = Some(offset); + } exploits_end = Some(offset); } if tag.field_number == 8 { - if tools_start.is_none() { tools_start = Some(offset); } + if tools_start.is_none() { + tools_start = Some(offset); + } tools_end = Some(offset); } - if tag.field_number == 9 { active_connection_offset = Some(offset); } + if tag.field_number == 9 { + active_connection_offset = Some(offset); + } } Ok(Self { accessor, -handle_offset, -real_name_offset, -age_offset, -skill_level_offset, -is_elite_offset, -crew_id_offset, -exploits_start, exploits_end, -tools_start, tools_end, -active_connection_offset, + handle_offset, + real_name_offset, + age_offset, + skill_level_offset, + is_elite_offset, + crew_id_offset, + exploits_start, + exploits_end, + tools_start, + tools_end, + active_connection_offset, }) } - pub fn handle(&self) -> crate::Result<&'a str> { - let offset = self.handle_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn handle(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .handle_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn real_name(&self) -> crate::Result<&'a str> { - let offset = self.real_name_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn real_name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .real_name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn age(&self) -> crate::Result { - let offset = self.age_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn age(&self) -> roto_runtime::Result { + let offset = self + .age_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn skill_level(&self) -> crate::Result { - let offset = self.skill_level_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn skill_level(&self) -> roto_runtime::Result { + let offset = self + .skill_level_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - Ok(f32::from_le_bytes(bytes.try_into().map_err(|_| crate::RotoError::WireFormatViolation)?)) + Ok(f32::from_le_bytes( + bytes + .try_into() + .map_err(|_| RotoError::WireFormatViolation)?, + )) } - pub fn is_elite(&self) -> crate::Result { - let offset = self.is_elite_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn is_elite(&self) -> roto_runtime::Result { + let offset = self + .is_elite_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn crew_id(&self) -> crate::Result { - let offset = self.crew_id_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn crew_id(&self) -> roto_runtime::Result { + let offset = self + .crew_id_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn exploits(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn exploits(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.exploits_start, self.exploits_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(7, start, end), _ => self.accessor.iter_repeated(7), } } - pub fn tools(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn tools(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.tools_start, self.tools_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(8, start, end), _ => self.accessor.iter_repeated(8), } } - pub fn active_connection(&self) -> crate::Result<&'a [u8]> { - let offset = self.active_connection_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn active_connection(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .active_connection_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct HackerBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, handle_written: bool, real_name_written: bool, age_written: bool, @@ -437,7 +529,7 @@ pub struct HackerBuilder<'b> { impl<'b> HackerBuilder<'b> { pub fn builder(buf: &mut [u8]) -> HackerBuilder<'_> { HackerBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), handle_written: false, real_name_written: false, age_written: false, @@ -450,61 +542,61 @@ impl<'b> HackerBuilder<'b> { } } - pub fn handle(mut self, value: &str) -> crate::Result { + pub fn handle(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.handle_written = true; Ok(self) } - pub fn real_name(mut self, value: &str) -> crate::Result { + pub fn real_name(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(2, value)?; self.real_name_written = true; Ok(self) } - pub fn age(mut self, value: i32) -> crate::Result { + pub fn age(mut self, value: i32) -> roto_runtime::Result { self.builder.write_int32(3, value)?; self.age_written = true; Ok(self) } - pub fn skill_level(mut self, value: &[u8]) -> crate::Result { + pub fn skill_level(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(4, value)?; self.skill_level_written = true; Ok(self) } - pub fn is_elite(mut self, value: u64) -> crate::Result { + pub fn is_elite(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(5, value)?; self.is_elite_written = true; Ok(self) } - pub fn crew_id(mut self, value: u64) -> crate::Result { + pub fn crew_id(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(6, value)?; self.crew_id_written = true; Ok(self) } - pub fn exploits(mut self, value: &str) -> crate::Result { + pub fn exploits(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(7, value)?; self.exploits_written = true; Ok(self) } - pub fn tools(mut self, value: &[u8]) -> crate::Result { + pub fn tools(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(8, value)?; self.tools_written = true; Ok(self) } - pub fn active_connection(mut self, value: &[u8]) -> crate::Result { + pub fn active_connection(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(9, value)?; self.active_connection_written = true; Ok(self) } - pub fn with(mut self, msg: &Hacker<'_>) -> crate::Result { + pub fn with(mut self, msg: &Hacker<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -526,13 +618,13 @@ impl<'b> HackerBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } pub struct Worm<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, variant_offset: Option, size_bytes_offset: Option, @@ -543,8 +635,8 @@ pub struct Worm<'a> { } impl<'a> Worm<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut name_offset = None; let mut variant_offset = None; let mut size_bytes_offset = None; @@ -554,73 +646,101 @@ impl<'a> Worm<'a> { let mut targets_end = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { name_offset = Some(offset); } - if tag.field_number == 2 { variant_offset = Some(offset); } - if tag.field_number == 3 { size_bytes_offset = Some(offset); } - if tag.field_number == 4 { payload_offset = Some(offset); } - if tag.field_number == 5 { polymorphic_offset = Some(offset); } + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + variant_offset = Some(offset); + } + if tag.field_number == 3 { + size_bytes_offset = Some(offset); + } + if tag.field_number == 4 { + payload_offset = Some(offset); + } + if tag.field_number == 5 { + polymorphic_offset = Some(offset); + } if tag.field_number == 6 { - if targets_start.is_none() { targets_start = Some(offset); } + if targets_start.is_none() { + targets_start = Some(offset); + } targets_end = Some(offset); } } Ok(Self { accessor, -name_offset, -variant_offset, -size_bytes_offset, -payload_offset, -polymorphic_offset, -targets_start, targets_end, + name_offset, + variant_offset, + size_bytes_offset, + payload_offset, + polymorphic_offset, + targets_start, + targets_end, }) } - pub fn name(&self) -> crate::Result<&'a str> { - let offset = self.name_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn variant(&self) -> crate::Result { - let offset = self.variant_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn variant(&self) -> roto_runtime::Result { + let offset = self + .variant_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn size_bytes(&self) -> crate::Result { - let offset = self.size_bytes_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn size_bytes(&self) -> roto_runtime::Result { + let offset = self + .size_bytes_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn payload(&self) -> crate::Result<&'a [u8]> { - let offset = self.payload_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn payload(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .payload_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn polymorphic(&self) -> crate::Result { - let offset = self.polymorphic_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn polymorphic(&self) -> roto_runtime::Result { + let offset = self + .polymorphic_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn targets(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn targets(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.targets_start, self.targets_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(6, start, end), _ => self.accessor.iter_repeated(6), } } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct WormBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, name_written: bool, variant_written: bool, size_bytes_written: bool, @@ -632,7 +752,7 @@ pub struct WormBuilder<'b> { impl<'b> WormBuilder<'b> { pub fn builder(buf: &mut [u8]) -> WormBuilder<'_> { WormBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), name_written: false, variant_written: false, size_bytes_written: false, @@ -642,43 +762,43 @@ impl<'b> WormBuilder<'b> { } } - pub fn name(mut self, value: &str) -> crate::Result { + pub fn name(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.name_written = true; Ok(self) } - pub fn variant(mut self, value: i32) -> crate::Result { + pub fn variant(mut self, value: i32) -> roto_runtime::Result { self.builder.write_int32(2, value)?; self.variant_written = true; Ok(self) } - pub fn size_bytes(mut self, value: u64) -> crate::Result { + pub fn size_bytes(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(3, value)?; self.size_bytes_written = true; Ok(self) } - pub fn payload(mut self, value: &[u8]) -> crate::Result { + pub fn payload(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(4, value)?; self.payload_written = true; Ok(self) } - pub fn polymorphic(mut self, value: u64) -> crate::Result { + pub fn polymorphic(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(5, value)?; self.polymorphic_written = true; Ok(self) } - pub fn targets(mut self, value: &str) -> crate::Result { + pub fn targets(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(6, value)?; self.targets_written = true; Ok(self) } - pub fn with(mut self, msg: &Worm<'_>) -> crate::Result { + pub fn with(mut self, msg: &Worm<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -697,13 +817,13 @@ impl<'b> WormBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } pub struct Operation<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, codename_offset: Option, target_corp_offset: Option, timestamp_offset: Option, @@ -718,8 +838,8 @@ pub struct Operation<'a> { } impl<'a> Operation<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut codename_offset = None; let mut target_corp_offset = None; let mut timestamp_offset = None; @@ -733,101 +853,140 @@ impl<'a> Operation<'a> { let mut severity_offset = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { codename_offset = Some(offset); } - if tag.field_number == 2 { target_corp_offset = Some(offset); } - if tag.field_number == 3 { timestamp_offset = Some(offset); } - if tag.field_number == 4 { successful_offset = Some(offset); } - if tag.field_number == 5 { stolen_data_offset = Some(offset); } + if tag.field_number == 1 { + codename_offset = Some(offset); + } + if tag.field_number == 2 { + target_corp_offset = Some(offset); + } + if tag.field_number == 3 { + timestamp_offset = Some(offset); + } + if tag.field_number == 4 { + successful_offset = Some(offset); + } + if tag.field_number == 5 { + stolen_data_offset = Some(offset); + } if tag.field_number == 6 { - if crew_start.is_none() { crew_start = Some(offset); } + if crew_start.is_none() { + crew_start = Some(offset); + } crew_end = Some(offset); } - if tag.field_number == 7 { worm_offset = Some(offset); } + if tag.field_number == 7 { + worm_offset = Some(offset); + } if tag.field_number == 8 { - if log_entries_start.is_none() { log_entries_start = Some(offset); } + if log_entries_start.is_none() { + log_entries_start = Some(offset); + } log_entries_end = Some(offset); } - if tag.field_number == 9 { severity_offset = Some(offset); } + if tag.field_number == 9 { + severity_offset = Some(offset); + } } Ok(Self { accessor, -codename_offset, -target_corp_offset, -timestamp_offset, -successful_offset, -stolen_data_offset, -crew_start, crew_end, -worm_offset, -log_entries_start, log_entries_end, -severity_offset, + codename_offset, + target_corp_offset, + timestamp_offset, + successful_offset, + stolen_data_offset, + crew_start, + crew_end, + worm_offset, + log_entries_start, + log_entries_end, + severity_offset, }) } - pub fn codename(&self) -> crate::Result<&'a str> { - let offset = self.codename_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn codename(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .codename_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn target_corp(&self) -> crate::Result<&'a str> { - let offset = self.target_corp_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn target_corp(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .target_corp_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn timestamp(&self) -> crate::Result { - let offset = self.timestamp_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn timestamp(&self) -> roto_runtime::Result { + let offset = self + .timestamp_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn successful(&self) -> crate::Result { - let offset = self.successful_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn successful(&self) -> roto_runtime::Result { + let offset = self + .successful_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn stolen_data(&self) -> crate::Result<&'a [u8]> { - let offset = self.stolen_data_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn stolen_data(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .stolen_data_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn crew(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn crew(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.crew_start, self.crew_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(6, start, end), _ => self.accessor.iter_repeated(6), } } - pub fn worm(&self) -> crate::Result<&'a [u8]> { - let offset = self.worm_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn worm(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .worm_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; Ok(bytes) } - pub fn log_entries(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn log_entries(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.log_entries_start, self.log_entries_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(8, start, end), _ => self.accessor.iter_repeated(8), } } - pub fn severity(&self) -> crate::Result { - let offset = self.severity_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn severity(&self) -> roto_runtime::Result { + let offset = self + .severity_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct OperationBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, codename_written: bool, target_corp_written: bool, timestamp_written: bool, @@ -842,7 +1001,7 @@ pub struct OperationBuilder<'b> { impl<'b> OperationBuilder<'b> { pub fn builder(buf: &mut [u8]) -> OperationBuilder<'_> { OperationBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), codename_written: false, target_corp_written: false, timestamp_written: false, @@ -855,61 +1014,61 @@ impl<'b> OperationBuilder<'b> { } } - pub fn codename(mut self, value: &str) -> crate::Result { + pub fn codename(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.codename_written = true; Ok(self) } - pub fn target_corp(mut self, value: &str) -> crate::Result { + pub fn target_corp(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(2, value)?; self.target_corp_written = true; Ok(self) } - pub fn timestamp(mut self, value: u64) -> crate::Result { + pub fn timestamp(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(3, value)?; self.timestamp_written = true; Ok(self) } - pub fn successful(mut self, value: u64) -> crate::Result { + pub fn successful(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(4, value)?; self.successful_written = true; Ok(self) } - pub fn stolen_data(mut self, value: &[u8]) -> crate::Result { + pub fn stolen_data(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(5, value)?; self.stolen_data_written = true; Ok(self) } - pub fn crew(mut self, value: &[u8]) -> crate::Result { + pub fn crew(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(6, value)?; self.crew_written = true; Ok(self) } - pub fn worm(mut self, value: &[u8]) -> crate::Result { + pub fn worm(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(7, value)?; self.worm_written = true; Ok(self) } - pub fn log_entries(mut self, value: &str) -> crate::Result { + pub fn log_entries(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(8, value)?; self.log_entries_written = true; Ok(self) } - pub fn severity(mut self, value: i32) -> crate::Result { + pub fn severity(mut self, value: i32) -> roto_runtime::Result { self.builder.write_int32(9, value)?; self.severity_written = true; Ok(self) } - pub fn with(mut self, msg: &Operation<'_>) -> crate::Result { + pub fn with(mut self, msg: &Operation<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -931,13 +1090,13 @@ impl<'b> OperationBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } pub struct Campaign<'a> { - accessor: crate::ProtoAccessor<'a>, + accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, operations_start: Option, operations_end: Option, @@ -945,57 +1104,69 @@ pub struct Campaign<'a> { } impl<'a> Campaign<'a> { - pub fn new(data: &'a [u8]) -> crate::Result { - let accessor = crate::ProtoAccessor::new(data)?; + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; let mut name_offset = None; let mut operations_start = None; let mut operations_end = None; let mut total_bytes_stolen_offset = None; for item in accessor.fields() { let (offset, tag, _) = item?; - if tag.field_number == 1 { name_offset = Some(offset); } + if tag.field_number == 1 { + name_offset = Some(offset); + } if tag.field_number == 2 { - if operations_start.is_none() { operations_start = Some(offset); } + if operations_start.is_none() { + operations_start = Some(offset); + } operations_end = Some(offset); } - if tag.field_number == 3 { total_bytes_stolen_offset = Some(offset); } + if tag.field_number == 3 { + total_bytes_stolen_offset = Some(offset); + } } Ok(Self { accessor, -name_offset, -operations_start, operations_end, -total_bytes_stolen_offset, + name_offset, + operations_start, + operations_end, + total_bytes_stolen_offset, }) } - pub fn name(&self) -> crate::Result<&'a str> { - let offset = self.name_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| crate::RotoError::WireFormatViolation) + str::from_utf8(bytes).map_err(|_| RotoError::WireFormatViolation) } - pub fn operations(&self) -> crate::RepeatedFieldIterator<'a> { + pub fn operations(&self) -> roto_runtime::RepeatedFieldIterator<'a> { match (self.operations_start, self.operations_end) { (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), _ => self.accessor.iter_repeated(2), } } - pub fn total_bytes_stolen(&self) -> crate::Result { - let offset = self.total_bytes_stolen_offset.ok_or(crate::RotoError::FieldNotFound)?; + pub fn total_bytes_stolen(&self) -> roto_runtime::Result { + let offset = self + .total_bytes_stolen_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; let (bytes, _) = self.accessor.get_value_at(offset)?; - crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation) + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) } - pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> { + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { self.accessor.raw_fields() } - } pub struct CampaignBuilder<'b> { - builder: crate::ProtoBuilder<'b>, + builder: roto_runtime::ProtoBuilder<'b>, name_written: bool, operations_written: bool, total_bytes_stolen_written: bool, @@ -1004,32 +1175,32 @@ pub struct CampaignBuilder<'b> { impl<'b> CampaignBuilder<'b> { pub fn builder(buf: &mut [u8]) -> CampaignBuilder<'_> { CampaignBuilder { - builder: crate::ProtoBuilder::new(buf), + builder: roto_runtime::ProtoBuilder::new(buf), name_written: false, operations_written: false, total_bytes_stolen_written: false, } } - pub fn name(mut self, value: &str) -> crate::Result { + pub fn name(mut self, value: &str) -> roto_runtime::Result { self.builder.write_string(1, value)?; self.name_written = true; Ok(self) } - pub fn operations(mut self, value: &[u8]) -> crate::Result { + pub fn operations(mut self, value: &[u8]) -> roto_runtime::Result { self.builder.write_bytes(2, value)?; self.operations_written = true; Ok(self) } - pub fn total_bytes_stolen(mut self, value: u64) -> crate::Result { + pub fn total_bytes_stolen(mut self, value: u64) -> roto_runtime::Result { self.builder.write_varint(3, value)?; self.total_bytes_stolen_written = true; Ok(self) } - pub fn with(mut self, msg: &Campaign<'_>) -> crate::Result { + pub fn with(mut self, msg: &Campaign<'_>) -> roto_runtime::Result { for item in msg.raw_fields() { let (field_number, raw_bytes) = item?; let is_written = match field_number { @@ -1045,8 +1216,7 @@ impl<'b> CampaignBuilder<'b> { Ok(self) } - pub fn finish(self) -> crate::Result<&'b mut [u8]> { + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { self.builder.finish() } } - diff --git a/benches/src/lib.rs b/benches/src/lib.rs new file mode 100644 index 0000000..45981ed --- /dev/null +++ b/benches/src/lib.rs @@ -0,0 +1 @@ +pub mod hackers; diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml new file mode 100644 index 0000000..d7c36a7 --- /dev/null +++ b/codegen/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "roto-codegen" +version = "0.1.0" +edition = "2024" + +[dependencies] +roto-runtime = { path = "../runtime" } +clap = { version = "4", features = ["derive"] } +log = "0.4" +env_logger = "0.11" diff --git a/data/.gitignore b/codegen/data/.gitignore similarity index 100% rename from data/.gitignore rename to codegen/data/.gitignore diff --git a/data/descriptor.desc b/codegen/data/descriptor.desc similarity index 100% rename from data/descriptor.desc rename to codegen/data/descriptor.desc diff --git a/data/request.bin b/codegen/data/request.bin similarity index 100% rename from data/request.bin rename to codegen/data/request.bin diff --git a/data/test_data.pb b/codegen/data/test_data.pb similarity index 100% rename from data/test_data.pb rename to codegen/data/test_data.pb diff --git a/data/test_data.textproto b/codegen/data/test_data.textproto similarity index 100% rename from data/test_data.textproto rename to codegen/data/test_data.textproto diff --git a/data/test_types.desc b/codegen/data/test_types.desc similarity index 100% rename from data/test_types.desc rename to codegen/data/test_types.desc diff --git a/data/test_types.proto b/codegen/data/test_types.proto similarity index 100% rename from data/test_types.proto rename to codegen/data/test_types.proto diff --git a/codegen/proto/google/protobuf/compiler/plugin.proto b/codegen/proto/google/protobuf/compiler/plugin.proto new file mode 100644 index 0000000..10d285f --- /dev/null +++ b/codegen/proto/google/protobuf/compiler/plugin.proto @@ -0,0 +1,180 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +// Author: kenton@google.com (Kenton Varda) +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +syntax = "proto2"; + +package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; + +import "google/protobuf/descriptor.proto"; + +option csharp_namespace = "Google.Protobuf.Compiler"; +option go_package = "google.golang.org/protobuf/types/pluginpb"; + +// The version number of protocol compiler. +message Version { + optional int32 major = 1; + optional int32 minor = 2; + optional int32 patch = 3; + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + optional string suffix = 4; +} + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +message CodeGeneratorRequest { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + repeated string file_to_generate = 1; + + // The generator parameter passed on the command-line. + optional string parameter = 2; + + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // Note: the files listed in files_to_generate will include runtime-retention + // options only, but all other files will include source-retention options. + // The source_file_descriptors field below is available in case you need + // source-retention options for files_to_generate. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. + repeated FileDescriptorProto proto_file = 15; + + // File descriptors with all options, including source-retention options. + // These descriptors are only provided for the files listed in + // files_to_generate. + repeated FileDescriptorProto source_file_descriptors = 17; + + // The version number of protocol compiler. + optional Version compiler_version = 3; +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +message CodeGeneratorResponse { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + optional string error = 1; + + // A bitmask of supported features that the code generator supports. + // This is a bitwise "or" of values from the Feature enum. + optional uint64 supported_features = 2; + + // Sync with code_generator.h. + enum Feature { + FEATURE_NONE = 0; + FEATURE_PROTO3_OPTIONAL = 1; + FEATURE_SUPPORTS_EDITIONS = 2; + } + + // The minimum edition this plugin supports. This will be treated as an + // Edition enum, but we want to allow unknown values. It should be specified + // according the edition enum value, *not* the edition number. Only takes + // effect for plugins that have FEATURE_SUPPORTS_EDITIONS set. + optional int32 minimum_edition = 3; + + // The maximum edition this plugin supports. This will be treated as an + // Edition enum, but we want to allow unknown values. It should be specified + // according the edition enum value, *not* the edition number. Only takes + // effect for plugins that have FEATURE_SUPPORTS_EDITIONS set. + optional int32 maximum_edition = 4; + + // Represents a single generated file. + message File { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + optional string name = 1; + + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + optional string insertion_point = 2; + + // The file contents. + optional string content = 15; + + // Information describing the file content being inserted. If an insertion + // point is used, this information will be appropriately offset and inserted + // into the code generation metadata for the generated files. + optional GeneratedCodeInfo generated_code_info = 16; + } + repeated File file = 15; +} diff --git a/codegen/proto/google/protobuf/descriptor.proto b/codegen/proto/google/protobuf/descriptor.proto new file mode 100644 index 0000000..89c4891 --- /dev/null +++ b/codegen/proto/google/protobuf/descriptor.proto @@ -0,0 +1,1507 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +syntax = "proto2"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension" + }]; +} + +// The full set of known editions. +enum Edition { + // A placeholder for an unknown edition value. + EDITION_UNKNOWN = 0; + + // A placeholder edition for specifying default behaviors *before* a feature + // was first introduced. This is effectively an "infinite past". + EDITION_LEGACY = 900; + + // Legacy syntax "editions". These pre-date editions, but behave much like + // distinct editions. These can't be used to specify the edition of proto + // files, but feature definitions must supply proto2/proto3 defaults for + // backwards compatibility. + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + + // Editions that have been released. The specific values are arbitrary and + // should not be depended on, but they will always be time-ordered for easy + // comparison. + EDITION_2023 = 1000; + EDITION_2024 = 1001; + EDITION_2026 = 1002; + + // A placeholder edition for developing and testing unscheduled features. + EDITION_UNSTABLE = 9999; + + // Placeholder editions for testing feature resolution. These should not be + // used or relied on outside of tests. + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; + + // Placeholder for specifying unbounded edition support. This should only + // ever be used by plugins that can expect to never require any changes to + // support a new edition. + EDITION_MAX = 0x7FFFFFFF; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // Names of files imported by this file purely for the purpose of providing + // option extensions. These are excluded from the dependency list above. + repeated string option_dependency = 15; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2", "proto3", and "editions". + // + // If `edition` is present, this value must be "editions". + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional string syntax = 12; + + // The edition of the proto file. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional Edition edition = 14; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 11; +} + +message ExtensionRangeOptions { + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + message Declaration { + // The extension number declared within the extension range. + optional int32 number = 1; + + // The fully-qualified name of the extension field. There must be a leading + // dot in front of the full name. + optional string full_name = 2; + + // The fully-qualified type name of the extension field. Unlike + // Metadata.type, Declaration.type must have a leading dot for messages + // and enums. + optional string type = 3; + + // If true, indicates that the number is reserved in the extension range, + // and any extension field with the number will fail to compile. Set this + // when a declared extension field is deleted. + optional bool reserved = 5; + + // If true, indicates that the extension must be defined as repeated. + // Otherwise the extension must be defined as optional. + optional bool repeated = 6; + + reserved 4; // removed is_repeated + } + + // For external users: DO NOT USE. We are in the process of open sourcing + // extension declaration and executing internal cleanups before it can be + // used externally. + repeated Declaration declaration = 2 [retention = RETENTION_SOURCE]; + + // Any features defined in the specific edition. + optional FeatureSet features = 50; + + // The verification state of the extension range. + enum VerificationState { + // All the extensions of the range must be declared. + DECLARATION = 0; + UNVERIFIED = 1; + } + + // The verification state of the range. + // TODO: flip the default to DECLARATION once all empty ranges + // are marked as UNVERIFIED. + optional VerificationState verification = 3 + [default = UNVERIFIED, retention = RETENTION_SOURCE]; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported after google.protobuf. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. In Editions, the group wire format + // can be enabled via the `message_encoding` feature. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REPEATED = 3; + // The required label is only allowed in google.protobuf. In proto3 and Editions + // it's explicitly prohibited. In Editions, the `field_presence` feature + // can be used to get this behavior. + LABEL_REQUIRED = 2; + } + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must belong to a oneof to signal + // to old proto3 clients that presence is tracked for this field. This oneof + // is known as a "synthetic" oneof, and this field must be its sole member + // (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs + // exist in the descriptor only, and do not generate any API. Synthetic oneofs + // must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 6; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; + + reserved 4; + reserved "stream"; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default = false]; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. + optional string java_outer_classname = 8; + + // If enabled, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [ + default = false, + feature_support = { + edition_introduced: EDITION_PROTO2 + edition_removed: EDITION_2024 + removal_error: "This behavior is enabled by default in editions 2024 and above. " + "To disable it, you can set `features.(pb.java).nest_in_file_class = YES` " + "on individual messages, enums, or services." + + } + ]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // A proto2 file can set this to true to opt in to UTF-8 checking for Java, + // which will throw an exception if invalid UTF-8 is parsed from the wire or + // assigned to a string field. + // + // TODO: clarify exactly what kinds of field types this option + // applies to, and update these docs accordingly. + // + // Proto3 files already perform these checks. Setting the option explicitly to + // false has no effect: it cannot be used to opt proto3 files out of UTF-8 + // checks. + optional bool java_string_check_utf8 = 27 [default = false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default = SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + reserved 42; // removed php_generic_services + reserved "php_generic_services"; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default = false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default = true]; + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 50; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998 [declaration = { + number: 990, + full_name: ".pb.file.cpp", + type: ".pb.file.CppFileOptions" + }]; + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + + reserved 4, 5, 6; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 12; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is only implemented to support use of + // [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + // type "bytes" in the open source release. + // TODO: make ctype actually deprecated. + optional CType ctype = 1 [/*deprecated = true,*/ default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + // The option [ctype=CORD] may be applied to a non-repeated field of type + // "bytes". It indicates that in C++, the data should be stored in a Cord + // instead of a string. For very large strings, this may reduce memory + // fragmentation. It may also allow better performance when parsing from a + // Cord, or when parsing with aliasing enabled, as the parsed Cord may then + // alias the original buffer. + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. This option is prohibited in + // Editions, but the `repeated_field_encoding` feature can be used to control + // the behavior. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // Note that lazy message fields are still eagerly verified to check + // ill-formed wireformat or missing required fields. Calling IsInitialized() + // on the outer message would fail if the inner message has missing required + // fields. Failed verification would result in parsing failure (except when + // uninitialized messages are acceptable). + optional bool lazy = 5 [default = false]; + + // unverified_lazy does no correctness checks on the byte stream. This should + // only be used where lazy with verification is prohibitive for performance + // reasons. + optional bool unverified_lazy = 15 [default = false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default = false]; + + // DEPRECATED. DO NOT USE! + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default = false, deprecated = true]; + + // Indicate that the field value should not be printed out when using debug + // formats, e.g. when the field contains sensitive credentials. + optional bool debug_redact = 16 [default = false]; + + // If set to RETENTION_SOURCE, the option will be omitted from the binary. + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + + optional OptionRetention retention = 17; + + // This indicates the types of entities that the field may apply to when used + // as an option. If it is unset, then the field may be freely used as an + // option on any kind of entity. + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + + repeated OptionTargetType targets = 19; + + message EditionDefault { + optional Edition edition = 3; + optional string value = 2; // Textproto value. + } + repeated EditionDefault edition_defaults = 20; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 21; + + // Information about the support window of a feature. + message FeatureSupport { + // The edition that this feature was first available in. In editions + // earlier than this one, the default assigned to EDITION_LEGACY will be + // used, and proto files will not be able to override it. + optional Edition edition_introduced = 1; + + // The edition this feature becomes deprecated in. Using this after this + // edition may trigger warnings. + optional Edition edition_deprecated = 2; + + // The deprecation warning text if this feature is used after the edition it + // was marked deprecated in. + optional string deprecation_warning = 3; + + // The edition this feature is no longer available in. In editions after + // this one, the last default assigned will be used, and proto files will + // not be able to override it. + optional Edition edition_removed = 4; + + // The removal error text if this feature is used after the edition it was + // removed in. + optional string removal_error = 5; + } + optional FeatureSupport feature_support = 22; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype + reserved 18; // reserve target, target_obsolete_do_not_use +} + +message OneofOptions { + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 1; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // TODO Remove this legacy behavior once downstream teams have + // had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 7; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default = false]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 2; + + // Indicate that fields annotated with this enum value should not be printed + // out when using debug formats, e.g. when the field contains sensitive + // credentials. + optional bool debug_redact = 3 [default = false]; + + // Information about the support window of a feature value. + optional FieldOptions.FeatureSupport feature_support = 4; + + // Range reserved for first-class extension options defined by the Protobuf + // team. Custom options must use the 1000+ range instead. + extensions 990 to 998 [declaration = { + number: 998, + full_name: ".pb.enumvalue.json", + type: ".pb.enumvalue.JsonEnumValueOptions" + }]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 34; + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 35; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Features + +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +message FeatureSet { + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + optional FieldPresence field_presence = 1 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPLICIT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "IMPLICIT" }, + edition_defaults = { edition: EDITION_2023, value: "EXPLICIT" } + ]; + + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + optional EnumType enum_type = 2 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "CLOSED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "OPEN" } + ]; + + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + optional RepeatedFieldEncoding repeated_field_encoding = 3 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPANDED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "PACKED" } + ]; + + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + VERIFY = 2; + NONE = 3; + reserved 1; + } + optional Utf8Validation utf8_validation = 4 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "NONE" }, + edition_defaults = { edition: EDITION_PROTO3, value: "VERIFY" } + ]; + + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + optional MessageEncoding message_encoding = 5 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LENGTH_PREFIXED" } + ]; + + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + optional JsonFormat json_format = 6 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY_BEST_EFFORT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "ALLOW" } + ]; + + enum EnforceNamingStyle { + ENFORCE_NAMING_STYLE_UNKNOWN = 0; + STYLE2024 = 1; + STYLE_LEGACY = 2; + STYLE2026 = 3; + } + optional EnforceNamingStyle enforce_naming_style = 7 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_EXTENSION_RANGE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_SERVICE, + targets = TARGET_TYPE_METHOD, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "STYLE_LEGACY" }, + edition_defaults = { edition: EDITION_2024, value: "STYLE2024" }, + edition_defaults = { edition: EDITION_2026, value: "STYLE2026" } + ]; + + message VisibilityFeature { + enum DefaultSymbolVisibility { + DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0; + + // Default pre-EDITION_2024, all UNSET visibility are export. + EXPORT_ALL = 1; + + // All top-level symbols default to export, nested default to local. + EXPORT_TOP_LEVEL = 2; + + // All symbols default to local. + LOCAL_ALL = 3; + + // All symbols local by default. Nested types cannot be exported. + // With special case caveat for message { enum {} reserved 1 to max; } + // This is the recommended setting for new protos. + STRICT = 4; + } + reserved 1 to max; + } + optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = + 8 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPORT_ALL" }, + edition_defaults = { edition: EDITION_2024, value: "EXPORT_TOP_LEVEL" } + ]; + + message ProtoLimitsFeature { + enum EnforceProtoLimits { + PROTO_LIMITS_UNKNOWN = 0; + + // Default pre-EDITION_2026: there are no limit enforcement at the protoc + // level. Practical limits still exist, but they will tend to fail while + // compiling protoc-generated code, and these limits tend to be language + // or toolchain specific. + LEGACY_NO_EXPLICIT_LIMITS = 1; + + // A set of limits enforced by Edition 2026 by default. For a detailed + // list of all the limits please consult the Edition 2026 documentation. + PROTO_LIMITS2026 = 2; + } + } + optional ProtoLimitsFeature.EnforceProtoLimits enforce_proto_limits = 9 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + feature_support = { + edition_introduced: EDITION_2026, + }, + edition_defaults = { + edition: EDITION_LEGACY, + value: "LEGACY_NO_EXPLICIT_LIMITS" + }, + edition_defaults = { edition: EDITION_2026, value: "PROTO_LIMITS2026" } + ]; + + reserved 999; + + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { number: 1002, full_name: ".pb.go", type: ".pb.GoFeatures" }, + declaration = { + number: 1003, + full_name: ".pb.python", + type: ".pb.PythonFeatures" + }, + declaration = { + number: 1004, + full_name: ".pb.csharp", + type: ".pb.CSharpFeatures" + }, + declaration = { + number: 1100, + full_name: ".imp.impress_feature_set", + type: ".imp.ImpressFeatureSet" + }, + declaration = { + number: 9989, + full_name: ".pb.java_mutable", + type: ".pb.JavaMutableFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + + extensions 9995 to 9999; // For internal testing + extensions 10000; // for https://github.com/bufbuild/protobuf-es +} + +// A compiled specification for the defaults of a set of features. These +// messages are generated from FeatureSet extensions and can be used to seed +// feature resolution. The resolution with this object becomes a simple search +// for the closest matching edition, followed by proto merges. +message FeatureSetDefaults { + // A map from every known edition with a unique set of defaults to its + // defaults. Not all editions may be contained here. For a given edition, + // the defaults at the closest matching edition ordered at or before it should + // be used. This field must be in strict ascending order by edition. + message FeatureSetEditionDefault { + optional Edition edition = 3; + + // Defaults of features that can be overridden in this edition. + optional FeatureSet overridable_features = 4; + + // Defaults of features that can't be overridden in this edition. + optional FeatureSet fixed_features = 5; + + reserved 1, 2; + reserved "features"; + } + repeated FeatureSetEditionDefault defaults = 1; + + // The minimum supported edition (inclusive) when this was constructed. + // Editions before this will not have defaults. + optional Edition minimum_edition = 4; + + // The maximum known edition (inclusive) when this was constructed. Editions + // after this will not have reliable defaults. + optional Edition maximum_edition = 5; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendant. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition appears. + // For example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed = true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed = true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to moo. + // // + // // Another line attached to moo. + // optional double moo = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to moo or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + full_name: ".buf.descriptor.v1.buf_source_code_info_extension" + }]; +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified object. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + + // Represents the identified object's effect on the element in the original + // .proto file. + enum Semantic { + // There is no effect or the effect is indescribable. + NONE = 0; + // The element is set or otherwise mutated. + SET = 1; + // An alias to the element is returned. + ALIAS = 2; + } + optional Semantic semantic = 5; + } +} + +// Describes the 'visibility' of a symbol with respect to the proto import +// system. Symbols can only be imported when the visibility rules do not prevent +// it (ex: local symbols cannot be imported). Visibility modifiers can only set +// on `message` and `enum` as they are the only types available to be referenced +// from other files. +enum SymbolVisibility { + VISIBILITY_UNSET = 0; + VISIBILITY_LOCAL = 1; + VISIBILITY_EXPORT = 2; +} diff --git a/codegen/proto/hackers.proto b/codegen/proto/hackers.proto new file mode 100644 index 0000000..f456b9c --- /dev/null +++ b/codegen/proto/hackers.proto @@ -0,0 +1,56 @@ +syntax = "proto3"; + +message Tool { + string name = 1; + string version = 2; + bytes payload = 3; + bool is_active = 4; + int32 exploit_count = 5; +} + +message Connection { + string host = 1; + int32 port = 2; + bool encrypted = 3; + int64 bandwidth_bps = 4; + bytes session_key = 5; +} + +message Hacker { + string handle = 1; + string real_name = 2; + int32 age = 3; + float skill_level = 4; // Fixed32 + bool is_elite = 5; + int64 crew_id = 6; + repeated string exploits = 7; + repeated Tool tools = 8; + Connection active_connection = 9; +} + +message Worm { + string name = 1; + int32 variant = 2; + int64 size_bytes = 3; + bytes payload = 4; + bool polymorphic = 5; + repeated string targets = 6; +} + +message Operation { + string codename = 1; + string target_corp = 2; + int64 timestamp = 3; + bool successful = 4; + bytes stolen_data = 5; + repeated Hacker crew = 6; + Worm worm = 7; + repeated string log_entries = 8; + int32 severity = 9; +} + +message Campaign { + string name = 1; + repeated Operation operations = 2; + int64 total_bytes_stolen = 3; +} diff --git a/src/bin/generator.rs b/codegen/src/bin/generator.rs similarity index 79% rename from src/bin/generator.rs rename to codegen/src/bin/generator.rs index 97f2607..fe0f0de 100644 --- a/src/bin/generator.rs +++ b/codegen/src/bin/generator.rs @@ -1,13 +1,15 @@ use clap::Parser; -use roto::google::protobuf::descriptor::{ - FileDescriptorSet -}; -use roto::generator::generate_rust_code; +use roto_codegen::generator::generate_rust_code; +use roto_codegen::google::protobuf::descriptor::FileDescriptorSet; use std::fs; use std::path::PathBuf; #[derive(Parser)] -#[command(author, version, about = "Generates Rust accessor and builder code from a protobuf descriptor set")] +#[command( + author, + version, + about = "Generates Rust accessor and builder code from a protobuf descriptor set" +)] struct Args { /// Path to the descriptor set file (.desc) #[arg(short, long)] diff --git a/src/bin/protoc-gen-roto.rs b/codegen/src/bin/protoc-gen-roto.rs similarity index 78% rename from src/bin/protoc-gen-roto.rs rename to codegen/src/bin/protoc-gen-roto.rs index d5608ad..444aedf 100644 --- a/src/bin/protoc-gen-roto.rs +++ b/codegen/src/bin/protoc-gen-roto.rs @@ -1,13 +1,11 @@ use env_logger::init; use log::{error, info}; -use roto::generator::generate_rust_code; -use roto::google::protobuf::descriptor::{ - FileDescriptorSet -}; -use roto::google::protobuf::compiler::plugin::{ +use roto_codegen::generator::generate_rust_code; +use roto_codegen::google::protobuf::compiler::plugin::{ CodeGeneratorRequest, CodeGeneratorResponseBuilder, code_generator_response::FileBuilder, }; -// use roto::ProtoBuilder; +use roto_codegen::google::protobuf::descriptor::FileDescriptorSet; +// use roto_runtime::ProtoBuilder; use std::io::{self, Read, Write}; fn main() { @@ -43,7 +41,9 @@ fn run() -> std::result::Result<(), Box> { } /// Core logic that transforms a CodeGeneratorRequest into a serialized CodeGeneratorResponse. -fn handle_request(request: &CodeGeneratorRequest) -> std::result::Result, Box> { +fn handle_request( + request: &CodeGeneratorRequest, +) -> std::result::Result, Box> { // 2. Construct a FileDescriptorSet from the request's proto_files let mut set_buf = Vec::new(); for file_res in request.proto_file() { @@ -58,7 +58,7 @@ fn handle_request(request: &CodeGeneratorRequest) -> std::result::Result // Write length as varint let len = file_data.len() as u64; let mut len_buf = [0u8; 10]; - let len_size = roto::write_varint(len, &mut len_buf).map_err(|e| { + let len_size = roto_runtime::write_varint(len, &mut len_buf).map_err(|e| { error!("Failed to write varint length: {:?}", e); e })?; @@ -70,7 +70,8 @@ fn handle_request(request: &CodeGeneratorRequest) -> std::result::Result let set = FileDescriptorSet::new(&set_buf)?; - let files_to_generate: Vec = request.file_to_generate() + let files_to_generate: Vec = request + .file_to_generate() .filter_map(|res| { let (bytes, _) = res.ok()?; std::str::from_utf8(bytes).ok().map(|s| s.to_string()) @@ -98,12 +99,10 @@ fn handle_request(request: &CodeGeneratorRequest) -> std::result::Result resp_builder = resp_builder.file(final_file)?; } - let final_response_slice = resp_builder - .finish() - .map_err(|e| { - error!("Failed to finish CodeGeneratorResponse: {:?}", e); - e - })?; + let final_response_slice = resp_builder.finish().map_err(|e| { + error!("Failed to finish CodeGeneratorResponse: {:?}", e); + e + })?; // The finish() method returns a reference to the buffer. // We convert it to a Vec to return it from this function. @@ -125,12 +124,19 @@ mod tests { } let data = fs::read(request_path).expect("Failed to read request.bin"); - let request = CodeGeneratorRequest::new(&data).expect("Failed to parse CodeGeneratorRequest"); + let request = + CodeGeneratorRequest::new(&data).expect("Failed to parse CodeGeneratorRequest"); let result = handle_request(&request); - assert!(result.is_ok(), "handle_request should succeed with request.bin"); + assert!( + result.is_ok(), + "handle_request should succeed with request.bin" + ); let response = result.unwrap(); - assert!(!response.is_empty(), "The generated response should not be empty"); + assert!( + !response.is_empty(), + "The generated response should not be empty" + ); } } diff --git a/src/generator.rs b/codegen/src/generator.rs similarity index 89% rename from src/generator.rs rename to codegen/src/generator.rs index 9aeab92..72dfae6 100644 --- a/src/generator.rs +++ b/codegen/src/generator.rs @@ -1,8 +1,8 @@ -use crate::ProtoAccessor; use crate::google::protobuf::descriptor::{ DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FileDescriptorProto, FileDescriptorSet, }; +use roto_runtime::ProtoAccessor; use std::collections::{HashMap, HashSet}; use std::str; @@ -37,7 +37,7 @@ fn map_type_to_rust_accessor(field_type: i32, label: i32) -> (String, String) { if label == 3 { // LABEL_REPEATED return ( - "crate::RepeatedFieldIterator<'a>".to_string(), + "roto_runtime::RepeatedFieldIterator<'a>".to_string(), "".to_string(), // Not used for repeated fields in the same way ); } @@ -57,23 +57,23 @@ fn map_type_to_rust_accessor(field_type: i32, label: i32) -> (String, String) { ), // TYPE_FLOAT 3 | 5 | 15 | 17 => ( "i32".to_string(), - "crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation)".to_string(), + "roto_runtime::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), ), // INT/SINT/SFIXED 32 4 | 6 | 13 => ( "u32".to_string(), - "crate::read_varint(bytes).map(|(v, _)| v as u32).map_err(|_| crate::RotoError::WireFormatViolation)".to_string(), + "roto_runtime::read_varint(bytes).map(|(v, _)| v as u32).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), ), // UINT/FIXED 32 16 | 18 => ( "i64".to_string(), - "crate::read_varint(bytes).map(|(v, _)| v as i64).map_err(|_| crate::RotoError::WireFormatViolation)".to_string(), + "roto_runtime::read_varint(bytes).map(|(v, _)| v as i64).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), ), // SINT/SFIXED 64 7 | 14 => ( "u64".to_string(), - "crate::read_varint(bytes).map(|(v, _)| v as u64).map_err(|_| crate::RotoError::WireFormatViolation)".to_string(), + "roto_runtime::read_varint(bytes).map(|(v, _)| v as u64).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), ), // UINT/FIXED 64 8 => ( "bool".to_string(), - "crate::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| crate::RotoError::WireFormatViolation)".to_string(), + "roto_runtime::read_varint(bytes).map(|(v, _)| v != 0).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), ), // TYPE_BOOL 11 | 12 => ("&'a [u8]".to_string(), "Ok(bytes)".to_string()), // MESSAGE/BYTES _ => ("&'a [u8]".to_string(), "Ok(bytes)".to_string()), @@ -97,7 +97,8 @@ fn write_enum(enum_proto: &EnumDescriptorProto, output: &mut String) { let (name_bytes, _) = accessor.get_value(1).expect("Enum value name missing"); let name = str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); let (num_bytes, _) = accessor.get_value(2).expect("Enum value number missing"); - let (num, _) = crate::read_varint(num_bytes).expect("Enum value number invalid varint"); + let (num, _) = + roto_runtime::read_varint(num_bytes).expect("Enum value number invalid varint"); let pascal_name = to_pascal_case(name); if num == 0 { @@ -126,7 +127,8 @@ fn write_enum(enum_proto: &EnumDescriptorProto, output: &mut String) { let (name_bytes, _) = accessor.get_value(1).expect("Enum value name missing"); let name = str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); let (num_bytes, _) = accessor.get_value(2).expect("Enum value number missing"); - let (num, _) = crate::read_varint(num_bytes).expect("Enum value number invalid varint"); + let (num, _) = + roto_runtime::read_varint(num_bytes).expect("Enum value number invalid varint"); output.push_str(&format!( " {} => {}::{},\n", @@ -162,7 +164,7 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { } output.push_str(&format!("pub struct {}<'a> {{\n", msg_name)); - output.push_str(" accessor: crate::ProtoAccessor<'a>,\n"); + output.push_str(" accessor: roto_runtime::ProtoAccessor<'a>,\n"); for (field_name, _tag, _f_type, f_label) in &fields_info { if *f_label == 3 { @@ -175,8 +177,8 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { output.push_str("}\n\n"); output.push_str(&format!("impl<'a> {}<'a> {{\n", msg_name)); - output.push_str(" pub fn new(data: &'a [u8]) -> crate::Result {\n"); - output.push_str(" let accessor = crate::ProtoAccessor::new(data)?;\n"); + output.push_str(" pub fn new(data: &'a [u8]) -> roto_runtime::Result {\n"); + output.push_str(" let accessor = roto_runtime::ProtoAccessor::new(data)?;\n"); if !fields_info.is_empty() { for (name, _, _, label) in &fields_info { if *label == 3 { @@ -245,11 +247,11 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { output.push_str(" }\n }\n\n"); } else { output.push_str(&format!( - " pub fn {}(&self) -> crate::Result<{}> {{\n", + " pub fn {}(&self) -> roto_runtime::Result<{}> {{\n", safe_name, rust_type )); output.push_str(&format!( - " let offset = self.{}_offset.ok_or(crate::RotoError::FieldNotFound)?;\n", + " let offset = self.{}_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?;\n", field_name )); output.push_str(" let (bytes, _) = self.accessor.get_value_at(offset)?;\n"); @@ -284,7 +286,7 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { // Builder struct — one `_written: bool` flag per field output.push_str(&format!("pub struct {}Builder<'b> {{\n", msg_name)); - output.push_str(" builder: crate::ProtoBuilder<'b>,\n"); + output.push_str(" builder: roto_runtime::ProtoBuilder<'b>,\n"); for (field_name, _, _, _, _) in &builder_fields { output.push_str(&format!(" {}_written: bool,\n", field_name)); } @@ -295,7 +297,7 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { " pub fn builder(buf: &mut [u8]) -> {}Builder<'_> {{\n {}Builder {{\n", msg_name, msg_name )); - output.push_str(" builder: crate::ProtoBuilder::new(buf),\n"); + output.push_str(" builder: roto_runtime::ProtoBuilder::new(buf),\n"); for (field_name, _, _, _, _) in &builder_fields { output.push_str(&format!(" {}_written: false,\n", field_name)); } @@ -304,14 +306,14 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { // Per-field setters — mark field as written for (field_name, safe_name, tag, rust_type, method) in &builder_fields { output.push_str(&format!( - " pub fn {}(mut self, value: {}) -> crate::Result {{\n self.builder.{}({}, value)?;\n self.{}_written = true;\n Ok(self)\n }}\n\n", + " pub fn {}(mut self, value: {}) -> roto_runtime::Result {{\n self.builder.{}({}, value)?;\n self.{}_written = true;\n Ok(self)\n }}\n\n", safe_name, rust_type, method, tag, field_name )); } // with() — copies unseen fields from an existing message output.push_str(&format!( - " pub fn with(mut self, msg: &{}<'_>) -> crate::Result {{\n", + " pub fn with(mut self, msg: &{}<'_>) -> roto_runtime::Result {{\n", msg_name )); output.push_str(" for item in msg.raw_fields() {\n"); @@ -332,7 +334,7 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { output.push_str(" Ok(self)\n"); output.push_str(" }\n\n"); - output.push_str(&format!(" pub fn finish(self) -> crate::Result<&'b mut [u8]> {{\n self.builder.finish()\n }}\n}}\n\n")); + output.push_str(&format!(" pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {{\n self.builder.finish()\n }}\n}}\n\n")); let mut nested_enums = Vec::new(); for e_res in msg_proto.enum_type() { @@ -403,7 +405,7 @@ pub fn generate_rust_code( let mut output = String::new(); output.push_str("// @generated by protoc-gen-roto — do not edit\n"); output.push_str("#![allow(unused_imports)]\n\n"); - output.push_str("use crate::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};\n"); + output.push_str("use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};\n"); output.push_str("use std::str;\n\n"); for dep_res in file_proto.dependency() { diff --git a/codegen/src/google/mod.rs b/codegen/src/google/mod.rs new file mode 100644 index 0000000..91e4166 --- /dev/null +++ b/codegen/src/google/mod.rs @@ -0,0 +1 @@ +pub mod protobuf; diff --git a/codegen/src/google/protobuf/compiler/mod.rs b/codegen/src/google/protobuf/compiler/mod.rs new file mode 100644 index 0000000..962cb1b --- /dev/null +++ b/codegen/src/google/protobuf/compiler/mod.rs @@ -0,0 +1 @@ +pub mod plugin; diff --git a/codegen/src/google/protobuf/compiler/plugin.rs b/codegen/src/google/protobuf/compiler/plugin.rs new file mode 100644 index 0000000..c6421ec --- /dev/null +++ b/codegen/src/google/protobuf/compiler/plugin.rs @@ -0,0 +1,679 @@ +// @generated by protoc-gen-roto — do not edit +#![allow(unused_imports)] + +use roto_runtime::{ + ProtoAccessor, ProtoBuilder, RepeatedFieldIterator, Result, RotoError, read_varint, +}; +use std::str; + +use crate::google::protobuf::descriptor; + +pub struct Version<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + major_offset: Option, + minor_offset: Option, + patch_offset: Option, + suffix_offset: Option, +} + +impl<'a> Version<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut major_offset = None; + let mut minor_offset = None; + let mut patch_offset = None; + let mut suffix_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + major_offset = Some(offset); + } + if tag.field_number == 2 { + minor_offset = Some(offset); + } + if tag.field_number == 3 { + patch_offset = Some(offset); + } + if tag.field_number == 4 { + suffix_offset = Some(offset); + } + } + + Ok(Self { + accessor, + major_offset, + minor_offset, + patch_offset, + suffix_offset, + }) + } + + pub fn major(&self) -> roto_runtime::Result { + let offset = self + .major_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn minor(&self) -> roto_runtime::Result { + let offset = self + .minor_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn patch(&self) -> roto_runtime::Result { + let offset = self + .patch_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn suffix(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .suffix_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct VersionBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + major_written: bool, + minor_written: bool, + patch_written: bool, + suffix_written: bool, +} + +impl<'b> VersionBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> VersionBuilder<'_> { + VersionBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + major_written: false, + minor_written: false, + patch_written: false, + suffix_written: false, + } + } + + pub fn major(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.major_written = true; + Ok(self) + } + + pub fn minor(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.minor_written = true; + Ok(self) + } + + pub fn patch(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(3, value)?; + self.patch_written = true; + Ok(self) + } + + pub fn suffix(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(4, value)?; + self.suffix_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &Version<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.major_written, + 2 => self.minor_written, + 3 => self.patch_written, + 4 => self.suffix_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct CodeGeneratorRequest<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + file_to_generate_start: Option, + file_to_generate_end: Option, + parameter_offset: Option, + proto_file_start: Option, + proto_file_end: Option, + source_file_descriptors_start: Option, + source_file_descriptors_end: Option, + compiler_version_offset: Option, +} + +impl<'a> CodeGeneratorRequest<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut file_to_generate_start = None; + let mut file_to_generate_end = None; + let mut parameter_offset = None; + let mut proto_file_start = None; + let mut proto_file_end = None; + let mut source_file_descriptors_start = None; + let mut source_file_descriptors_end = None; + let mut compiler_version_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if file_to_generate_start.is_none() { + file_to_generate_start = Some(offset); + } + file_to_generate_end = Some(offset); + } + if tag.field_number == 2 { + parameter_offset = Some(offset); + } + if tag.field_number == 15 { + if proto_file_start.is_none() { + proto_file_start = Some(offset); + } + proto_file_end = Some(offset); + } + if tag.field_number == 17 { + if source_file_descriptors_start.is_none() { + source_file_descriptors_start = Some(offset); + } + source_file_descriptors_end = Some(offset); + } + if tag.field_number == 3 { + compiler_version_offset = Some(offset); + } + } + + Ok(Self { + accessor, + file_to_generate_start, + file_to_generate_end, + parameter_offset, + proto_file_start, + proto_file_end, + source_file_descriptors_start, + source_file_descriptors_end, + compiler_version_offset, + }) + } + + pub fn file_to_generate(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.file_to_generate_start, self.file_to_generate_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn parameter(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .parameter_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn proto_file(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.proto_file_start, self.proto_file_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(15, start, end), + _ => self.accessor.iter_repeated(15), + } + } + + pub fn source_file_descriptors(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.source_file_descriptors_start, + self.source_file_descriptors_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(17, start, end), + _ => self.accessor.iter_repeated(17), + } + } + + pub fn compiler_version(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .compiler_version_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct CodeGeneratorRequestBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + file_to_generate_written: bool, + parameter_written: bool, + proto_file_written: bool, + source_file_descriptors_written: bool, + compiler_version_written: bool, +} + +impl<'b> CodeGeneratorRequestBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> CodeGeneratorRequestBuilder<'_> { + CodeGeneratorRequestBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + file_to_generate_written: false, + parameter_written: false, + proto_file_written: false, + source_file_descriptors_written: false, + compiler_version_written: false, + } + } + + pub fn file_to_generate(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.file_to_generate_written = true; + Ok(self) + } + + pub fn parameter(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.parameter_written = true; + Ok(self) + } + + pub fn proto_file(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(15, value)?; + self.proto_file_written = true; + Ok(self) + } + + pub fn source_file_descriptors(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(17, value)?; + self.source_file_descriptors_written = true; + Ok(self) + } + + pub fn compiler_version(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.compiler_version_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &CodeGeneratorRequest<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.file_to_generate_written, + 2 => self.parameter_written, + 15 => self.proto_file_written, + 17 => self.source_file_descriptors_written, + 3 => self.compiler_version_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct CodeGeneratorResponse<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + error_offset: Option, + supported_features_offset: Option, + minimum_edition_offset: Option, + maximum_edition_offset: Option, + file_start: Option, + file_end: Option, +} + +impl<'a> CodeGeneratorResponse<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut error_offset = None; + let mut supported_features_offset = None; + let mut minimum_edition_offset = None; + let mut maximum_edition_offset = None; + let mut file_start = None; + let mut file_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + error_offset = Some(offset); + } + if tag.field_number == 2 { + supported_features_offset = Some(offset); + } + if tag.field_number == 3 { + minimum_edition_offset = Some(offset); + } + if tag.field_number == 4 { + maximum_edition_offset = Some(offset); + } + if tag.field_number == 15 { + if file_start.is_none() { + file_start = Some(offset); + } + file_end = Some(offset); + } + } + + Ok(Self { + accessor, + error_offset, + supported_features_offset, + minimum_edition_offset, + maximum_edition_offset, + file_start, + file_end, + }) + } + + pub fn error(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .error_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn supported_features(&self) -> roto_runtime::Result { + let offset = self + .supported_features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn minimum_edition(&self) -> roto_runtime::Result { + let offset = self + .minimum_edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn maximum_edition(&self) -> roto_runtime::Result { + let offset = self + .maximum_edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn file(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.file_start, self.file_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(15, start, end), + _ => self.accessor.iter_repeated(15), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct CodeGeneratorResponseBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + error_written: bool, + supported_features_written: bool, + minimum_edition_written: bool, + maximum_edition_written: bool, + file_written: bool, +} + +impl<'b> CodeGeneratorResponseBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> CodeGeneratorResponseBuilder<'_> { + CodeGeneratorResponseBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + error_written: false, + supported_features_written: false, + minimum_edition_written: false, + maximum_edition_written: false, + file_written: false, + } + } + + pub fn error(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.error_written = true; + Ok(self) + } + + pub fn supported_features(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.supported_features_written = true; + Ok(self) + } + + pub fn minimum_edition(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(3, value)?; + self.minimum_edition_written = true; + Ok(self) + } + + pub fn maximum_edition(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(4, value)?; + self.maximum_edition_written = true; + Ok(self) + } + + pub fn file(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(15, value)?; + self.file_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &CodeGeneratorResponse<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.error_written, + 2 => self.supported_features_written, + 3 => self.minimum_edition_written, + 4 => self.maximum_edition_written, + 15 => self.file_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod code_generator_response { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum Feature { + FEATURENONE = 0, + FEATUREPROTO3OPTIONAL = 1, + FEATURESUPPORTSEDITIONS = 2, + } + + impl Feature { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => Feature::FEATURENONE, + 1 => Feature::FEATUREPROTO3OPTIONAL, + 2 => Feature::FEATURESUPPORTSEDITIONS, + _ => Feature::FEATURENONE, + } + } + } + + pub struct File<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + insertion_point_offset: Option, + content_offset: Option, + generated_code_info_offset: Option, + } + + impl<'a> File<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut insertion_point_offset = None; + let mut content_offset = None; + let mut generated_code_info_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + insertion_point_offset = Some(offset); + } + if tag.field_number == 15 { + content_offset = Some(offset); + } + if tag.field_number == 16 { + generated_code_info_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + insertion_point_offset, + content_offset, + generated_code_info_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn insertion_point(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .insertion_point_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn content(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .content_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn generated_code_info(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .generated_code_info_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct FileBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + insertion_point_written: bool, + content_written: bool, + generated_code_info_written: bool, + } + + impl<'b> FileBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FileBuilder<'_> { + FileBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + insertion_point_written: false, + content_written: false, + generated_code_info_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn insertion_point(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.insertion_point_written = true; + Ok(self) + } + + pub fn content(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(15, value)?; + self.content_written = true; + Ok(self) + } + + pub fn generated_code_info(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(16, value)?; + self.generated_code_info_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &File<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.insertion_point_written, + 15 => self.content_written, + 16 => self.generated_code_info_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} diff --git a/codegen/src/google/protobuf/descriptor.rs b/codegen/src/google/protobuf/descriptor.rs new file mode 100644 index 0000000..24ff708 --- /dev/null +++ b/codegen/src/google/protobuf/descriptor.rs @@ -0,0 +1,6711 @@ +// @generated by protoc-gen-roto — do not edit +#![allow(unused_imports)] + +use roto_runtime::{ + ProtoAccessor, ProtoBuilder, RepeatedFieldIterator, Result, RotoError, read_varint, +}; +use std::str; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(i32)] +pub enum Edition { + EDITIONUNKNOWN = 0, + EDITIONLEGACY = 900, + EDITIONPROTO2 = 998, + EDITIONPROTO3 = 999, + EDITION2023 = 1000, + EDITION2024 = 1001, + EDITION2026 = 1002, + EDITIONUNSTABLE = 9999, + EDITION1TESTONLY = 1, + EDITION2TESTONLY = 2, + EDITION99997TESTONLY = 99997, + EDITION99998TESTONLY = 99998, + EDITION99999TESTONLY = 99999, + EDITIONMAX = 2147483647, +} + +impl Edition { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => Edition::EDITIONUNKNOWN, + 900 => Edition::EDITIONLEGACY, + 998 => Edition::EDITIONPROTO2, + 999 => Edition::EDITIONPROTO3, + 1000 => Edition::EDITION2023, + 1001 => Edition::EDITION2024, + 1002 => Edition::EDITION2026, + 9999 => Edition::EDITIONUNSTABLE, + 1 => Edition::EDITION1TESTONLY, + 2 => Edition::EDITION2TESTONLY, + 99997 => Edition::EDITION99997TESTONLY, + 99998 => Edition::EDITION99998TESTONLY, + 99999 => Edition::EDITION99999TESTONLY, + 2147483647 => Edition::EDITIONMAX, + _ => Edition::EDITIONUNKNOWN, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(i32)] +pub enum SymbolVisibility { + VISIBILITYUNSET = 0, + VISIBILITYLOCAL = 1, + VISIBILITYEXPORT = 2, +} + +impl SymbolVisibility { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => SymbolVisibility::VISIBILITYUNSET, + 1 => SymbolVisibility::VISIBILITYLOCAL, + 2 => SymbolVisibility::VISIBILITYEXPORT, + _ => SymbolVisibility::VISIBILITYUNSET, + } + } +} + +pub struct FileDescriptorSet<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + file_start: Option, + file_end: Option, +} + +impl<'a> FileDescriptorSet<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut file_start = None; + let mut file_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if file_start.is_none() { + file_start = Some(offset); + } + file_end = Some(offset); + } + } + + Ok(Self { + accessor, + file_start, + file_end, + }) + } + + pub fn file(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.file_start, self.file_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FileDescriptorSetBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + file_written: bool, +} + +impl<'b> FileDescriptorSetBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FileDescriptorSetBuilder<'_> { + FileDescriptorSetBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + file_written: false, + } + } + + pub fn file(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(1, value)?; + self.file_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FileDescriptorSet<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.file_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct FileDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + package_offset: Option, + dependency_start: Option, + dependency_end: Option, + public_dependency_start: Option, + public_dependency_end: Option, + weak_dependency_start: Option, + weak_dependency_end: Option, + option_dependency_start: Option, + option_dependency_end: Option, + message_type_start: Option, + message_type_end: Option, + enum_type_start: Option, + enum_type_end: Option, + service_start: Option, + service_end: Option, + extension_start: Option, + extension_end: Option, + options_offset: Option, + source_code_info_offset: Option, + syntax_offset: Option, + edition_offset: Option, +} + +impl<'a> FileDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut package_offset = None; + let mut dependency_start = None; + let mut dependency_end = None; + let mut public_dependency_start = None; + let mut public_dependency_end = None; + let mut weak_dependency_start = None; + let mut weak_dependency_end = None; + let mut option_dependency_start = None; + let mut option_dependency_end = None; + let mut message_type_start = None; + let mut message_type_end = None; + let mut enum_type_start = None; + let mut enum_type_end = None; + let mut service_start = None; + let mut service_end = None; + let mut extension_start = None; + let mut extension_end = None; + let mut options_offset = None; + let mut source_code_info_offset = None; + let mut syntax_offset = None; + let mut edition_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + package_offset = Some(offset); + } + if tag.field_number == 3 { + if dependency_start.is_none() { + dependency_start = Some(offset); + } + dependency_end = Some(offset); + } + if tag.field_number == 10 { + if public_dependency_start.is_none() { + public_dependency_start = Some(offset); + } + public_dependency_end = Some(offset); + } + if tag.field_number == 11 { + if weak_dependency_start.is_none() { + weak_dependency_start = Some(offset); + } + weak_dependency_end = Some(offset); + } + if tag.field_number == 15 { + if option_dependency_start.is_none() { + option_dependency_start = Some(offset); + } + option_dependency_end = Some(offset); + } + if tag.field_number == 4 { + if message_type_start.is_none() { + message_type_start = Some(offset); + } + message_type_end = Some(offset); + } + if tag.field_number == 5 { + if enum_type_start.is_none() { + enum_type_start = Some(offset); + } + enum_type_end = Some(offset); + } + if tag.field_number == 6 { + if service_start.is_none() { + service_start = Some(offset); + } + service_end = Some(offset); + } + if tag.field_number == 7 { + if extension_start.is_none() { + extension_start = Some(offset); + } + extension_end = Some(offset); + } + if tag.field_number == 8 { + options_offset = Some(offset); + } + if tag.field_number == 9 { + source_code_info_offset = Some(offset); + } + if tag.field_number == 12 { + syntax_offset = Some(offset); + } + if tag.field_number == 14 { + edition_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + package_offset, + dependency_start, + dependency_end, + public_dependency_start, + public_dependency_end, + weak_dependency_start, + weak_dependency_end, + option_dependency_start, + option_dependency_end, + message_type_start, + message_type_end, + enum_type_start, + enum_type_end, + service_start, + service_end, + extension_start, + extension_end, + options_offset, + source_code_info_offset, + syntax_offset, + edition_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn package(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .package_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn dependency(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.dependency_start, self.dependency_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(3, start, end), + _ => self.accessor.iter_repeated(3), + } + } + + pub fn public_dependency(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.public_dependency_start, self.public_dependency_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(10, start, end), + _ => self.accessor.iter_repeated(10), + } + } + + pub fn weak_dependency(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.weak_dependency_start, self.weak_dependency_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(11, start, end), + _ => self.accessor.iter_repeated(11), + } + } + + pub fn option_dependency(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.option_dependency_start, self.option_dependency_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(15, start, end), + _ => self.accessor.iter_repeated(15), + } + } + + pub fn message_type(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.message_type_start, self.message_type_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(4, start, end), + _ => self.accessor.iter_repeated(4), + } + } + + pub fn enum_type(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.enum_type_start, self.enum_type_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(5, start, end), + _ => self.accessor.iter_repeated(5), + } + } + + pub fn service(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.service_start, self.service_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(6, start, end), + _ => self.accessor.iter_repeated(6), + } + } + + pub fn extension(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.extension_start, self.extension_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(7, start, end), + _ => self.accessor.iter_repeated(7), + } + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn source_code_info(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .source_code_info_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn syntax(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .syntax_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn edition(&self) -> roto_runtime::Result { + let offset = self + .edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FileDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + package_written: bool, + dependency_written: bool, + public_dependency_written: bool, + weak_dependency_written: bool, + option_dependency_written: bool, + message_type_written: bool, + enum_type_written: bool, + service_written: bool, + extension_written: bool, + options_written: bool, + source_code_info_written: bool, + syntax_written: bool, + edition_written: bool, +} + +impl<'b> FileDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FileDescriptorProtoBuilder<'_> { + FileDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + package_written: false, + dependency_written: false, + public_dependency_written: false, + weak_dependency_written: false, + option_dependency_written: false, + message_type_written: false, + enum_type_written: false, + service_written: false, + extension_written: false, + options_written: false, + source_code_info_written: false, + syntax_written: false, + edition_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn package(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.package_written = true; + Ok(self) + } + + pub fn dependency(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.dependency_written = true; + Ok(self) + } + + pub fn public_dependency(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(10, value)?; + self.public_dependency_written = true; + Ok(self) + } + + pub fn weak_dependency(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(11, value)?; + self.weak_dependency_written = true; + Ok(self) + } + + pub fn option_dependency(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(15, value)?; + self.option_dependency_written = true; + Ok(self) + } + + pub fn message_type(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.message_type_written = true; + Ok(self) + } + + pub fn enum_type(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(5, value)?; + self.enum_type_written = true; + Ok(self) + } + + pub fn service(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(6, value)?; + self.service_written = true; + Ok(self) + } + + pub fn extension(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(7, value)?; + self.extension_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(8, value)?; + self.options_written = true; + Ok(self) + } + + pub fn source_code_info(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(9, value)?; + self.source_code_info_written = true; + Ok(self) + } + + pub fn syntax(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(12, value)?; + self.syntax_written = true; + Ok(self) + } + + pub fn edition(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(14, value)?; + self.edition_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FileDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.package_written, + 3 => self.dependency_written, + 10 => self.public_dependency_written, + 11 => self.weak_dependency_written, + 15 => self.option_dependency_written, + 4 => self.message_type_written, + 5 => self.enum_type_written, + 6 => self.service_written, + 7 => self.extension_written, + 8 => self.options_written, + 9 => self.source_code_info_written, + 12 => self.syntax_written, + 14 => self.edition_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct DescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + field_start: Option, + field_end: Option, + extension_start: Option, + extension_end: Option, + nested_type_start: Option, + nested_type_end: Option, + enum_type_start: Option, + enum_type_end: Option, + extension_range_start: Option, + extension_range_end: Option, + oneof_decl_start: Option, + oneof_decl_end: Option, + options_offset: Option, + reserved_range_start: Option, + reserved_range_end: Option, + reserved_name_start: Option, + reserved_name_end: Option, + visibility_offset: Option, +} + +impl<'a> DescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut field_start = None; + let mut field_end = None; + let mut extension_start = None; + let mut extension_end = None; + let mut nested_type_start = None; + let mut nested_type_end = None; + let mut enum_type_start = None; + let mut enum_type_end = None; + let mut extension_range_start = None; + let mut extension_range_end = None; + let mut oneof_decl_start = None; + let mut oneof_decl_end = None; + let mut options_offset = None; + let mut reserved_range_start = None; + let mut reserved_range_end = None; + let mut reserved_name_start = None; + let mut reserved_name_end = None; + let mut visibility_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + if field_start.is_none() { + field_start = Some(offset); + } + field_end = Some(offset); + } + if tag.field_number == 6 { + if extension_start.is_none() { + extension_start = Some(offset); + } + extension_end = Some(offset); + } + if tag.field_number == 3 { + if nested_type_start.is_none() { + nested_type_start = Some(offset); + } + nested_type_end = Some(offset); + } + if tag.field_number == 4 { + if enum_type_start.is_none() { + enum_type_start = Some(offset); + } + enum_type_end = Some(offset); + } + if tag.field_number == 5 { + if extension_range_start.is_none() { + extension_range_start = Some(offset); + } + extension_range_end = Some(offset); + } + if tag.field_number == 8 { + if oneof_decl_start.is_none() { + oneof_decl_start = Some(offset); + } + oneof_decl_end = Some(offset); + } + if tag.field_number == 7 { + options_offset = Some(offset); + } + if tag.field_number == 9 { + if reserved_range_start.is_none() { + reserved_range_start = Some(offset); + } + reserved_range_end = Some(offset); + } + if tag.field_number == 10 { + if reserved_name_start.is_none() { + reserved_name_start = Some(offset); + } + reserved_name_end = Some(offset); + } + if tag.field_number == 11 { + visibility_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + field_start, + field_end, + extension_start, + extension_end, + nested_type_start, + nested_type_end, + enum_type_start, + enum_type_end, + extension_range_start, + extension_range_end, + oneof_decl_start, + oneof_decl_end, + options_offset, + reserved_range_start, + reserved_range_end, + reserved_name_start, + reserved_name_end, + visibility_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn field(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.field_start, self.field_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn extension(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.extension_start, self.extension_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(6, start, end), + _ => self.accessor.iter_repeated(6), + } + } + + pub fn nested_type(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.nested_type_start, self.nested_type_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(3, start, end), + _ => self.accessor.iter_repeated(3), + } + } + + pub fn enum_type(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.enum_type_start, self.enum_type_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(4, start, end), + _ => self.accessor.iter_repeated(4), + } + } + + pub fn extension_range(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.extension_range_start, self.extension_range_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(5, start, end), + _ => self.accessor.iter_repeated(5), + } + } + + pub fn oneof_decl(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.oneof_decl_start, self.oneof_decl_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(8, start, end), + _ => self.accessor.iter_repeated(8), + } + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn reserved_range(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.reserved_range_start, self.reserved_range_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(9, start, end), + _ => self.accessor.iter_repeated(9), + } + } + + pub fn reserved_name(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.reserved_name_start, self.reserved_name_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(10, start, end), + _ => self.accessor.iter_repeated(10), + } + } + + pub fn visibility(&self) -> roto_runtime::Result { + let offset = self + .visibility_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct DescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + field_written: bool, + extension_written: bool, + nested_type_written: bool, + enum_type_written: bool, + extension_range_written: bool, + oneof_decl_written: bool, + options_written: bool, + reserved_range_written: bool, + reserved_name_written: bool, + visibility_written: bool, +} + +impl<'b> DescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> DescriptorProtoBuilder<'_> { + DescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + field_written: false, + extension_written: false, + nested_type_written: false, + enum_type_written: false, + extension_range_written: false, + oneof_decl_written: false, + options_written: false, + reserved_range_written: false, + reserved_name_written: false, + visibility_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn field(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.field_written = true; + Ok(self) + } + + pub fn extension(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(6, value)?; + self.extension_written = true; + Ok(self) + } + + pub fn nested_type(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.nested_type_written = true; + Ok(self) + } + + pub fn enum_type(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.enum_type_written = true; + Ok(self) + } + + pub fn extension_range(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(5, value)?; + self.extension_range_written = true; + Ok(self) + } + + pub fn oneof_decl(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(8, value)?; + self.oneof_decl_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(7, value)?; + self.options_written = true; + Ok(self) + } + + pub fn reserved_range(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(9, value)?; + self.reserved_range_written = true; + Ok(self) + } + + pub fn reserved_name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(10, value)?; + self.reserved_name_written = true; + Ok(self) + } + + pub fn visibility(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(11, value)?; + self.visibility_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &DescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.field_written, + 6 => self.extension_written, + 3 => self.nested_type_written, + 4 => self.enum_type_written, + 5 => self.extension_range_written, + 8 => self.oneof_decl_written, + 7 => self.options_written, + 9 => self.reserved_range_written, + 10 => self.reserved_name_written, + 11 => self.visibility_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod descriptor_proto { + pub struct ExtensionRange<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + start_offset: Option, + end_offset: Option, + options_offset: Option, + } + + impl<'a> ExtensionRange<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut start_offset = None; + let mut end_offset = None; + let mut options_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + start_offset = Some(offset); + } + if tag.field_number == 2 { + end_offset = Some(offset); + } + if tag.field_number == 3 { + options_offset = Some(offset); + } + } + + Ok(Self { + accessor, + start_offset, + end_offset, + options_offset, + }) + } + + pub fn start(&self) -> roto_runtime::Result { + let offset = self + .start_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn end(&self) -> roto_runtime::Result { + let offset = self + .end_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct ExtensionRangeBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + start_written: bool, + end_written: bool, + options_written: bool, + } + + impl<'b> ExtensionRangeBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ExtensionRangeBuilder<'_> { + ExtensionRangeBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + start_written: false, + end_written: false, + options_written: false, + } + } + + pub fn start(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.start_written = true; + Ok(self) + } + + pub fn end(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.end_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.options_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &ExtensionRange<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.start_written, + 2 => self.end_written, + 3 => self.options_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } + + pub struct ReservedRange<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + start_offset: Option, + end_offset: Option, + } + + impl<'a> ReservedRange<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut start_offset = None; + let mut end_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + start_offset = Some(offset); + } + if tag.field_number == 2 { + end_offset = Some(offset); + } + } + + Ok(Self { + accessor, + start_offset, + end_offset, + }) + } + + pub fn start(&self) -> roto_runtime::Result { + let offset = self + .start_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn end(&self) -> roto_runtime::Result { + let offset = self + .end_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct ReservedRangeBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + start_written: bool, + end_written: bool, + } + + impl<'b> ReservedRangeBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ReservedRangeBuilder<'_> { + ReservedRangeBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + start_written: false, + end_written: false, + } + } + + pub fn start(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.start_written = true; + Ok(self) + } + + pub fn end(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.end_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &ReservedRange<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.start_written, + 2 => self.end_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct ExtensionRangeOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, + declaration_start: Option, + declaration_end: Option, + features_offset: Option, + verification_offset: Option, +} + +impl<'a> ExtensionRangeOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + let mut declaration_start = None; + let mut declaration_end = None; + let mut features_offset = None; + let mut verification_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + if tag.field_number == 2 { + if declaration_start.is_none() { + declaration_start = Some(offset); + } + declaration_end = Some(offset); + } + if tag.field_number == 50 { + features_offset = Some(offset); + } + if tag.field_number == 3 { + verification_offset = Some(offset); + } + } + + Ok(Self { + accessor, + uninterpreted_option_start, + uninterpreted_option_end, + declaration_start, + declaration_end, + features_offset, + verification_offset, + }) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn declaration(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.declaration_start, self.declaration_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn verification(&self) -> roto_runtime::Result { + let offset = self + .verification_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct ExtensionRangeOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + uninterpreted_option_written: bool, + declaration_written: bool, + features_written: bool, + verification_written: bool, +} + +impl<'b> ExtensionRangeOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ExtensionRangeOptionsBuilder<'_> { + ExtensionRangeOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + uninterpreted_option_written: false, + declaration_written: false, + features_written: false, + verification_written: false, + } + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn declaration(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.declaration_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(50, value)?; + self.features_written = true; + Ok(self) + } + + pub fn verification(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.verification_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &ExtensionRangeOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 999 => self.uninterpreted_option_written, + 2 => self.declaration_written, + 50 => self.features_written, + 3 => self.verification_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod extension_range_options { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum VerificationState { + DECLARATION = 0, + UNVERIFIED = 1, + } + + impl VerificationState { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => VerificationState::DECLARATION, + 1 => VerificationState::UNVERIFIED, + _ => VerificationState::DECLARATION, + } + } + } + + pub struct Declaration<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + number_offset: Option, + full_name_offset: Option, + type_offset: Option, + reserved_offset: Option, + repeated_offset: Option, + } + + impl<'a> Declaration<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut number_offset = None; + let mut full_name_offset = None; + let mut type_offset = None; + let mut reserved_offset = None; + let mut repeated_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + number_offset = Some(offset); + } + if tag.field_number == 2 { + full_name_offset = Some(offset); + } + if tag.field_number == 3 { + type_offset = Some(offset); + } + if tag.field_number == 5 { + reserved_offset = Some(offset); + } + if tag.field_number == 6 { + repeated_offset = Some(offset); + } + } + + Ok(Self { + accessor, + number_offset, + full_name_offset, + type_offset, + reserved_offset, + repeated_offset, + }) + } + + pub fn number(&self) -> roto_runtime::Result { + let offset = self + .number_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn full_name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .full_name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn r#type(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .type_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn reserved(&self) -> roto_runtime::Result { + let offset = self + .reserved_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn repeated(&self) -> roto_runtime::Result { + let offset = self + .repeated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct DeclarationBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + number_written: bool, + full_name_written: bool, + type_written: bool, + reserved_written: bool, + repeated_written: bool, + } + + impl<'b> DeclarationBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> DeclarationBuilder<'_> { + DeclarationBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + number_written: false, + full_name_written: false, + type_written: false, + reserved_written: false, + repeated_written: false, + } + } + + pub fn number(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.number_written = true; + Ok(self) + } + + pub fn full_name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.full_name_written = true; + Ok(self) + } + + pub fn r#type(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.type_written = true; + Ok(self) + } + + pub fn reserved(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.reserved_written = true; + Ok(self) + } + + pub fn repeated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.repeated_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &Declaration<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.number_written, + 2 => self.full_name_written, + 3 => self.type_written, + 5 => self.reserved_written, + 6 => self.repeated_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct FieldDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + number_offset: Option, + label_offset: Option, + type_offset: Option, + type_name_offset: Option, + extendee_offset: Option, + default_value_offset: Option, + oneof_index_offset: Option, + json_name_offset: Option, + options_offset: Option, + proto3_optional_offset: Option, +} + +impl<'a> FieldDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut number_offset = None; + let mut label_offset = None; + let mut type_offset = None; + let mut type_name_offset = None; + let mut extendee_offset = None; + let mut default_value_offset = None; + let mut oneof_index_offset = None; + let mut json_name_offset = None; + let mut options_offset = None; + let mut proto3_optional_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 3 { + number_offset = Some(offset); + } + if tag.field_number == 4 { + label_offset = Some(offset); + } + if tag.field_number == 5 { + type_offset = Some(offset); + } + if tag.field_number == 6 { + type_name_offset = Some(offset); + } + if tag.field_number == 2 { + extendee_offset = Some(offset); + } + if tag.field_number == 7 { + default_value_offset = Some(offset); + } + if tag.field_number == 9 { + oneof_index_offset = Some(offset); + } + if tag.field_number == 10 { + json_name_offset = Some(offset); + } + if tag.field_number == 8 { + options_offset = Some(offset); + } + if tag.field_number == 17 { + proto3_optional_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + number_offset, + label_offset, + type_offset, + type_name_offset, + extendee_offset, + default_value_offset, + oneof_index_offset, + json_name_offset, + options_offset, + proto3_optional_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn number(&self) -> roto_runtime::Result { + let offset = self + .number_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn label(&self) -> roto_runtime::Result { + let offset = self + .label_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn r#type(&self) -> roto_runtime::Result { + let offset = self + .type_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn type_name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .type_name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn extendee(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .extendee_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn default_value(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .default_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn oneof_index(&self) -> roto_runtime::Result { + let offset = self + .oneof_index_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn json_name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .json_name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn proto3_optional(&self) -> roto_runtime::Result { + let offset = self + .proto3_optional_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FieldDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + number_written: bool, + label_written: bool, + type_written: bool, + type_name_written: bool, + extendee_written: bool, + default_value_written: bool, + oneof_index_written: bool, + json_name_written: bool, + options_written: bool, + proto3_optional_written: bool, +} + +impl<'b> FieldDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FieldDescriptorProtoBuilder<'_> { + FieldDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + number_written: false, + label_written: false, + type_written: false, + type_name_written: false, + extendee_written: false, + default_value_written: false, + oneof_index_written: false, + json_name_written: false, + options_written: false, + proto3_optional_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn number(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(3, value)?; + self.number_written = true; + Ok(self) + } + + pub fn label(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(4, value)?; + self.label_written = true; + Ok(self) + } + + pub fn r#type(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.type_written = true; + Ok(self) + } + + pub fn type_name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(6, value)?; + self.type_name_written = true; + Ok(self) + } + + pub fn extendee(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.extendee_written = true; + Ok(self) + } + + pub fn default_value(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(7, value)?; + self.default_value_written = true; + Ok(self) + } + + pub fn oneof_index(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(9, value)?; + self.oneof_index_written = true; + Ok(self) + } + + pub fn json_name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(10, value)?; + self.json_name_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(8, value)?; + self.options_written = true; + Ok(self) + } + + pub fn proto3_optional(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(17, value)?; + self.proto3_optional_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FieldDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 3 => self.number_written, + 4 => self.label_written, + 5 => self.type_written, + 6 => self.type_name_written, + 2 => self.extendee_written, + 7 => self.default_value_written, + 9 => self.oneof_index_written, + 10 => self.json_name_written, + 8 => self.options_written, + 17 => self.proto3_optional_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod field_descriptor_proto { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum Type { + TYPEDOUBLE = 1, + TYPEFLOAT = 2, + TYPEINT64 = 3, + TYPEUINT64 = 4, + TYPEINT32 = 5, + TYPEFIXED64 = 6, + TYPEFIXED32 = 7, + TYPEBOOL = 8, + TYPESTRING = 9, + TYPEGROUP = 10, + TYPEMESSAGE = 11, + TYPEBYTES = 12, + TYPEUINT32 = 13, + TYPEENUM = 14, + TYPESFIXED32 = 15, + TYPESFIXED64 = 16, + TYPESINT32 = 17, + TYPESINT64 = 18, + Unknown = 0, + } + + impl Type { + pub fn from_i32(value: i32) -> Self { + match value { + 1 => Type::TYPEDOUBLE, + 2 => Type::TYPEFLOAT, + 3 => Type::TYPEINT64, + 4 => Type::TYPEUINT64, + 5 => Type::TYPEINT32, + 6 => Type::TYPEFIXED64, + 7 => Type::TYPEFIXED32, + 8 => Type::TYPEBOOL, + 9 => Type::TYPESTRING, + 10 => Type::TYPEGROUP, + 11 => Type::TYPEMESSAGE, + 12 => Type::TYPEBYTES, + 13 => Type::TYPEUINT32, + 14 => Type::TYPEENUM, + 15 => Type::TYPESFIXED32, + 16 => Type::TYPESFIXED64, + 17 => Type::TYPESINT32, + 18 => Type::TYPESINT64, + _ => Type::Unknown, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum Label { + LABELOPTIONAL = 1, + LABELREPEATED = 3, + LABELREQUIRED = 2, + Unknown = 0, + } + + impl Label { + pub fn from_i32(value: i32) -> Self { + match value { + 1 => Label::LABELOPTIONAL, + 3 => Label::LABELREPEATED, + 2 => Label::LABELREQUIRED, + _ => Label::Unknown, + } + } + } +} + +pub struct OneofDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + options_offset: Option, +} + +impl<'a> OneofDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut options_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + options_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + options_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct OneofDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + options_written: bool, +} + +impl<'b> OneofDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> OneofDescriptorProtoBuilder<'_> { + OneofDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + options_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.options_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &OneofDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.options_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct EnumDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + value_start: Option, + value_end: Option, + options_offset: Option, + reserved_range_start: Option, + reserved_range_end: Option, + reserved_name_start: Option, + reserved_name_end: Option, + visibility_offset: Option, +} + +impl<'a> EnumDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut value_start = None; + let mut value_end = None; + let mut options_offset = None; + let mut reserved_range_start = None; + let mut reserved_range_end = None; + let mut reserved_name_start = None; + let mut reserved_name_end = None; + let mut visibility_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + if value_start.is_none() { + value_start = Some(offset); + } + value_end = Some(offset); + } + if tag.field_number == 3 { + options_offset = Some(offset); + } + if tag.field_number == 4 { + if reserved_range_start.is_none() { + reserved_range_start = Some(offset); + } + reserved_range_end = Some(offset); + } + if tag.field_number == 5 { + if reserved_name_start.is_none() { + reserved_name_start = Some(offset); + } + reserved_name_end = Some(offset); + } + if tag.field_number == 6 { + visibility_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + value_start, + value_end, + options_offset, + reserved_range_start, + reserved_range_end, + reserved_name_start, + reserved_name_end, + visibility_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn value(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.value_start, self.value_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn reserved_range(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.reserved_range_start, self.reserved_range_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(4, start, end), + _ => self.accessor.iter_repeated(4), + } + } + + pub fn reserved_name(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.reserved_name_start, self.reserved_name_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(5, start, end), + _ => self.accessor.iter_repeated(5), + } + } + + pub fn visibility(&self) -> roto_runtime::Result { + let offset = self + .visibility_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct EnumDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + value_written: bool, + options_written: bool, + reserved_range_written: bool, + reserved_name_written: bool, + visibility_written: bool, +} + +impl<'b> EnumDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EnumDescriptorProtoBuilder<'_> { + EnumDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + value_written: false, + options_written: false, + reserved_range_written: false, + reserved_name_written: false, + visibility_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn value(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.value_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.options_written = true; + Ok(self) + } + + pub fn reserved_range(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.reserved_range_written = true; + Ok(self) + } + + pub fn reserved_name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(5, value)?; + self.reserved_name_written = true; + Ok(self) + } + + pub fn visibility(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.visibility_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EnumDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.value_written, + 3 => self.options_written, + 4 => self.reserved_range_written, + 5 => self.reserved_name_written, + 6 => self.visibility_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod enum_descriptor_proto { + pub struct EnumReservedRange<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + start_offset: Option, + end_offset: Option, + } + + impl<'a> EnumReservedRange<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut start_offset = None; + let mut end_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + start_offset = Some(offset); + } + if tag.field_number == 2 { + end_offset = Some(offset); + } + } + + Ok(Self { + accessor, + start_offset, + end_offset, + }) + } + + pub fn start(&self) -> roto_runtime::Result { + let offset = self + .start_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn end(&self) -> roto_runtime::Result { + let offset = self + .end_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct EnumReservedRangeBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + start_written: bool, + end_written: bool, + } + + impl<'b> EnumReservedRangeBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EnumReservedRangeBuilder<'_> { + EnumReservedRangeBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + start_written: false, + end_written: false, + } + } + + pub fn start(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.start_written = true; + Ok(self) + } + + pub fn end(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.end_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EnumReservedRange<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.start_written, + 2 => self.end_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct EnumValueDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + number_offset: Option, + options_offset: Option, +} + +impl<'a> EnumValueDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut number_offset = None; + let mut options_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + number_offset = Some(offset); + } + if tag.field_number == 3 { + options_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + number_offset, + options_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn number(&self) -> roto_runtime::Result { + let offset = self + .number_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct EnumValueDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + number_written: bool, + options_written: bool, +} + +impl<'b> EnumValueDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EnumValueDescriptorProtoBuilder<'_> { + EnumValueDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + number_written: false, + options_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn number(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.number_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.options_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EnumValueDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.number_written, + 3 => self.options_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct ServiceDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + method_start: Option, + method_end: Option, + options_offset: Option, +} + +impl<'a> ServiceDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut method_start = None; + let mut method_end = None; + let mut options_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + if method_start.is_none() { + method_start = Some(offset); + } + method_end = Some(offset); + } + if tag.field_number == 3 { + options_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + method_start, + method_end, + options_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn method(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.method_start, self.method_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct ServiceDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + method_written: bool, + options_written: bool, +} + +impl<'b> ServiceDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ServiceDescriptorProtoBuilder<'_> { + ServiceDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + method_written: false, + options_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn method(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.method_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(3, value)?; + self.options_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &ServiceDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.method_written, + 3 => self.options_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct MethodDescriptorProto<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_offset: Option, + input_type_offset: Option, + output_type_offset: Option, + options_offset: Option, + client_streaming_offset: Option, + server_streaming_offset: Option, +} + +impl<'a> MethodDescriptorProto<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_offset = None; + let mut input_type_offset = None; + let mut output_type_offset = None; + let mut options_offset = None; + let mut client_streaming_offset = None; + let mut server_streaming_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_offset = Some(offset); + } + if tag.field_number == 2 { + input_type_offset = Some(offset); + } + if tag.field_number == 3 { + output_type_offset = Some(offset); + } + if tag.field_number == 4 { + options_offset = Some(offset); + } + if tag.field_number == 5 { + client_streaming_offset = Some(offset); + } + if tag.field_number == 6 { + server_streaming_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_offset, + input_type_offset, + output_type_offset, + options_offset, + client_streaming_offset, + server_streaming_offset, + }) + } + + pub fn name(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn input_type(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .input_type_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn output_type(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .output_type_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn options(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .options_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn client_streaming(&self) -> roto_runtime::Result { + let offset = self + .client_streaming_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn server_streaming(&self) -> roto_runtime::Result { + let offset = self + .server_streaming_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct MethodDescriptorProtoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + input_type_written: bool, + output_type_written: bool, + options_written: bool, + client_streaming_written: bool, + server_streaming_written: bool, +} + +impl<'b> MethodDescriptorProtoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> MethodDescriptorProtoBuilder<'_> { + MethodDescriptorProtoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + input_type_written: false, + output_type_written: false, + options_written: false, + client_streaming_written: false, + server_streaming_written: false, + } + } + + pub fn name(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_written = true; + Ok(self) + } + + pub fn input_type(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.input_type_written = true; + Ok(self) + } + + pub fn output_type(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.output_type_written = true; + Ok(self) + } + + pub fn options(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.options_written = true; + Ok(self) + } + + pub fn client_streaming(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.client_streaming_written = true; + Ok(self) + } + + pub fn server_streaming(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.server_streaming_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &MethodDescriptorProto<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_written, + 2 => self.input_type_written, + 3 => self.output_type_written, + 4 => self.options_written, + 5 => self.client_streaming_written, + 6 => self.server_streaming_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct FileOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + java_package_offset: Option, + java_outer_classname_offset: Option, + java_multiple_files_offset: Option, + java_generate_equals_and_hash_offset: Option, + java_string_check_utf8_offset: Option, + optimize_for_offset: Option, + go_package_offset: Option, + cc_generic_services_offset: Option, + java_generic_services_offset: Option, + py_generic_services_offset: Option, + deprecated_offset: Option, + cc_enable_arenas_offset: Option, + objc_class_prefix_offset: Option, + csharp_namespace_offset: Option, + swift_prefix_offset: Option, + php_class_prefix_offset: Option, + php_namespace_offset: Option, + php_metadata_namespace_offset: Option, + ruby_package_offset: Option, + features_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> FileOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut java_package_offset = None; + let mut java_outer_classname_offset = None; + let mut java_multiple_files_offset = None; + let mut java_generate_equals_and_hash_offset = None; + let mut java_string_check_utf8_offset = None; + let mut optimize_for_offset = None; + let mut go_package_offset = None; + let mut cc_generic_services_offset = None; + let mut java_generic_services_offset = None; + let mut py_generic_services_offset = None; + let mut deprecated_offset = None; + let mut cc_enable_arenas_offset = None; + let mut objc_class_prefix_offset = None; + let mut csharp_namespace_offset = None; + let mut swift_prefix_offset = None; + let mut php_class_prefix_offset = None; + let mut php_namespace_offset = None; + let mut php_metadata_namespace_offset = None; + let mut ruby_package_offset = None; + let mut features_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + java_package_offset = Some(offset); + } + if tag.field_number == 8 { + java_outer_classname_offset = Some(offset); + } + if tag.field_number == 10 { + java_multiple_files_offset = Some(offset); + } + if tag.field_number == 20 { + java_generate_equals_and_hash_offset = Some(offset); + } + if tag.field_number == 27 { + java_string_check_utf8_offset = Some(offset); + } + if tag.field_number == 9 { + optimize_for_offset = Some(offset); + } + if tag.field_number == 11 { + go_package_offset = Some(offset); + } + if tag.field_number == 16 { + cc_generic_services_offset = Some(offset); + } + if tag.field_number == 17 { + java_generic_services_offset = Some(offset); + } + if tag.field_number == 18 { + py_generic_services_offset = Some(offset); + } + if tag.field_number == 23 { + deprecated_offset = Some(offset); + } + if tag.field_number == 31 { + cc_enable_arenas_offset = Some(offset); + } + if tag.field_number == 36 { + objc_class_prefix_offset = Some(offset); + } + if tag.field_number == 37 { + csharp_namespace_offset = Some(offset); + } + if tag.field_number == 39 { + swift_prefix_offset = Some(offset); + } + if tag.field_number == 40 { + php_class_prefix_offset = Some(offset); + } + if tag.field_number == 41 { + php_namespace_offset = Some(offset); + } + if tag.field_number == 44 { + php_metadata_namespace_offset = Some(offset); + } + if tag.field_number == 45 { + ruby_package_offset = Some(offset); + } + if tag.field_number == 50 { + features_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + java_package_offset, + java_outer_classname_offset, + java_multiple_files_offset, + java_generate_equals_and_hash_offset, + java_string_check_utf8_offset, + optimize_for_offset, + go_package_offset, + cc_generic_services_offset, + java_generic_services_offset, + py_generic_services_offset, + deprecated_offset, + cc_enable_arenas_offset, + objc_class_prefix_offset, + csharp_namespace_offset, + swift_prefix_offset, + php_class_prefix_offset, + php_namespace_offset, + php_metadata_namespace_offset, + ruby_package_offset, + features_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn java_package(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .java_package_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn java_outer_classname(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .java_outer_classname_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn java_multiple_files(&self) -> roto_runtime::Result { + let offset = self + .java_multiple_files_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn java_generate_equals_and_hash(&self) -> roto_runtime::Result { + let offset = self + .java_generate_equals_and_hash_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn java_string_check_utf8(&self) -> roto_runtime::Result { + let offset = self + .java_string_check_utf8_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn optimize_for(&self) -> roto_runtime::Result { + let offset = self + .optimize_for_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn go_package(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .go_package_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn cc_generic_services(&self) -> roto_runtime::Result { + let offset = self + .cc_generic_services_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn java_generic_services(&self) -> roto_runtime::Result { + let offset = self + .java_generic_services_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn py_generic_services(&self) -> roto_runtime::Result { + let offset = self + .py_generic_services_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn cc_enable_arenas(&self) -> roto_runtime::Result { + let offset = self + .cc_enable_arenas_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn objc_class_prefix(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .objc_class_prefix_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn csharp_namespace(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .csharp_namespace_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn swift_prefix(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .swift_prefix_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn php_class_prefix(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .php_class_prefix_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn php_namespace(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .php_namespace_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn php_metadata_namespace(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .php_metadata_namespace_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn ruby_package(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .ruby_package_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FileOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + java_package_written: bool, + java_outer_classname_written: bool, + java_multiple_files_written: bool, + java_generate_equals_and_hash_written: bool, + java_string_check_utf8_written: bool, + optimize_for_written: bool, + go_package_written: bool, + cc_generic_services_written: bool, + java_generic_services_written: bool, + py_generic_services_written: bool, + deprecated_written: bool, + cc_enable_arenas_written: bool, + objc_class_prefix_written: bool, + csharp_namespace_written: bool, + swift_prefix_written: bool, + php_class_prefix_written: bool, + php_namespace_written: bool, + php_metadata_namespace_written: bool, + ruby_package_written: bool, + features_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> FileOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FileOptionsBuilder<'_> { + FileOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + java_package_written: false, + java_outer_classname_written: false, + java_multiple_files_written: false, + java_generate_equals_and_hash_written: false, + java_string_check_utf8_written: false, + optimize_for_written: false, + go_package_written: false, + cc_generic_services_written: false, + java_generic_services_written: false, + py_generic_services_written: false, + deprecated_written: false, + cc_enable_arenas_written: false, + objc_class_prefix_written: false, + csharp_namespace_written: false, + swift_prefix_written: false, + php_class_prefix_written: false, + php_namespace_written: false, + php_metadata_namespace_written: false, + ruby_package_written: false, + features_written: false, + uninterpreted_option_written: false, + } + } + + pub fn java_package(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.java_package_written = true; + Ok(self) + } + + pub fn java_outer_classname(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(8, value)?; + self.java_outer_classname_written = true; + Ok(self) + } + + pub fn java_multiple_files(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(10, value)?; + self.java_multiple_files_written = true; + Ok(self) + } + + pub fn java_generate_equals_and_hash(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(20, value)?; + self.java_generate_equals_and_hash_written = true; + Ok(self) + } + + pub fn java_string_check_utf8(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(27, value)?; + self.java_string_check_utf8_written = true; + Ok(self) + } + + pub fn optimize_for(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(9, value)?; + self.optimize_for_written = true; + Ok(self) + } + + pub fn go_package(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(11, value)?; + self.go_package_written = true; + Ok(self) + } + + pub fn cc_generic_services(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(16, value)?; + self.cc_generic_services_written = true; + Ok(self) + } + + pub fn java_generic_services(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(17, value)?; + self.java_generic_services_written = true; + Ok(self) + } + + pub fn py_generic_services(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(18, value)?; + self.py_generic_services_written = true; + Ok(self) + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(23, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn cc_enable_arenas(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(31, value)?; + self.cc_enable_arenas_written = true; + Ok(self) + } + + pub fn objc_class_prefix(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(36, value)?; + self.objc_class_prefix_written = true; + Ok(self) + } + + pub fn csharp_namespace(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(37, value)?; + self.csharp_namespace_written = true; + Ok(self) + } + + pub fn swift_prefix(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(39, value)?; + self.swift_prefix_written = true; + Ok(self) + } + + pub fn php_class_prefix(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(40, value)?; + self.php_class_prefix_written = true; + Ok(self) + } + + pub fn php_namespace(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(41, value)?; + self.php_namespace_written = true; + Ok(self) + } + + pub fn php_metadata_namespace(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(44, value)?; + self.php_metadata_namespace_written = true; + Ok(self) + } + + pub fn ruby_package(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(45, value)?; + self.ruby_package_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(50, value)?; + self.features_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FileOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.java_package_written, + 8 => self.java_outer_classname_written, + 10 => self.java_multiple_files_written, + 20 => self.java_generate_equals_and_hash_written, + 27 => self.java_string_check_utf8_written, + 9 => self.optimize_for_written, + 11 => self.go_package_written, + 16 => self.cc_generic_services_written, + 17 => self.java_generic_services_written, + 18 => self.py_generic_services_written, + 23 => self.deprecated_written, + 31 => self.cc_enable_arenas_written, + 36 => self.objc_class_prefix_written, + 37 => self.csharp_namespace_written, + 39 => self.swift_prefix_written, + 40 => self.php_class_prefix_written, + 41 => self.php_namespace_written, + 44 => self.php_metadata_namespace_written, + 45 => self.ruby_package_written, + 50 => self.features_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod file_options { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum OptimizeMode { + SPEED = 1, + CODESIZE = 2, + LITERUNTIME = 3, + Unknown = 0, + } + + impl OptimizeMode { + pub fn from_i32(value: i32) -> Self { + match value { + 1 => OptimizeMode::SPEED, + 2 => OptimizeMode::CODESIZE, + 3 => OptimizeMode::LITERUNTIME, + _ => OptimizeMode::Unknown, + } + } + } +} + +pub struct MessageOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + message_set_wire_format_offset: Option, + no_standard_descriptor_accessor_offset: Option, + deprecated_offset: Option, + map_entry_offset: Option, + deprecated_legacy_json_field_conflicts_offset: Option, + features_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> MessageOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut message_set_wire_format_offset = None; + let mut no_standard_descriptor_accessor_offset = None; + let mut deprecated_offset = None; + let mut map_entry_offset = None; + let mut deprecated_legacy_json_field_conflicts_offset = None; + let mut features_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + message_set_wire_format_offset = Some(offset); + } + if tag.field_number == 2 { + no_standard_descriptor_accessor_offset = Some(offset); + } + if tag.field_number == 3 { + deprecated_offset = Some(offset); + } + if tag.field_number == 7 { + map_entry_offset = Some(offset); + } + if tag.field_number == 11 { + deprecated_legacy_json_field_conflicts_offset = Some(offset); + } + if tag.field_number == 12 { + features_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + message_set_wire_format_offset, + no_standard_descriptor_accessor_offset, + deprecated_offset, + map_entry_offset, + deprecated_legacy_json_field_conflicts_offset, + features_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn message_set_wire_format(&self) -> roto_runtime::Result { + let offset = self + .message_set_wire_format_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn no_standard_descriptor_accessor(&self) -> roto_runtime::Result { + let offset = self + .no_standard_descriptor_accessor_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn map_entry(&self) -> roto_runtime::Result { + let offset = self + .map_entry_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated_legacy_json_field_conflicts(&self) -> roto_runtime::Result { + let offset = self + .deprecated_legacy_json_field_conflicts_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct MessageOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + message_set_wire_format_written: bool, + no_standard_descriptor_accessor_written: bool, + deprecated_written: bool, + map_entry_written: bool, + deprecated_legacy_json_field_conflicts_written: bool, + features_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> MessageOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> MessageOptionsBuilder<'_> { + MessageOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + message_set_wire_format_written: false, + no_standard_descriptor_accessor_written: false, + deprecated_written: false, + map_entry_written: false, + deprecated_legacy_json_field_conflicts_written: false, + features_written: false, + uninterpreted_option_written: false, + } + } + + pub fn message_set_wire_format(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(1, value)?; + self.message_set_wire_format_written = true; + Ok(self) + } + + pub fn no_standard_descriptor_accessor(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.no_standard_descriptor_accessor_written = true; + Ok(self) + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn map_entry(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(7, value)?; + self.map_entry_written = true; + Ok(self) + } + + pub fn deprecated_legacy_json_field_conflicts( + mut self, + value: u64, + ) -> roto_runtime::Result { + self.builder.write_varint(11, value)?; + self.deprecated_legacy_json_field_conflicts_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(12, value)?; + self.features_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &MessageOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.message_set_wire_format_written, + 2 => self.no_standard_descriptor_accessor_written, + 3 => self.deprecated_written, + 7 => self.map_entry_written, + 11 => self.deprecated_legacy_json_field_conflicts_written, + 12 => self.features_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct FieldOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + ctype_offset: Option, + packed_offset: Option, + jstype_offset: Option, + lazy_offset: Option, + unverified_lazy_offset: Option, + deprecated_offset: Option, + weak_offset: Option, + debug_redact_offset: Option, + retention_offset: Option, + targets_start: Option, + targets_end: Option, + edition_defaults_start: Option, + edition_defaults_end: Option, + features_offset: Option, + feature_support_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> FieldOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut ctype_offset = None; + let mut packed_offset = None; + let mut jstype_offset = None; + let mut lazy_offset = None; + let mut unverified_lazy_offset = None; + let mut deprecated_offset = None; + let mut weak_offset = None; + let mut debug_redact_offset = None; + let mut retention_offset = None; + let mut targets_start = None; + let mut targets_end = None; + let mut edition_defaults_start = None; + let mut edition_defaults_end = None; + let mut features_offset = None; + let mut feature_support_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + ctype_offset = Some(offset); + } + if tag.field_number == 2 { + packed_offset = Some(offset); + } + if tag.field_number == 6 { + jstype_offset = Some(offset); + } + if tag.field_number == 5 { + lazy_offset = Some(offset); + } + if tag.field_number == 15 { + unverified_lazy_offset = Some(offset); + } + if tag.field_number == 3 { + deprecated_offset = Some(offset); + } + if tag.field_number == 10 { + weak_offset = Some(offset); + } + if tag.field_number == 16 { + debug_redact_offset = Some(offset); + } + if tag.field_number == 17 { + retention_offset = Some(offset); + } + if tag.field_number == 19 { + if targets_start.is_none() { + targets_start = Some(offset); + } + targets_end = Some(offset); + } + if tag.field_number == 20 { + if edition_defaults_start.is_none() { + edition_defaults_start = Some(offset); + } + edition_defaults_end = Some(offset); + } + if tag.field_number == 21 { + features_offset = Some(offset); + } + if tag.field_number == 22 { + feature_support_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + ctype_offset, + packed_offset, + jstype_offset, + lazy_offset, + unverified_lazy_offset, + deprecated_offset, + weak_offset, + debug_redact_offset, + retention_offset, + targets_start, + targets_end, + edition_defaults_start, + edition_defaults_end, + features_offset, + feature_support_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn ctype(&self) -> roto_runtime::Result { + let offset = self + .ctype_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn packed(&self) -> roto_runtime::Result { + let offset = self + .packed_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn jstype(&self) -> roto_runtime::Result { + let offset = self + .jstype_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn lazy(&self) -> roto_runtime::Result { + let offset = self + .lazy_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn unverified_lazy(&self) -> roto_runtime::Result { + let offset = self + .unverified_lazy_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn weak(&self) -> roto_runtime::Result { + let offset = self + .weak_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn debug_redact(&self) -> roto_runtime::Result { + let offset = self + .debug_redact_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn retention(&self) -> roto_runtime::Result { + let offset = self + .retention_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn targets(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.targets_start, self.targets_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(19, start, end), + _ => self.accessor.iter_repeated(19), + } + } + + pub fn edition_defaults(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.edition_defaults_start, self.edition_defaults_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(20, start, end), + _ => self.accessor.iter_repeated(20), + } + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn feature_support(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .feature_support_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FieldOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + ctype_written: bool, + packed_written: bool, + jstype_written: bool, + lazy_written: bool, + unverified_lazy_written: bool, + deprecated_written: bool, + weak_written: bool, + debug_redact_written: bool, + retention_written: bool, + targets_written: bool, + edition_defaults_written: bool, + features_written: bool, + feature_support_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> FieldOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FieldOptionsBuilder<'_> { + FieldOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + ctype_written: false, + packed_written: false, + jstype_written: false, + lazy_written: false, + unverified_lazy_written: false, + deprecated_written: false, + weak_written: false, + debug_redact_written: false, + retention_written: false, + targets_written: false, + edition_defaults_written: false, + features_written: false, + feature_support_written: false, + uninterpreted_option_written: false, + } + } + + pub fn ctype(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(1, value)?; + self.ctype_written = true; + Ok(self) + } + + pub fn packed(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.packed_written = true; + Ok(self) + } + + pub fn jstype(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.jstype_written = true; + Ok(self) + } + + pub fn lazy(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.lazy_written = true; + Ok(self) + } + + pub fn unverified_lazy(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(15, value)?; + self.unverified_lazy_written = true; + Ok(self) + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn weak(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(10, value)?; + self.weak_written = true; + Ok(self) + } + + pub fn debug_redact(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(16, value)?; + self.debug_redact_written = true; + Ok(self) + } + + pub fn retention(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(17, value)?; + self.retention_written = true; + Ok(self) + } + + pub fn targets(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(19, value)?; + self.targets_written = true; + Ok(self) + } + + pub fn edition_defaults(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(20, value)?; + self.edition_defaults_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(21, value)?; + self.features_written = true; + Ok(self) + } + + pub fn feature_support(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(22, value)?; + self.feature_support_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FieldOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.ctype_written, + 2 => self.packed_written, + 6 => self.jstype_written, + 5 => self.lazy_written, + 15 => self.unverified_lazy_written, + 3 => self.deprecated_written, + 10 => self.weak_written, + 16 => self.debug_redact_written, + 17 => self.retention_written, + 19 => self.targets_written, + 20 => self.edition_defaults_written, + 21 => self.features_written, + 22 => self.feature_support_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod field_options { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum CType { + STRING = 0, + CORD = 1, + STRINGPIECE = 2, + } + + impl CType { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => CType::STRING, + 1 => CType::CORD, + 2 => CType::STRINGPIECE, + _ => CType::STRING, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum JSType { + JSNORMAL = 0, + JSSTRING = 1, + JSNUMBER = 2, + } + + impl JSType { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => JSType::JSNORMAL, + 1 => JSType::JSSTRING, + 2 => JSType::JSNUMBER, + _ => JSType::JSNORMAL, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum OptionRetention { + RETENTIONUNKNOWN = 0, + RETENTIONRUNTIME = 1, + RETENTIONSOURCE = 2, + } + + impl OptionRetention { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => OptionRetention::RETENTIONUNKNOWN, + 1 => OptionRetention::RETENTIONRUNTIME, + 2 => OptionRetention::RETENTIONSOURCE, + _ => OptionRetention::RETENTIONUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum OptionTargetType { + TARGETTYPEUNKNOWN = 0, + TARGETTYPEFILE = 1, + TARGETTYPEEXTENSIONRANGE = 2, + TARGETTYPEMESSAGE = 3, + TARGETTYPEFIELD = 4, + TARGETTYPEONEOF = 5, + TARGETTYPEENUM = 6, + TARGETTYPEENUMENTRY = 7, + TARGETTYPESERVICE = 8, + TARGETTYPEMETHOD = 9, + } + + impl OptionTargetType { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => OptionTargetType::TARGETTYPEUNKNOWN, + 1 => OptionTargetType::TARGETTYPEFILE, + 2 => OptionTargetType::TARGETTYPEEXTENSIONRANGE, + 3 => OptionTargetType::TARGETTYPEMESSAGE, + 4 => OptionTargetType::TARGETTYPEFIELD, + 5 => OptionTargetType::TARGETTYPEONEOF, + 6 => OptionTargetType::TARGETTYPEENUM, + 7 => OptionTargetType::TARGETTYPEENUMENTRY, + 8 => OptionTargetType::TARGETTYPESERVICE, + 9 => OptionTargetType::TARGETTYPEMETHOD, + _ => OptionTargetType::TARGETTYPEUNKNOWN, + } + } + } + + pub struct EditionDefault<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + edition_offset: Option, + value_offset: Option, + } + + impl<'a> EditionDefault<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut edition_offset = None; + let mut value_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 3 { + edition_offset = Some(offset); + } + if tag.field_number == 2 { + value_offset = Some(offset); + } + } + + Ok(Self { + accessor, + edition_offset, + value_offset, + }) + } + + pub fn edition(&self) -> roto_runtime::Result { + let offset = self + .edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn value(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct EditionDefaultBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + edition_written: bool, + value_written: bool, + } + + impl<'b> EditionDefaultBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EditionDefaultBuilder<'_> { + EditionDefaultBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + edition_written: false, + value_written: false, + } + } + + pub fn edition(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.edition_written = true; + Ok(self) + } + + pub fn value(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.value_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EditionDefault<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 3 => self.edition_written, + 2 => self.value_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } + + pub struct FeatureSupport<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + edition_introduced_offset: Option, + edition_deprecated_offset: Option, + deprecation_warning_offset: Option, + edition_removed_offset: Option, + removal_error_offset: Option, + } + + impl<'a> FeatureSupport<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut edition_introduced_offset = None; + let mut edition_deprecated_offset = None; + let mut deprecation_warning_offset = None; + let mut edition_removed_offset = None; + let mut removal_error_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + edition_introduced_offset = Some(offset); + } + if tag.field_number == 2 { + edition_deprecated_offset = Some(offset); + } + if tag.field_number == 3 { + deprecation_warning_offset = Some(offset); + } + if tag.field_number == 4 { + edition_removed_offset = Some(offset); + } + if tag.field_number == 5 { + removal_error_offset = Some(offset); + } + } + + Ok(Self { + accessor, + edition_introduced_offset, + edition_deprecated_offset, + deprecation_warning_offset, + edition_removed_offset, + removal_error_offset, + }) + } + + pub fn edition_introduced(&self) -> roto_runtime::Result { + let offset = self + .edition_introduced_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn edition_deprecated(&self) -> roto_runtime::Result { + let offset = self + .edition_deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecation_warning(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .deprecation_warning_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn edition_removed(&self) -> roto_runtime::Result { + let offset = self + .edition_removed_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn removal_error(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .removal_error_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct FeatureSupportBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + edition_introduced_written: bool, + edition_deprecated_written: bool, + deprecation_warning_written: bool, + edition_removed_written: bool, + removal_error_written: bool, + } + + impl<'b> FeatureSupportBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FeatureSupportBuilder<'_> { + FeatureSupportBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + edition_introduced_written: false, + edition_deprecated_written: false, + deprecation_warning_written: false, + edition_removed_written: false, + removal_error_written: false, + } + } + + pub fn edition_introduced(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(1, value)?; + self.edition_introduced_written = true; + Ok(self) + } + + pub fn edition_deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.edition_deprecated_written = true; + Ok(self) + } + + pub fn deprecation_warning(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.deprecation_warning_written = true; + Ok(self) + } + + pub fn edition_removed(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(4, value)?; + self.edition_removed_written = true; + Ok(self) + } + + pub fn removal_error(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(5, value)?; + self.removal_error_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FeatureSupport<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.edition_introduced_written, + 2 => self.edition_deprecated_written, + 3 => self.deprecation_warning_written, + 4 => self.edition_removed_written, + 5 => self.removal_error_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct OneofOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + features_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> OneofOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut features_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + features_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + features_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct OneofOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + features_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> OneofOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> OneofOptionsBuilder<'_> { + OneofOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + features_written: false, + uninterpreted_option_written: false, + } + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(1, value)?; + self.features_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &OneofOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.features_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct EnumOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + allow_alias_offset: Option, + deprecated_offset: Option, + deprecated_legacy_json_field_conflicts_offset: Option, + features_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> EnumOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut allow_alias_offset = None; + let mut deprecated_offset = None; + let mut deprecated_legacy_json_field_conflicts_offset = None; + let mut features_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 2 { + allow_alias_offset = Some(offset); + } + if tag.field_number == 3 { + deprecated_offset = Some(offset); + } + if tag.field_number == 6 { + deprecated_legacy_json_field_conflicts_offset = Some(offset); + } + if tag.field_number == 7 { + features_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + allow_alias_offset, + deprecated_offset, + deprecated_legacy_json_field_conflicts_offset, + features_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn allow_alias(&self) -> roto_runtime::Result { + let offset = self + .allow_alias_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn deprecated_legacy_json_field_conflicts(&self) -> roto_runtime::Result { + let offset = self + .deprecated_legacy_json_field_conflicts_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct EnumOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + allow_alias_written: bool, + deprecated_written: bool, + deprecated_legacy_json_field_conflicts_written: bool, + features_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> EnumOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EnumOptionsBuilder<'_> { + EnumOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + allow_alias_written: false, + deprecated_written: false, + deprecated_legacy_json_field_conflicts_written: false, + features_written: false, + uninterpreted_option_written: false, + } + } + + pub fn allow_alias(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.allow_alias_written = true; + Ok(self) + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn deprecated_legacy_json_field_conflicts( + mut self, + value: u64, + ) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.deprecated_legacy_json_field_conflicts_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(7, value)?; + self.features_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EnumOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 2 => self.allow_alias_written, + 3 => self.deprecated_written, + 6 => self.deprecated_legacy_json_field_conflicts_written, + 7 => self.features_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct EnumValueOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + deprecated_offset: Option, + features_offset: Option, + debug_redact_offset: Option, + feature_support_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> EnumValueOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut deprecated_offset = None; + let mut features_offset = None; + let mut debug_redact_offset = None; + let mut feature_support_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + deprecated_offset = Some(offset); + } + if tag.field_number == 2 { + features_offset = Some(offset); + } + if tag.field_number == 3 { + debug_redact_offset = Some(offset); + } + if tag.field_number == 4 { + feature_support_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + deprecated_offset, + features_offset, + debug_redact_offset, + feature_support_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn debug_redact(&self) -> roto_runtime::Result { + let offset = self + .debug_redact_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn feature_support(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .feature_support_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct EnumValueOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + deprecated_written: bool, + features_written: bool, + debug_redact_written: bool, + feature_support_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> EnumValueOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> EnumValueOptionsBuilder<'_> { + EnumValueOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + deprecated_written: false, + features_written: false, + debug_redact_written: false, + feature_support_written: false, + uninterpreted_option_written: false, + } + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(1, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.features_written = true; + Ok(self) + } + + pub fn debug_redact(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.debug_redact_written = true; + Ok(self) + } + + pub fn feature_support(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.feature_support_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &EnumValueOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.deprecated_written, + 2 => self.features_written, + 3 => self.debug_redact_written, + 4 => self.feature_support_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct ServiceOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + features_offset: Option, + deprecated_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> ServiceOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut features_offset = None; + let mut deprecated_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 34 { + features_offset = Some(offset); + } + if tag.field_number == 33 { + deprecated_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + features_offset, + deprecated_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct ServiceOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + features_written: bool, + deprecated_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> ServiceOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ServiceOptionsBuilder<'_> { + ServiceOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + features_written: false, + deprecated_written: false, + uninterpreted_option_written: false, + } + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(34, value)?; + self.features_written = true; + Ok(self) + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(33, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &ServiceOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 34 => self.features_written, + 33 => self.deprecated_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub struct MethodOptions<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + deprecated_offset: Option, + idempotency_level_offset: Option, + features_offset: Option, + uninterpreted_option_start: Option, + uninterpreted_option_end: Option, +} + +impl<'a> MethodOptions<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut deprecated_offset = None; + let mut idempotency_level_offset = None; + let mut features_offset = None; + let mut uninterpreted_option_start = None; + let mut uninterpreted_option_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 33 { + deprecated_offset = Some(offset); + } + if tag.field_number == 34 { + idempotency_level_offset = Some(offset); + } + if tag.field_number == 35 { + features_offset = Some(offset); + } + if tag.field_number == 999 { + if uninterpreted_option_start.is_none() { + uninterpreted_option_start = Some(offset); + } + uninterpreted_option_end = Some(offset); + } + } + + Ok(Self { + accessor, + deprecated_offset, + idempotency_level_offset, + features_offset, + uninterpreted_option_start, + uninterpreted_option_end, + }) + } + + pub fn deprecated(&self) -> roto_runtime::Result { + let offset = self + .deprecated_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn idempotency_level(&self) -> roto_runtime::Result { + let offset = self + .idempotency_level_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn uninterpreted_option(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.uninterpreted_option_start, + self.uninterpreted_option_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(999, start, end), + _ => self.accessor.iter_repeated(999), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct MethodOptionsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + deprecated_written: bool, + idempotency_level_written: bool, + features_written: bool, + uninterpreted_option_written: bool, +} + +impl<'b> MethodOptionsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> MethodOptionsBuilder<'_> { + MethodOptionsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + deprecated_written: false, + idempotency_level_written: false, + features_written: false, + uninterpreted_option_written: false, + } + } + + pub fn deprecated(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(33, value)?; + self.deprecated_written = true; + Ok(self) + } + + pub fn idempotency_level(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(34, value)?; + self.idempotency_level_written = true; + Ok(self) + } + + pub fn features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(35, value)?; + self.features_written = true; + Ok(self) + } + + pub fn uninterpreted_option(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(999, value)?; + self.uninterpreted_option_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &MethodOptions<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 33 => self.deprecated_written, + 34 => self.idempotency_level_written, + 35 => self.features_written, + 999 => self.uninterpreted_option_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod method_options { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum IdempotencyLevel { + IDEMPOTENCYUNKNOWN = 0, + NOSIDEEFFECTS = 1, + IDEMPOTENT = 2, + } + + impl IdempotencyLevel { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => IdempotencyLevel::IDEMPOTENCYUNKNOWN, + 1 => IdempotencyLevel::NOSIDEEFFECTS, + 2 => IdempotencyLevel::IDEMPOTENT, + _ => IdempotencyLevel::IDEMPOTENCYUNKNOWN, + } + } + } +} + +pub struct UninterpretedOption<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_start: Option, + name_end: Option, + identifier_value_offset: Option, + positive_int_value_offset: Option, + negative_int_value_offset: Option, + double_value_offset: Option, + string_value_offset: Option, + aggregate_value_offset: Option, +} + +impl<'a> UninterpretedOption<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_start = None; + let mut name_end = None; + let mut identifier_value_offset = None; + let mut positive_int_value_offset = None; + let mut negative_int_value_offset = None; + let mut double_value_offset = None; + let mut string_value_offset = None; + let mut aggregate_value_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 2 { + if name_start.is_none() { + name_start = Some(offset); + } + name_end = Some(offset); + } + if tag.field_number == 3 { + identifier_value_offset = Some(offset); + } + if tag.field_number == 4 { + positive_int_value_offset = Some(offset); + } + if tag.field_number == 5 { + negative_int_value_offset = Some(offset); + } + if tag.field_number == 6 { + double_value_offset = Some(offset); + } + if tag.field_number == 7 { + string_value_offset = Some(offset); + } + if tag.field_number == 8 { + aggregate_value_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_start, + name_end, + identifier_value_offset, + positive_int_value_offset, + negative_int_value_offset, + double_value_offset, + string_value_offset, + aggregate_value_offset, + }) + } + + pub fn name(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.name_start, self.name_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn identifier_value(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .identifier_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn positive_int_value(&self) -> roto_runtime::Result { + let offset = self + .positive_int_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn negative_int_value(&self) -> roto_runtime::Result { + let offset = self + .negative_int_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn double_value(&self) -> roto_runtime::Result { + let offset = self + .double_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(f64::from_le_bytes(bytes.try_into().map_err(|_| { + roto_runtime::RotoError::WireFormatViolation + })?)) + } + + pub fn string_value(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .string_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn aggregate_value(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .aggregate_value_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct UninterpretedOptionBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_written: bool, + identifier_value_written: bool, + positive_int_value_written: bool, + negative_int_value_written: bool, + double_value_written: bool, + string_value_written: bool, + aggregate_value_written: bool, +} + +impl<'b> UninterpretedOptionBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> UninterpretedOptionBuilder<'_> { + UninterpretedOptionBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_written: false, + identifier_value_written: false, + positive_int_value_written: false, + negative_int_value_written: false, + double_value_written: false, + string_value_written: false, + aggregate_value_written: false, + } + } + + pub fn name(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(2, value)?; + self.name_written = true; + Ok(self) + } + + pub fn identifier_value(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.identifier_value_written = true; + Ok(self) + } + + pub fn positive_int_value(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(4, value)?; + self.positive_int_value_written = true; + Ok(self) + } + + pub fn negative_int_value(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.negative_int_value_written = true; + Ok(self) + } + + pub fn double_value(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(6, value)?; + self.double_value_written = true; + Ok(self) + } + + pub fn string_value(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(7, value)?; + self.string_value_written = true; + Ok(self) + } + + pub fn aggregate_value(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(8, value)?; + self.aggregate_value_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &UninterpretedOption<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 2 => self.name_written, + 3 => self.identifier_value_written, + 4 => self.positive_int_value_written, + 5 => self.negative_int_value_written, + 6 => self.double_value_written, + 7 => self.string_value_written, + 8 => self.aggregate_value_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod uninterpreted_option { + pub struct NamePart<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + name_part_offset: Option, + is_extension_offset: Option, + } + + impl<'a> NamePart<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut name_part_offset = None; + let mut is_extension_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + name_part_offset = Some(offset); + } + if tag.field_number == 2 { + is_extension_offset = Some(offset); + } + } + + Ok(Self { + accessor, + name_part_offset, + is_extension_offset, + }) + } + + pub fn name_part(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .name_part_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn is_extension(&self) -> roto_runtime::Result { + let offset = self + .is_extension_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v != 0) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct NamePartBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + name_part_written: bool, + is_extension_written: bool, + } + + impl<'b> NamePartBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> NamePartBuilder<'_> { + NamePartBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + name_part_written: false, + is_extension_written: false, + } + } + + pub fn name_part(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(1, value)?; + self.name_part_written = true; + Ok(self) + } + + pub fn is_extension(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.is_extension_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &NamePart<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.name_part_written, + 2 => self.is_extension_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct FeatureSet<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + field_presence_offset: Option, + enum_type_offset: Option, + repeated_field_encoding_offset: Option, + utf8_validation_offset: Option, + message_encoding_offset: Option, + json_format_offset: Option, + enforce_naming_style_offset: Option, + default_symbol_visibility_offset: Option, + enforce_proto_limits_offset: Option, +} + +impl<'a> FeatureSet<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut field_presence_offset = None; + let mut enum_type_offset = None; + let mut repeated_field_encoding_offset = None; + let mut utf8_validation_offset = None; + let mut message_encoding_offset = None; + let mut json_format_offset = None; + let mut enforce_naming_style_offset = None; + let mut default_symbol_visibility_offset = None; + let mut enforce_proto_limits_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + field_presence_offset = Some(offset); + } + if tag.field_number == 2 { + enum_type_offset = Some(offset); + } + if tag.field_number == 3 { + repeated_field_encoding_offset = Some(offset); + } + if tag.field_number == 4 { + utf8_validation_offset = Some(offset); + } + if tag.field_number == 5 { + message_encoding_offset = Some(offset); + } + if tag.field_number == 6 { + json_format_offset = Some(offset); + } + if tag.field_number == 7 { + enforce_naming_style_offset = Some(offset); + } + if tag.field_number == 8 { + default_symbol_visibility_offset = Some(offset); + } + if tag.field_number == 9 { + enforce_proto_limits_offset = Some(offset); + } + } + + Ok(Self { + accessor, + field_presence_offset, + enum_type_offset, + repeated_field_encoding_offset, + utf8_validation_offset, + message_encoding_offset, + json_format_offset, + enforce_naming_style_offset, + default_symbol_visibility_offset, + enforce_proto_limits_offset, + }) + } + + pub fn field_presence(&self) -> roto_runtime::Result { + let offset = self + .field_presence_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn enum_type(&self) -> roto_runtime::Result { + let offset = self + .enum_type_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn repeated_field_encoding(&self) -> roto_runtime::Result { + let offset = self + .repeated_field_encoding_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn utf8_validation(&self) -> roto_runtime::Result { + let offset = self + .utf8_validation_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn message_encoding(&self) -> roto_runtime::Result { + let offset = self + .message_encoding_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn json_format(&self) -> roto_runtime::Result { + let offset = self + .json_format_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn enforce_naming_style(&self) -> roto_runtime::Result { + let offset = self + .enforce_naming_style_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn default_symbol_visibility(&self) -> roto_runtime::Result { + let offset = self + .default_symbol_visibility_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn enforce_proto_limits(&self) -> roto_runtime::Result { + let offset = self + .enforce_proto_limits_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FeatureSetBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + field_presence_written: bool, + enum_type_written: bool, + repeated_field_encoding_written: bool, + utf8_validation_written: bool, + message_encoding_written: bool, + json_format_written: bool, + enforce_naming_style_written: bool, + default_symbol_visibility_written: bool, + enforce_proto_limits_written: bool, +} + +impl<'b> FeatureSetBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FeatureSetBuilder<'_> { + FeatureSetBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + field_presence_written: false, + enum_type_written: false, + repeated_field_encoding_written: false, + utf8_validation_written: false, + message_encoding_written: false, + json_format_written: false, + enforce_naming_style_written: false, + default_symbol_visibility_written: false, + enforce_proto_limits_written: false, + } + } + + pub fn field_presence(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(1, value)?; + self.field_presence_written = true; + Ok(self) + } + + pub fn enum_type(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(2, value)?; + self.enum_type_written = true; + Ok(self) + } + + pub fn repeated_field_encoding(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.repeated_field_encoding_written = true; + Ok(self) + } + + pub fn utf8_validation(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(4, value)?; + self.utf8_validation_written = true; + Ok(self) + } + + pub fn message_encoding(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.message_encoding_written = true; + Ok(self) + } + + pub fn json_format(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(6, value)?; + self.json_format_written = true; + Ok(self) + } + + pub fn enforce_naming_style(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(7, value)?; + self.enforce_naming_style_written = true; + Ok(self) + } + + pub fn default_symbol_visibility(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(8, value)?; + self.default_symbol_visibility_written = true; + Ok(self) + } + + pub fn enforce_proto_limits(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(9, value)?; + self.enforce_proto_limits_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FeatureSet<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.field_presence_written, + 2 => self.enum_type_written, + 3 => self.repeated_field_encoding_written, + 4 => self.utf8_validation_written, + 5 => self.message_encoding_written, + 6 => self.json_format_written, + 7 => self.enforce_naming_style_written, + 8 => self.default_symbol_visibility_written, + 9 => self.enforce_proto_limits_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod feature_set { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum FieldPresence { + FIELDPRESENCEUNKNOWN = 0, + EXPLICIT = 1, + IMPLICIT = 2, + LEGACYREQUIRED = 3, + } + + impl FieldPresence { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => FieldPresence::FIELDPRESENCEUNKNOWN, + 1 => FieldPresence::EXPLICIT, + 2 => FieldPresence::IMPLICIT, + 3 => FieldPresence::LEGACYREQUIRED, + _ => FieldPresence::FIELDPRESENCEUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum EnumType { + ENUMTYPEUNKNOWN = 0, + OPEN = 1, + CLOSED = 2, + } + + impl EnumType { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => EnumType::ENUMTYPEUNKNOWN, + 1 => EnumType::OPEN, + 2 => EnumType::CLOSED, + _ => EnumType::ENUMTYPEUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum RepeatedFieldEncoding { + REPEATEDFIELDENCODINGUNKNOWN = 0, + PACKED = 1, + EXPANDED = 2, + } + + impl RepeatedFieldEncoding { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => RepeatedFieldEncoding::REPEATEDFIELDENCODINGUNKNOWN, + 1 => RepeatedFieldEncoding::PACKED, + 2 => RepeatedFieldEncoding::EXPANDED, + _ => RepeatedFieldEncoding::REPEATEDFIELDENCODINGUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum Utf8Validation { + UTF8VALIDATIONUNKNOWN = 0, + VERIFY = 2, + NONE = 3, + } + + impl Utf8Validation { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => Utf8Validation::UTF8VALIDATIONUNKNOWN, + 2 => Utf8Validation::VERIFY, + 3 => Utf8Validation::NONE, + _ => Utf8Validation::UTF8VALIDATIONUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum MessageEncoding { + MESSAGEENCODINGUNKNOWN = 0, + LENGTHPREFIXED = 1, + DELIMITED = 2, + } + + impl MessageEncoding { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => MessageEncoding::MESSAGEENCODINGUNKNOWN, + 1 => MessageEncoding::LENGTHPREFIXED, + 2 => MessageEncoding::DELIMITED, + _ => MessageEncoding::MESSAGEENCODINGUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum JsonFormat { + JSONFORMATUNKNOWN = 0, + ALLOW = 1, + LEGACYBESTEFFORT = 2, + } + + impl JsonFormat { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => JsonFormat::JSONFORMATUNKNOWN, + 1 => JsonFormat::ALLOW, + 2 => JsonFormat::LEGACYBESTEFFORT, + _ => JsonFormat::JSONFORMATUNKNOWN, + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum EnforceNamingStyle { + ENFORCENAMINGSTYLEUNKNOWN = 0, + STYLE2024 = 1, + STYLELEGACY = 2, + STYLE2026 = 3, + } + + impl EnforceNamingStyle { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => EnforceNamingStyle::ENFORCENAMINGSTYLEUNKNOWN, + 1 => EnforceNamingStyle::STYLE2024, + 2 => EnforceNamingStyle::STYLELEGACY, + 3 => EnforceNamingStyle::STYLE2026, + _ => EnforceNamingStyle::ENFORCENAMINGSTYLEUNKNOWN, + } + } + } + + pub struct VisibilityFeature<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + } + + impl<'a> VisibilityFeature<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + Ok(Self { accessor }) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct VisibilityFeatureBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + } + + impl<'b> VisibilityFeatureBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> VisibilityFeatureBuilder<'_> { + VisibilityFeatureBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + } + } + + pub fn with(mut self, msg: &VisibilityFeature<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } + + pub mod visibility_feature { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum DefaultSymbolVisibility { + DEFAULTSYMBOLVISIBILITYUNKNOWN = 0, + EXPORTALL = 1, + EXPORTTOPLEVEL = 2, + LOCALALL = 3, + STRICT = 4, + } + + impl DefaultSymbolVisibility { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => DefaultSymbolVisibility::DEFAULTSYMBOLVISIBILITYUNKNOWN, + 1 => DefaultSymbolVisibility::EXPORTALL, + 2 => DefaultSymbolVisibility::EXPORTTOPLEVEL, + 3 => DefaultSymbolVisibility::LOCALALL, + 4 => DefaultSymbolVisibility::STRICT, + _ => DefaultSymbolVisibility::DEFAULTSYMBOLVISIBILITYUNKNOWN, + } + } + } + } + + pub struct ProtoLimitsFeature<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + } + + impl<'a> ProtoLimitsFeature<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + Ok(Self { accessor }) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct ProtoLimitsFeatureBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + } + + impl<'b> ProtoLimitsFeatureBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> ProtoLimitsFeatureBuilder<'_> { + ProtoLimitsFeatureBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + } + } + + pub fn with(mut self, msg: &ProtoLimitsFeature<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } + + pub mod proto_limits_feature { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum EnforceProtoLimits { + PROTOLIMITSUNKNOWN = 0, + LEGACYNOEXPLICITLIMITS = 1, + PROTOLIMITS2026 = 2, + } + + impl EnforceProtoLimits { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => EnforceProtoLimits::PROTOLIMITSUNKNOWN, + 1 => EnforceProtoLimits::LEGACYNOEXPLICITLIMITS, + 2 => EnforceProtoLimits::PROTOLIMITS2026, + _ => EnforceProtoLimits::PROTOLIMITSUNKNOWN, + } + } + } + } +} + +pub struct FeatureSetDefaults<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + defaults_start: Option, + defaults_end: Option, + minimum_edition_offset: Option, + maximum_edition_offset: Option, +} + +impl<'a> FeatureSetDefaults<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut defaults_start = None; + let mut defaults_end = None; + let mut minimum_edition_offset = None; + let mut maximum_edition_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if defaults_start.is_none() { + defaults_start = Some(offset); + } + defaults_end = Some(offset); + } + if tag.field_number == 4 { + minimum_edition_offset = Some(offset); + } + if tag.field_number == 5 { + maximum_edition_offset = Some(offset); + } + } + + Ok(Self { + accessor, + defaults_start, + defaults_end, + minimum_edition_offset, + maximum_edition_offset, + }) + } + + pub fn defaults(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.defaults_start, self.defaults_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn minimum_edition(&self) -> roto_runtime::Result { + let offset = self + .minimum_edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn maximum_edition(&self) -> roto_runtime::Result { + let offset = self + .maximum_edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct FeatureSetDefaultsBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + defaults_written: bool, + minimum_edition_written: bool, + maximum_edition_written: bool, +} + +impl<'b> FeatureSetDefaultsBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FeatureSetDefaultsBuilder<'_> { + FeatureSetDefaultsBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + defaults_written: false, + minimum_edition_written: false, + maximum_edition_written: false, + } + } + + pub fn defaults(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(1, value)?; + self.defaults_written = true; + Ok(self) + } + + pub fn minimum_edition(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(4, value)?; + self.minimum_edition_written = true; + Ok(self) + } + + pub fn maximum_edition(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.maximum_edition_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FeatureSetDefaults<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.defaults_written, + 4 => self.minimum_edition_written, + 5 => self.maximum_edition_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod feature_set_defaults { + pub struct FeatureSetEditionDefault<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + edition_offset: Option, + overridable_features_offset: Option, + fixed_features_offset: Option, + } + + impl<'a> FeatureSetEditionDefault<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut edition_offset = None; + let mut overridable_features_offset = None; + let mut fixed_features_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 3 { + edition_offset = Some(offset); + } + if tag.field_number == 4 { + overridable_features_offset = Some(offset); + } + if tag.field_number == 5 { + fixed_features_offset = Some(offset); + } + } + + Ok(Self { + accessor, + edition_offset, + overridable_features_offset, + fixed_features_offset, + }) + } + + pub fn edition(&self) -> roto_runtime::Result { + let offset = self + .edition_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn overridable_features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .overridable_features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn fixed_features(&self) -> roto_runtime::Result<&'a [u8]> { + let offset = self + .fixed_features_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + Ok(bytes) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct FeatureSetEditionDefaultBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + edition_written: bool, + overridable_features_written: bool, + fixed_features_written: bool, + } + + impl<'b> FeatureSetEditionDefaultBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> FeatureSetEditionDefaultBuilder<'_> { + FeatureSetEditionDefaultBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + edition_written: false, + overridable_features_written: false, + fixed_features_written: false, + } + } + + pub fn edition(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(3, value)?; + self.edition_written = true; + Ok(self) + } + + pub fn overridable_features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(4, value)?; + self.overridable_features_written = true; + Ok(self) + } + + pub fn fixed_features(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(5, value)?; + self.fixed_features_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &FeatureSetEditionDefault<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 3 => self.edition_written, + 4 => self.overridable_features_written, + 5 => self.fixed_features_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct SourceCodeInfo<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + location_start: Option, + location_end: Option, +} + +impl<'a> SourceCodeInfo<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut location_start = None; + let mut location_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if location_start.is_none() { + location_start = Some(offset); + } + location_end = Some(offset); + } + } + + Ok(Self { + accessor, + location_start, + location_end, + }) + } + + pub fn location(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.location_start, self.location_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct SourceCodeInfoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + location_written: bool, +} + +impl<'b> SourceCodeInfoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> SourceCodeInfoBuilder<'_> { + SourceCodeInfoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + location_written: false, + } + } + + pub fn location(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(1, value)?; + self.location_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &SourceCodeInfo<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.location_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod source_code_info { + pub struct Location<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + path_start: Option, + path_end: Option, + span_start: Option, + span_end: Option, + leading_comments_offset: Option, + trailing_comments_offset: Option, + leading_detached_comments_start: Option, + leading_detached_comments_end: Option, + } + + impl<'a> Location<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut path_start = None; + let mut path_end = None; + let mut span_start = None; + let mut span_end = None; + let mut leading_comments_offset = None; + let mut trailing_comments_offset = None; + let mut leading_detached_comments_start = None; + let mut leading_detached_comments_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if path_start.is_none() { + path_start = Some(offset); + } + path_end = Some(offset); + } + if tag.field_number == 2 { + if span_start.is_none() { + span_start = Some(offset); + } + span_end = Some(offset); + } + if tag.field_number == 3 { + leading_comments_offset = Some(offset); + } + if tag.field_number == 4 { + trailing_comments_offset = Some(offset); + } + if tag.field_number == 6 { + if leading_detached_comments_start.is_none() { + leading_detached_comments_start = Some(offset); + } + leading_detached_comments_end = Some(offset); + } + } + + Ok(Self { + accessor, + path_start, + path_end, + span_start, + span_end, + leading_comments_offset, + trailing_comments_offset, + leading_detached_comments_start, + leading_detached_comments_end, + }) + } + + pub fn path(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.path_start, self.path_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn span(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.span_start, self.span_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(2, start, end), + _ => self.accessor.iter_repeated(2), + } + } + + pub fn leading_comments(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .leading_comments_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn trailing_comments(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .trailing_comments_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn leading_detached_comments(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match ( + self.leading_detached_comments_start, + self.leading_detached_comments_end, + ) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(6, start, end), + _ => self.accessor.iter_repeated(6), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct LocationBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + path_written: bool, + span_written: bool, + leading_comments_written: bool, + trailing_comments_written: bool, + leading_detached_comments_written: bool, + } + + impl<'b> LocationBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> LocationBuilder<'_> { + LocationBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + path_written: false, + span_written: false, + leading_comments_written: false, + trailing_comments_written: false, + leading_detached_comments_written: false, + } + } + + pub fn path(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.path_written = true; + Ok(self) + } + + pub fn span(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(2, value)?; + self.span_written = true; + Ok(self) + } + + pub fn leading_comments(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(3, value)?; + self.leading_comments_written = true; + Ok(self) + } + + pub fn trailing_comments(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(4, value)?; + self.trailing_comments_written = true; + Ok(self) + } + + pub fn leading_detached_comments(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(6, value)?; + self.leading_detached_comments_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &Location<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.path_written, + 2 => self.span_written, + 3 => self.leading_comments_written, + 4 => self.trailing_comments_written, + 6 => self.leading_detached_comments_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } +} + +pub struct GeneratedCodeInfo<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + annotation_start: Option, + annotation_end: Option, +} + +impl<'a> GeneratedCodeInfo<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut annotation_start = None; + let mut annotation_end = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if annotation_start.is_none() { + annotation_start = Some(offset); + } + annotation_end = Some(offset); + } + } + + Ok(Self { + accessor, + annotation_start, + annotation_end, + }) + } + + pub fn annotation(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.annotation_start, self.annotation_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } +} + +pub struct GeneratedCodeInfoBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + annotation_written: bool, +} + +impl<'b> GeneratedCodeInfoBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> GeneratedCodeInfoBuilder<'_> { + GeneratedCodeInfoBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + annotation_written: false, + } + } + + pub fn annotation(mut self, value: &[u8]) -> roto_runtime::Result { + self.builder.write_bytes(1, value)?; + self.annotation_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &GeneratedCodeInfo<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.annotation_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } +} + +pub mod generated_code_info { + pub struct Annotation<'a> { + accessor: roto_runtime::ProtoAccessor<'a>, + path_start: Option, + path_end: Option, + source_file_offset: Option, + begin_offset: Option, + end_offset: Option, + semantic_offset: Option, + } + + impl<'a> Annotation<'a> { + pub fn new(data: &'a [u8]) -> roto_runtime::Result { + let accessor = roto_runtime::ProtoAccessor::new(data)?; + let mut path_start = None; + let mut path_end = None; + let mut source_file_offset = None; + let mut begin_offset = None; + let mut end_offset = None; + let mut semantic_offset = None; + for item in accessor.fields() { + let (offset, tag, _) = item?; + if tag.field_number == 1 { + if path_start.is_none() { + path_start = Some(offset); + } + path_end = Some(offset); + } + if tag.field_number == 2 { + source_file_offset = Some(offset); + } + if tag.field_number == 3 { + begin_offset = Some(offset); + } + if tag.field_number == 4 { + end_offset = Some(offset); + } + if tag.field_number == 5 { + semantic_offset = Some(offset); + } + } + + Ok(Self { + accessor, + path_start, + path_end, + source_file_offset, + begin_offset, + end_offset, + semantic_offset, + }) + } + + pub fn path(&self) -> roto_runtime::RepeatedFieldIterator<'a> { + match (self.path_start, self.path_end) { + (Some(start), Some(end)) => self.accessor.iter_repeated_range(1, start, end), + _ => self.accessor.iter_repeated(1), + } + } + + pub fn source_file(&self) -> roto_runtime::Result<&'a str> { + let offset = self + .source_file_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn begin(&self) -> roto_runtime::Result { + let offset = self + .begin_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn end(&self) -> roto_runtime::Result { + let offset = self + .end_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as i32) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn semantic(&self) -> roto_runtime::Result { + let offset = self + .semantic_offset + .ok_or(roto_runtime::RotoError::FieldNotFound)?; + let (bytes, _) = self.accessor.get_value_at(offset)?; + roto_runtime::read_varint(bytes) + .map(|(v, _)| v as u64) + .map_err(|_| roto_runtime::RotoError::WireFormatViolation) + } + + pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { + self.accessor.raw_fields() + } + } + + pub struct AnnotationBuilder<'b> { + builder: roto_runtime::ProtoBuilder<'b>, + path_written: bool, + source_file_written: bool, + begin_written: bool, + end_written: bool, + semantic_written: bool, + } + + impl<'b> AnnotationBuilder<'b> { + pub fn builder(buf: &mut [u8]) -> AnnotationBuilder<'_> { + AnnotationBuilder { + builder: roto_runtime::ProtoBuilder::new(buf), + path_written: false, + source_file_written: false, + begin_written: false, + end_written: false, + semantic_written: false, + } + } + + pub fn path(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(1, value)?; + self.path_written = true; + Ok(self) + } + + pub fn source_file(mut self, value: &str) -> roto_runtime::Result { + self.builder.write_string(2, value)?; + self.source_file_written = true; + Ok(self) + } + + pub fn begin(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(3, value)?; + self.begin_written = true; + Ok(self) + } + + pub fn end(mut self, value: i32) -> roto_runtime::Result { + self.builder.write_int32(4, value)?; + self.end_written = true; + Ok(self) + } + + pub fn semantic(mut self, value: u64) -> roto_runtime::Result { + self.builder.write_varint(5, value)?; + self.semantic_written = true; + Ok(self) + } + + pub fn with(mut self, msg: &Annotation<'_>) -> roto_runtime::Result { + for item in msg.raw_fields() { + let (field_number, raw_bytes) = item?; + let is_written = match field_number { + 1 => self.path_written, + 2 => self.source_file_written, + 3 => self.begin_written, + 4 => self.end_written, + 5 => self.semantic_written, + _ => false, + }; + if !is_written { + self.builder.write_raw(raw_bytes)?; + } + } + Ok(self) + } + + pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { + self.builder.finish() + } + } + + pub mod annotation { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(i32)] + pub enum Semantic { + NONE = 0, + SET = 1, + ALIAS = 2, + } + + impl Semantic { + pub fn from_i32(value: i32) -> Self { + match value { + 0 => Semantic::NONE, + 1 => Semantic::SET, + 2 => Semantic::ALIAS, + _ => Semantic::NONE, + } + } + } + } +} diff --git a/codegen/src/google/protobuf/mod.rs b/codegen/src/google/protobuf/mod.rs new file mode 100644 index 0000000..e4b3346 --- /dev/null +++ b/codegen/src/google/protobuf/mod.rs @@ -0,0 +1,2 @@ +pub mod compiler; +pub mod descriptor; diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs new file mode 100644 index 0000000..8038813 --- /dev/null +++ b/codegen/src/lib.rs @@ -0,0 +1,2 @@ +pub mod generator; +pub mod google; diff --git a/tests/build_generated_code.rs b/codegen/tests/build_generated_code.rs similarity index 71% rename from tests/build_generated_code.rs rename to codegen/tests/build_generated_code.rs index ddffc63..814d91d 100644 --- a/tests/build_generated_code.rs +++ b/codegen/tests/build_generated_code.rs @@ -1,19 +1,14 @@ +use roto_codegen::google::protobuf::compiler::plugin::CodeGeneratorRequest; +use roto_codegen::google::protobuf::descriptor::FileDescriptorSet; use std::fs; use std::process::Command; -use roto::google::protobuf::descriptor::{ - FileDescriptorSet -}; -use roto::google::protobuf::compiler::plugin::{ - CodeGeneratorRequest, -}; #[test] fn test_generated_code_builds() { // 1. Generate Rust code from data/request.bin let request_path = "data/request.bin"; let data = fs::read(request_path).expect("Failed to read request.bin"); - let request = CodeGeneratorRequest::new(&data) - .expect("Failed to parse CodeGeneratorRequest"); + let request = CodeGeneratorRequest::new(&data).expect("Failed to parse CodeGeneratorRequest"); // Mimic the logic from protoc-gen-roto to build a FileDescriptorSet let mut set_buf = Vec::new(); @@ -26,17 +21,20 @@ fn test_generated_code_builds() { // Write length as varint let len = file_data.len() as u64; let mut len_buf = [0u8; 10]; - let len_size = roto::write_varint(len, &mut len_buf).expect("Failed to write varint length"); + let len_size = + roto_runtime::write_varint(len, &mut len_buf).expect("Failed to write varint length"); set_buf.extend_from_slice(&len_buf[..len_size]); // Write data set_buf.extend_from_slice(file_data); } - let set = FileDescriptorSet::new(&set_buf) - .expect("Failed to create FileDescriptorSet"); + let set = FileDescriptorSet::new(&set_buf).expect("Failed to create FileDescriptorSet"); - let generated_files = roto::generator::generate_rust_code(&set, None, false); - assert!(!generated_files.is_empty(), "Generated code should not be empty"); + let generated_files = roto_codegen::generator::generate_rust_code(&set, None, false); + assert!( + !generated_files.is_empty(), + "Generated code should not be empty" + ); // 2. Setup a temporary Cargo project to verify the code builds let root = std::env::current_dir().expect("Failed to get current directory"); @@ -57,9 +55,10 @@ fn test_generated_code_builds() { // 3. Configure the project to depend on the current roto crate let cargo_toml_path = temp_project_dir.join("Cargo.toml"); - let cargo_toml_content = fs::read_to_string(&cargo_toml_path).expect("Failed to read Cargo.toml"); + let cargo_toml_content = + fs::read_to_string(&cargo_toml_path).expect("Failed to read Cargo.toml"); let updated_cargo_toml = format!( - "{}\n\nroto = {{ path = \"..\" }}", + "{}\n\nroto-codegen = {{ path = \"..\" }}\nroto-runtime = {{ path = \"../../runtime\" }}\n\n[workspace]\n", cargo_toml_content ); fs::write(cargo_toml_path, updated_cargo_toml).expect("Failed to write Cargo.toml"); @@ -83,5 +82,8 @@ fn test_generated_code_builds() { .status() .expect("Failed to run cargo build"); - assert!(build_status.success(), "The generated Rust code failed to build in a standalone project!"); + assert!( + build_status.success(), + "The generated Rust code failed to build in a standalone project!" + ); } diff --git a/tests/test_nested_protos.rs b/codegen/tests/test_nested_protos.rs similarity index 66% rename from tests/test_nested_protos.rs rename to codegen/tests/test_nested_protos.rs index 78aefa3..53688ab 100644 --- a/tests/test_nested_protos.rs +++ b/codegen/tests/test_nested_protos.rs @@ -1,7 +1,5 @@ -use roto::generator::generate_rust_code; -use roto::google::protobuf::descriptor::{ - FileDescriptorSet -}; +use roto_codegen::generator::generate_rust_code; +use roto_codegen::google::protobuf::descriptor::FileDescriptorSet; use std::fs; #[test] @@ -18,8 +16,9 @@ fn test_nested_proto_generation_contains_modules() { // but request.bin is usually a CodeGeneratorRequest. // Let's use the same logic as build_generated_code.rs to get a FileDescriptorSet - let request = roto::google::protobuf::compiler::plugin::CodeGeneratorRequest::new(&data) - .expect("Failed to parse CodeGeneratorRequest"); + let request = + roto_codegen::google::protobuf::compiler::plugin::CodeGeneratorRequest::new(&data) + .expect("Failed to parse CodeGeneratorRequest"); let mut set_buf = Vec::new(); for file_res in request.proto_file() { @@ -27,7 +26,8 @@ fn test_nested_proto_generation_contains_modules() { set_buf.push(10); let len = file_data.len() as u64; let mut len_buf = [0u8; 10]; - let len_size = roto::write_varint(len, &mut len_buf).expect("Failed to write varint length"); + let len_size = + roto_runtime::write_varint(len, &mut len_buf).expect("Failed to write varint length"); set_buf.extend_from_slice(&len_buf[..len_size]); set_buf.extend_from_slice(file_data); } @@ -35,12 +35,21 @@ fn test_nested_proto_generation_contains_modules() { let generated_files = generate_rust_code(&set, None, false); - let all_code: String = generated_files.into_iter().map(|(_, content)| content).collect(); + let all_code: String = generated_files + .into_iter() + .map(|(_, content)| content) + .collect(); println!("Generated Code:\n{}", all_code); // We want to see if any message has a nested module. // Since we don't know exactly what's in request.bin, we'll look for ANY 'pub mod' inside the generated code // that isn't at the top level (though the generator puts them inside the message definition). - assert!(all_code.contains("pub mod "), "Generated code should contain at least one nested module for nested types"); - assert!(all_code.contains("pub struct "), "Generated code should contain structs"); + assert!( + all_code.contains("pub mod "), + "Generated code should contain at least one nested module for nested types" + ); + assert!( + all_code.contains("pub struct "), + "Generated code should contain structs" + ); } diff --git a/tests/test_with_method.rs b/codegen/tests/test_with_method.rs similarity index 89% rename from tests/test_with_method.rs rename to codegen/tests/test_with_method.rs index 7c8dfd9..d211387 100644 --- a/tests/test_with_method.rs +++ b/codegen/tests/test_with_method.rs @@ -1,6 +1,6 @@ -use roto::generator::generate_rust_code; -use roto::google::protobuf::compiler::plugin::CodeGeneratorRequest; -use roto::google::protobuf::descriptor::FileDescriptorSet; +use roto_codegen::generator::generate_rust_code; +use roto_codegen::google::protobuf::compiler::plugin::CodeGeneratorRequest; +use roto_codegen::google::protobuf::descriptor::FileDescriptorSet; use std::fs; fn load_generated_code() -> String { @@ -13,7 +13,7 @@ fn load_generated_code() -> String { set_buf.push(10u8); let len = file_data.len() as u64; let mut len_buf = [0u8; 10]; - let len_size = roto::write_varint(len, &mut len_buf).unwrap(); + let len_size = roto_runtime::write_varint(len, &mut len_buf).unwrap(); set_buf.extend_from_slice(&len_buf[..len_size]); set_buf.extend_from_slice(file_data); } diff --git a/protos/Cargo.toml b/protos/Cargo.toml new file mode 100644 index 0000000..e416ccf --- /dev/null +++ b/protos/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "protos" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/protos/src/lib.rs b/protos/src/lib.rs new file mode 100644 index 0000000..98dd882 --- /dev/null +++ b/protos/src/lib.rs @@ -0,0 +1,3 @@ +pub fn hello() { + println!("Hello from protos!"); +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml new file mode 100644 index 0000000..29c59cd --- /dev/null +++ b/runtime/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "roto-runtime" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/runtime/data/.gitignore b/runtime/data/.gitignore new file mode 100644 index 0000000..f2e59b9 --- /dev/null +++ b/runtime/data/.gitignore @@ -0,0 +1 @@ +bench/ diff --git a/runtime/data/descriptor.desc b/runtime/data/descriptor.desc new file mode 100644 index 0000000..8378d0b Binary files /dev/null and b/runtime/data/descriptor.desc differ diff --git a/runtime/data/request.bin b/runtime/data/request.bin new file mode 100644 index 0000000..7afcaaa Binary files /dev/null and b/runtime/data/request.bin differ diff --git a/runtime/data/test_data.pb b/runtime/data/test_data.pb new file mode 100644 index 0000000..f010831 Binary files /dev/null and b/runtime/data/test_data.pb differ diff --git a/runtime/data/test_data.textproto b/runtime/data/test_data.textproto new file mode 100644 index 0000000..5dc54ba --- /dev/null +++ b/runtime/data/test_data.textproto @@ -0,0 +1,39 @@ +d_val: 3.1415926535 +f_val: 2.71828 +i32_val: 42 +i64_val: 123456789012345 +u32_val: 1000 +u64_val: 18446744073709551615 +si32_val: -42 +si64_val: -123456789012345 +fx32_val: 123456 +fx64_val: 1234567890123456789 +sfx32_val: -123456 +sfx64_val: -1234567890123456789 +b_val: true +s_val: "Hello Roto!" +bytes_val: "SGVsbG8gUm90byE=" +status: ACTIVE +repeated_i32: 1 +repeated_i32: 2 +repeated_i32: 3 +repeated_i32: 4 +repeated_i32: 5 +repeated_string: "one" +repeated_string: "two" +repeated_string: "three" +repeated_nested { + id: 101 + name: "Nested 1" + active: true +} +repeated_nested { + id: 102 + name: "Nested 2" + active: false +} +single_nested { + id: 200 + name: "Single Nested" + active: true +} diff --git a/runtime/data/test_types.desc b/runtime/data/test_types.desc new file mode 100644 index 0000000..6ff3fb1 Binary files /dev/null and b/runtime/data/test_types.desc differ diff --git a/runtime/data/test_types.proto b/runtime/data/test_types.proto new file mode 100644 index 0000000..c4b4a9a --- /dev/null +++ b/runtime/data/test_types.proto @@ -0,0 +1,53 @@ +syntax = "proto3"; + +package roto.test; + +// A comprehensive message containing all primitive types and complex structures +// to test the proto-to-rust codegen and runtime accessors. +message ComplexMessage { + // --- Floating Point --- + double d_val = 1; + float f_val = 2; + + // --- Integers (Variable Length) --- + int32 i32_val = 3; + int64 i64_val = 4; + uint32 u32_val = 5; + uint64 u64_val = 6; + sint32 si32_val = 7; + sint64 si64_val = 8; + + // --- Integers (Fixed Length) --- + fixed32 fx32_val = 9; + fixed64 fx64_val = 10; + sfixed32 sfx32_val = 11; + sfixed64 sfx64_val = 12; + + // --- Other Primitives --- + bool b_val = 13; + string s_val = 14; + bytes bytes_val = 15; + + // --- Enumerations --- + enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; + DELETED = 3; + } + Status status = 16; + + // --- Repeated Fields --- + // Testing packed primitives and non-packed types + repeated int32 repeated_i32 = 17; + repeated string repeated_string = 18; + repeated NestedMessage repeated_nested = 19; + + // --- Nested Messages --- + message NestedMessage { + int32 id = 1; + string name = 2; + bool active = 3; + } + NestedMessage single_nested = 20; +} diff --git a/src/lib.rs b/runtime/src/lib.rs similarity index 99% rename from src/lib.rs rename to runtime/src/lib.rs index e289ddf..0c71a0f 100644 --- a/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,10 +1,3 @@ -pub mod generator; -pub mod google; -pub mod hackers; -// Uncomment this to check if the code compiles -// #[path = "../proto/google/protobuf/descriptor.rs"] -// pub mod descriptor; - use std::fmt; #[derive(Debug, PartialEq, Eq)] diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}