Add Builder::with for updating messages

Allow creating a new message based on an existing one, overriding
specific fields while copying the remaining original fields.
This commit is contained in:
2026-05-04 20:11:54 -07:00
parent 05e4c275bb
commit 04ef952a58
5 changed files with 1723 additions and 13 deletions
+250
View File
@@ -70,41 +70,78 @@ exploit_count_offset,
crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation)
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct ToolBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
name_written: bool,
version_written: bool,
payload_written: bool,
is_active_written: bool,
exploit_count_written: bool,
}
impl<'b> ToolBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> ToolBuilder<'_> {
ToolBuilder {
builder: crate::ProtoBuilder::new(buf),
name_written: false,
version_written: false,
payload_written: false,
is_active_written: false,
exploit_count_written: false,
}
}
pub fn name(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.name_written = true;
Ok(self)
}
pub fn version(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(2, value)?;
self.version_written = true;
Ok(self)
}
pub fn payload(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(3, value)?;
self.payload_written = true;
Ok(self)
}
pub fn is_active(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(4, value)?;
self.is_active_written = true;
Ok(self)
}
pub fn exploit_count(mut self, value: i32) -> crate::Result<Self> {
self.builder.write_int32(5, value)?;
self.exploit_count_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Tool<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.name_written,
2 => self.version_written,
3 => self.payload_written,
4 => self.is_active_written,
5 => self.exploit_count_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}
@@ -179,41 +216,78 @@ session_key_offset,
Ok(bytes)
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct ConnectionBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
host_written: bool,
port_written: bool,
encrypted_written: bool,
bandwidth_bps_written: bool,
session_key_written: bool,
}
impl<'b> ConnectionBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> ConnectionBuilder<'_> {
ConnectionBuilder {
builder: crate::ProtoBuilder::new(buf),
host_written: false,
port_written: false,
encrypted_written: false,
bandwidth_bps_written: false,
session_key_written: false,
}
}
pub fn host(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.host_written = true;
Ok(self)
}
pub fn port(mut self, value: i32) -> crate::Result<Self> {
self.builder.write_int32(2, value)?;
self.port_written = true;
Ok(self)
}
pub fn encrypted(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(3, value)?;
self.encrypted_written = true;
Ok(self)
}
pub fn bandwidth_bps(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(4, value)?;
self.bandwidth_bps_written = true;
Ok(self)
}
pub fn session_key(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(5, value)?;
self.session_key_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Connection<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.host_written,
2 => self.port_written,
3 => self.encrypted_written,
4 => self.bandwidth_bps_written,
5 => self.session_key_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}
@@ -340,61 +414,114 @@ active_connection_offset,
Ok(bytes)
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct HackerBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
handle_written: bool,
real_name_written: bool,
age_written: bool,
skill_level_written: bool,
is_elite_written: bool,
crew_id_written: bool,
exploits_written: bool,
tools_written: bool,
active_connection_written: bool,
}
impl<'b> HackerBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> HackerBuilder<'_> {
HackerBuilder {
builder: crate::ProtoBuilder::new(buf),
handle_written: false,
real_name_written: false,
age_written: false,
skill_level_written: false,
is_elite_written: false,
crew_id_written: false,
exploits_written: false,
tools_written: false,
active_connection_written: false,
}
}
pub fn handle(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.handle_written = true;
Ok(self)
}
pub fn real_name(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(2, value)?;
self.real_name_written = true;
Ok(self)
}
pub fn age(mut self, value: i32) -> crate::Result<Self> {
self.builder.write_int32(3, value)?;
self.age_written = true;
Ok(self)
}
pub fn skill_level(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(4, value)?;
self.skill_level_written = true;
Ok(self)
}
pub fn is_elite(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(5, value)?;
self.is_elite_written = true;
Ok(self)
}
pub fn crew_id(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(6, value)?;
self.crew_id_written = true;
Ok(self)
}
pub fn exploits(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(7, value)?;
self.exploits_written = true;
Ok(self)
}
pub fn tools(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(8, value)?;
self.tools_written = true;
Ok(self)
}
pub fn active_connection(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(9, value)?;
self.active_connection_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Hacker<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.handle_written,
2 => self.real_name_written,
3 => self.age_written,
4 => self.skill_level_written,
5 => self.is_elite_written,
6 => self.crew_id_written,
7 => self.exploits_written,
8 => self.tools_written,
9 => self.active_connection_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}
@@ -485,46 +612,87 @@ targets_start, targets_end,
}
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct WormBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
name_written: bool,
variant_written: bool,
size_bytes_written: bool,
payload_written: bool,
polymorphic_written: bool,
targets_written: bool,
}
impl<'b> WormBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> WormBuilder<'_> {
WormBuilder {
builder: crate::ProtoBuilder::new(buf),
name_written: false,
variant_written: false,
size_bytes_written: false,
payload_written: false,
polymorphic_written: false,
targets_written: false,
}
}
pub fn name(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.name_written = true;
Ok(self)
}
pub fn variant(mut self, value: i32) -> crate::Result<Self> {
self.builder.write_int32(2, value)?;
self.variant_written = true;
Ok(self)
}
pub fn size_bytes(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(3, value)?;
self.size_bytes_written = true;
Ok(self)
}
pub fn payload(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(4, value)?;
self.payload_written = true;
Ok(self)
}
pub fn polymorphic(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(5, value)?;
self.polymorphic_written = true;
Ok(self)
}
pub fn targets(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(6, value)?;
self.targets_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Worm<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.name_written,
2 => self.variant_written,
3 => self.size_bytes_written,
4 => self.payload_written,
5 => self.polymorphic_written,
6 => self.targets_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}
@@ -651,61 +819,114 @@ severity_offset,
crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation)
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct OperationBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
codename_written: bool,
target_corp_written: bool,
timestamp_written: bool,
successful_written: bool,
stolen_data_written: bool,
crew_written: bool,
worm_written: bool,
log_entries_written: bool,
severity_written: bool,
}
impl<'b> OperationBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> OperationBuilder<'_> {
OperationBuilder {
builder: crate::ProtoBuilder::new(buf),
codename_written: false,
target_corp_written: false,
timestamp_written: false,
successful_written: false,
stolen_data_written: false,
crew_written: false,
worm_written: false,
log_entries_written: false,
severity_written: false,
}
}
pub fn codename(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.codename_written = true;
Ok(self)
}
pub fn target_corp(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(2, value)?;
self.target_corp_written = true;
Ok(self)
}
pub fn timestamp(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(3, value)?;
self.timestamp_written = true;
Ok(self)
}
pub fn successful(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(4, value)?;
self.successful_written = true;
Ok(self)
}
pub fn stolen_data(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(5, value)?;
self.stolen_data_written = true;
Ok(self)
}
pub fn crew(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(6, value)?;
self.crew_written = true;
Ok(self)
}
pub fn worm(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(7, value)?;
self.worm_written = true;
Ok(self)
}
pub fn log_entries(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(8, value)?;
self.log_entries_written = true;
Ok(self)
}
pub fn severity(mut self, value: i32) -> crate::Result<Self> {
self.builder.write_int32(9, value)?;
self.severity_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Operation<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.codename_written,
2 => self.target_corp_written,
3 => self.timestamp_written,
4 => self.successful_written,
5 => self.stolen_data_written,
6 => self.crew_written,
7 => self.worm_written,
8 => self.log_entries_written,
9 => self.severity_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}
@@ -766,31 +987,60 @@ total_bytes_stolen_offset,
crate::read_varint(bytes).map(|(v, _)| v as i32).map_err(|_| crate::RotoError::WireFormatViolation)
}
pub fn raw_fields(&self) -> crate::RawFieldIterator<'a> {
self.accessor.raw_fields()
}
}
pub struct CampaignBuilder<'b> {
builder: crate::ProtoBuilder<'b>,
name_written: bool,
operations_written: bool,
total_bytes_stolen_written: bool,
}
impl<'b> CampaignBuilder<'b> {
pub fn builder(buf: &mut [u8]) -> CampaignBuilder<'_> {
CampaignBuilder {
builder: crate::ProtoBuilder::new(buf),
name_written: false,
operations_written: false,
total_bytes_stolen_written: false,
}
}
pub fn name(mut self, value: &str) -> crate::Result<Self> {
self.builder.write_string(1, value)?;
self.name_written = true;
Ok(self)
}
pub fn operations(mut self, value: &[u8]) -> crate::Result<Self> {
self.builder.write_bytes(2, value)?;
self.operations_written = true;
Ok(self)
}
pub fn total_bytes_stolen(mut self, value: u64) -> crate::Result<Self> {
self.builder.write_varint(3, value)?;
self.total_bytes_stolen_written = true;
Ok(self)
}
pub fn with(mut self, msg: &Campaign<'_>) -> crate::Result<Self> {
for item in msg.raw_fields() {
let (field_number, raw_bytes) = item?;
let is_written = match field_number {
1 => self.name_written,
2 => self.operations_written,
3 => self.total_bytes_stolen_written,
_ => false,
};
if !is_written {
self.builder.write_raw(raw_bytes)?;
}
}
Ok(self)
}