Skip to content

Commit aaf7efd

Browse files
authored
mesh_protobuf: Only deduplicate descriptors by package and name (#1821)
As a new warning in Rust 1.89 points out, comparisons of function pointers are unreliable (https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html). The derive of PartialEq on a type containing a function pointer will produce such a comparison, triggering this warning. Instead of deriving the trait and inserting MessageDescriptors into a HashMap, just use their package and name as a deduplication key, under the assumption that nobody would declare two different types with the same package and name.
1 parent 0460c27 commit aaf7efd

File tree

2 files changed

+31
-29
lines changed

2 files changed

+31
-29
lines changed

support/mesh/mesh_protobuf/src/protofile/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub enum MessageDescription<'a> {
4646

4747
/// A type URL, used in [`ProtobufAny`](super::message::ProtobufAny) (which
4848
/// shares an encoding with `google.protobuf.Any`).
49-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
49+
#[derive(Debug, Copy, Clone)]
5050
pub struct TypeUrl<'a> {
5151
package: &'a str,
5252
name: &'a str,
@@ -106,21 +106,21 @@ where
106106
}
107107

108108
/// The description of a field type.
109-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
109+
#[derive(Debug, Copy, Clone)]
110110
pub struct FieldType<'a> {
111111
kind: FieldKind<'a>,
112112
sequence_type: Option<SequenceType<'a>>,
113113
annotation: &'a str,
114114
}
115115

116-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
116+
#[derive(Debug, Copy, Clone)]
117117
enum SequenceType<'a> {
118118
Optional,
119119
Repeated,
120120
Map(&'a str),
121121
}
122122

123-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
123+
#[derive(Debug, Copy, Clone)]
124124
enum FieldKind<'a> {
125125
Builtin(&'a str),
126126
Local(&'a str),
@@ -291,7 +291,7 @@ impl<'a> FieldType<'a> {
291291
}
292292

293293
/// A descriptor for a message field.
294-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
294+
#[derive(Debug, Copy, Clone)]
295295
pub struct FieldDescriptor<'a> {
296296
field_type: FieldType<'a>,
297297
field_number: u32,
@@ -317,7 +317,7 @@ impl<'a> FieldDescriptor<'a> {
317317
}
318318

319319
/// A description of a protobuf `oneof`.
320-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
320+
#[derive(Debug, Copy, Clone)]
321321
pub struct OneofDescriptor<'a> {
322322
name: &'a str,
323323
variants: &'a [FieldDescriptor<'a>],
@@ -331,7 +331,7 @@ impl<'a> OneofDescriptor<'a> {
331331
}
332332

333333
/// A message descriptor.
334-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
334+
#[derive(Debug, Copy, Clone)]
335335
pub struct MessageDescriptor<'a> {
336336
comment: &'a str,
337337
name: &'a str,
@@ -361,7 +361,7 @@ impl<'a> MessageDescriptor<'a> {
361361

362362
/// A message descriptor for a message rooted directly in a package (and not
363363
/// nested in another message type).
364-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
364+
#[derive(Debug, Copy, Clone)]
365365
pub struct TopLevelDescriptor<'a> {
366366
package: &'a str,
367367
message: &'a MessageDescriptor<'a>,

support/mesh/mesh_protobuf/src/protofile/writer.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ use crate::protofile::MessageDescription;
1515
use crate::protofile::SequenceType;
1616
use alloc::borrow::Cow;
1717
use alloc::boxed::Box;
18+
use alloc::collections::VecDeque;
1819
use alloc::format;
1920
use alloc::string::String;
2021
use alloc::vec::Vec;
2122
use heck::ToUpperCamelCase;
22-
use std::collections::HashSet;
23+
use std::collections::HashMap;
2324
use std::io;
2425
use std::io::Write;
2526
use std::path::Path;
@@ -44,8 +45,6 @@ impl<'a> DescriptorWriter<'a> {
4445

4546
// Sort the descriptors to get a consistent order from run to run and build to build.
4647
descriptors.sort_by_key(|desc| (desc.package, desc.message.name));
47-
// Deduplicate by package and name. TODO: ensure duplicates match.
48-
descriptors.dedup_by_key(|desc| (desc.package, desc.message.name));
4948

5049
Self {
5150
descriptors,
@@ -188,34 +187,39 @@ impl Write for PackageWriter<'_, '_> {
188187
fn referenced_descriptors<'a>(
189188
descriptors: impl IntoIterator<Item = &'a MessageDescription<'a>>,
190189
) -> Vec<&'a TopLevelDescriptor<'a>> {
190+
// Deduplicate by package and name. TODO: ensure duplicates match.
191191
let mut descriptors =
192-
Vec::from_iter(descriptors.into_iter().copied().filter_map(|d| match d {
193-
MessageDescription::Internal(tld) => Some(tld),
192+
HashMap::from_iter(descriptors.into_iter().copied().filter_map(|d| match d {
193+
MessageDescription::Internal(tld) => Some(((tld.package, tld.message.name), tld)),
194194
MessageDescription::External { .. } => None,
195195
}));
196-
let mut inserted = HashSet::from_iter(descriptors.iter().copied());
196+
197+
let mut queue = VecDeque::from_iter(descriptors.values().copied());
197198

198199
fn process_field_type<'a>(
199200
field_type: &FieldType<'a>,
200-
descriptors: &mut Vec<&'a TopLevelDescriptor<'a>>,
201-
inserted: &mut HashSet<&'a TopLevelDescriptor<'a>>,
201+
descriptors: &mut HashMap<(&'a str, &'a str), &'a TopLevelDescriptor<'a>>,
202+
queue: &mut VecDeque<&'a TopLevelDescriptor<'a>>,
202203
) {
203204
match field_type.kind {
204205
FieldKind::Message(tld) => {
205206
if let MessageDescription::Internal(tld) = tld() {
206-
if inserted.insert(tld) {
207-
descriptors.push(tld);
207+
if descriptors
208+
.insert((tld.package, tld.message.name), tld)
209+
.is_none()
210+
{
211+
queue.push_back(tld);
208212
}
209213
}
210214
}
211215
FieldKind::Tuple(tys) => {
212216
for ty in tys {
213-
process_field_type(ty, descriptors, inserted);
217+
process_field_type(ty, descriptors, queue);
214218
}
215219
}
216220
FieldKind::KeyValue(tys) => {
217221
for ty in tys {
218-
process_field_type(ty, descriptors, inserted);
222+
process_field_type(ty, descriptors, queue);
219223
}
220224
}
221225
FieldKind::Builtin(_) | FieldKind::Local(_) | FieldKind::External { .. } => {}
@@ -224,28 +228,26 @@ fn referenced_descriptors<'a>(
224228

225229
fn process_message<'a>(
226230
message: &MessageDescriptor<'a>,
227-
descriptors: &mut Vec<&'a TopLevelDescriptor<'a>>,
228-
inserted: &mut HashSet<&'a TopLevelDescriptor<'a>>,
231+
descriptors: &mut HashMap<(&'a str, &'a str), &'a TopLevelDescriptor<'a>>,
232+
queue: &mut VecDeque<&'a TopLevelDescriptor<'a>>,
229233
) {
230234
for field in message
231235
.fields
232236
.iter()
233237
.chain(message.oneofs.iter().flat_map(|oneof| oneof.variants))
234238
{
235-
process_field_type(&field.field_type, descriptors, inserted);
239+
process_field_type(&field.field_type, descriptors, queue);
236240
}
237241
for inner in message.messages {
238-
process_message(inner, descriptors, inserted);
242+
process_message(inner, descriptors, queue);
239243
}
240244
}
241245

242-
let mut i = 0;
243-
while let Some(&tld) = descriptors.get(i) {
244-
process_message(tld.message, &mut descriptors, &mut inserted);
245-
i += 1;
246+
while let Some(tld) = queue.pop_front() {
247+
process_message(tld.message, &mut descriptors, &mut queue);
246248
}
247249

248-
descriptors
250+
descriptors.values().copied().collect()
249251
}
250252

251253
fn package_proto_file(package: &str) -> String {

0 commit comments

Comments
 (0)