Skip to content

Commit e5fabe2

Browse files
feat: Add OneofDescriptor::is_synthetic (#175)
1 parent 6d9e8cb commit e5fabe2

File tree

23 files changed

+164
-141
lines changed

23 files changed

+164
-141
lines changed

prost-reflect-build/src/lib.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,10 @@ impl Builder {
152152
let descriptor = DescriptorPool::decode(buf.as_ref()).expect("Invalid file descriptor");
153153

154154
let pool_attribute = if let Some(descriptor_pool) = &self.descriptor_pool_expr {
155-
format!(
156-
r#"#[prost_reflect(descriptor_pool = "{}")]"#,
157-
descriptor_pool,
158-
)
155+
format!(r#"#[prost_reflect(descriptor_pool = "{descriptor_pool}")]"#,)
159156
} else if let Some(file_descriptor_set_bytes) = &self.file_descriptor_set_bytes_expr {
160157
format!(
161-
r#"#[prost_reflect(file_descriptor_set_bytes = "{}")]"#,
162-
file_descriptor_set_bytes,
158+
r#"#[prost_reflect(file_descriptor_set_bytes = "{file_descriptor_set_bytes}")]"#,
163159
)
164160
} else {
165161
return Err(io::Error::other(
@@ -173,7 +169,7 @@ impl Builder {
173169
.type_attribute(full_name, "#[derive(::prost_reflect::ReflectMessage)]")
174170
.type_attribute(
175171
full_name,
176-
format!(r#"#[prost_reflect(message_name = "{}")]"#, full_name,),
172+
format!(r#"#[prost_reflect(message_name = "{full_name}")]"#),
177173
)
178174
.type_attribute(full_name, &pool_attribute);
179175
}

prost-reflect-conformance-tests/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ fn main() -> Result<()> {
1919
}
2020

2121
let version = git_describe(&src_dir)?;
22-
let protobuf_dir = &out_dir.join(format!("protobuf-{}", version));
22+
let protobuf_dir = &out_dir.join(format!("protobuf-{version}"));
2323

2424
if !protobuf_dir.exists() {
25-
let build_dir = &out_dir.join(format!("build-protobuf-{}", version));
25+
let build_dir = &out_dir.join(format!("build-protobuf-{version}"));
2626
fs::create_dir_all(build_dir).expect("failed to create build directory");
2727

2828
let tempdir = tempfile::Builder::new()

prost-reflect-conformance-tests/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn main() -> io::Result<()> {
3737

3838
let result = match ConformanceRequest::decode(&*bytes) {
3939
Ok(request) => handle_request(request),
40-
Err(error) => conformance_response::Result::ParseError(format!("{:?}", error)),
40+
Err(error) => conformance_response::Result::ParseError(format!("{error:?}")),
4141
};
4242

4343
let response = ConformanceResponse {

prost-reflect-tests/src/arbitrary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn mask() -> impl Strategy<Value = FieldMask> {
6868
let mut parts = parts.into_iter();
6969
let mut path = parts.next().unwrap();
7070
for part in parts {
71-
write!(path, ".{}", part).unwrap();
71+
write!(path, ".{part}").unwrap();
7272
}
7373
path
7474
})

prost-reflect-tests/src/desc.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,35 +243,35 @@ fn test_debug_impls() {
243243
let _ = format!("{:?}", test_file_descriptor());
244244

245245
for service in test_file_descriptor().services() {
246-
let _ = format!("{:?}", service);
246+
let _ = format!("{service:?}");
247247
for method in service.methods() {
248-
let _ = format!("{:?}", method);
248+
let _ = format!("{method:?}");
249249
}
250250
}
251251

252252
for file in test_file_descriptor().files() {
253-
let _ = format!("{:?}", file);
253+
let _ = format!("{file:?}");
254254
}
255255

256256
for message in test_file_descriptor().all_messages() {
257-
let _ = format!("{:?}", message);
257+
let _ = format!("{message:?}");
258258
for field in message.fields() {
259-
let _ = format!("{:?}", field);
259+
let _ = format!("{field:?}");
260260
}
261261
for oneof in message.oneofs() {
262-
let _ = format!("{:?}", oneof);
262+
let _ = format!("{oneof:?}");
263263
}
264264
}
265265

266266
for enum_ in test_file_descriptor().all_enums() {
267-
let _ = format!("{:?}", enum_);
267+
let _ = format!("{enum_:?}");
268268
for value in enum_.values() {
269-
let _ = format!("{:?}", value);
269+
let _ = format!("{value:?}");
270270
}
271271
}
272272

273273
for extension in test_file_descriptor().all_extensions() {
274-
let _ = format!("{:?}", extension);
274+
let _ = format!("{extension:?}");
275275
}
276276
}
277277

@@ -785,3 +785,33 @@ fn message_take_fields() {
785785
assert_eq!(dynamic_message.fields_mut().count(), 0);
786786
assert_eq!(dynamic_message.extensions_mut().count(), 0);
787787
}
788+
789+
#[test]
790+
fn oneof_not_synthetic() {
791+
let message_desc = test_file_descriptor()
792+
.get_message_by_name("test.MessageWithOneof")
793+
.unwrap();
794+
795+
assert_eq!(message_desc.oneofs().len(), 1);
796+
797+
let oneof_desc = message_desc.oneofs().next().unwrap();
798+
assert_eq!(oneof_desc.name(), "test_oneof");
799+
assert!(!oneof_desc.is_synthetic());
800+
}
801+
802+
#[test]
803+
fn proto3_optional_field() {
804+
let message_desc = test_file_descriptor()
805+
.get_message_by_name("test.MessageWithOptionalEnum")
806+
.unwrap();
807+
let field_desc = message_desc.get_field_by_name("optional_enum").unwrap();
808+
let oneof_desc = field_desc.containing_oneof().unwrap();
809+
810+
assert!(field_desc.supports_presence());
811+
assert_eq!(oneof_desc.name(), "_optional_enum");
812+
assert!(oneof_desc.is_synthetic());
813+
assert!(oneof_desc.fields().eq([field_desc.clone()]));
814+
815+
assert_eq!(message_desc.oneofs().len(), 1);
816+
assert!(message_desc.oneofs().eq([oneof_desc.clone()]));
817+
}

prost-reflect-tests/src/test.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ message MessageWithOneof {
8989
}
9090
}
9191

92+
message MessageWithOptionalEnum {
93+
enum OptionalEnum {
94+
DEFAULT = 0;
95+
}
96+
97+
optional OptionalEnum optional_enum = 1;
98+
}
99+
92100
message Point {
93101
int32 latitude = 1;
94102
int32 longitude = 2;

prost-reflect/src/descriptor/api.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,16 @@ impl OneofDescriptor {
16101610
})
16111611
}
16121612

1613+
/// Returns `true` if this is a synthetic oneof generated to support proto3 optional semantics.
1614+
///
1615+
/// If `true`, then [`fields`](OneofDescriptor::fields) will yield exactly one field, for which [`FieldDescriptorProto::proto3_optional`] returns true.
1616+
pub fn is_synthetic(&self) -> bool {
1617+
self.fields().len() == 1
1618+
&& self
1619+
.fields()
1620+
.all(|f| f.field_descriptor_proto().proto3_optional())
1621+
}
1622+
16131623
fn inner(&self) -> &OneofDescriptorInner {
16141624
&self.message.inner().oneofs[self.index as usize]
16151625
}
@@ -1882,7 +1892,7 @@ fn join_name<'a>(namespace: &str, name: &'a str) -> Cow<'a, str> {
18821892
if namespace.is_empty() {
18831893
Cow::Borrowed(name)
18841894
} else {
1885-
Cow::Owned(format!("{}.{}", namespace, name))
1895+
Cow::Owned(format!("{namespace}.{name}"))
18861896
}
18871897
}
18881898

prost-reflect/src/descriptor/build/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ impl<'a, 'b> ResolveNameResult<'a, 'b> {
263263
join_path(found_path1, found_path2),
264264
),
265265
help: Some(format!(
266-
"'{}' is defined in '{}', which is not imported by '{}'",
267-
name, dep_name, root_name
266+
"'{name}' is defined in '{dep_name}', which is not imported by '{root_name}'"
268267
)),
269268
name: name.into_owned(),
270269
})
@@ -341,7 +340,7 @@ fn resolve_relative_name<'a, 'b>(
341340
for candidate_parent in resolve_relative_candidate_parents(scope) {
342341
let candidate = match candidate_parent {
343342
"" => Cow::Borrowed(relative_first_part),
344-
_ => Cow::Owned(format!("{}.{}", candidate_parent, relative_first_part)),
343+
_ => Cow::Owned(format!("{candidate_parent}.{relative_first_part}")),
345344
};
346345

347346
if relative_first_part.len() == relative_name.len() {
@@ -358,7 +357,7 @@ fn resolve_relative_name<'a, 'b>(
358357
Some(def) if def.kind.is_parent() => {
359358
let candidate_full = match candidate_parent {
360359
"" => Cow::Borrowed(relative_name),
361-
_ => Cow::Owned(format!("{}.{}", candidate_parent, relative_name)),
360+
_ => Cow::Owned(format!("{candidate_parent}.{relative_name}")),
362361
};
363362

364363
let res =

prost-reflect/src/descriptor/build/options.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ fn set_file_option(file: &mut FileDescriptorProto, path: &[i32], encoded: &[u8])
744744
let value = &mut service.method[path[3] as usize];
745745
value.options = Some(Options::decode(encoded).unwrap());
746746
}
747-
p => panic!("unknown path element {}", p),
747+
p => panic!("unknown path element {p}"),
748748
}
749749
}
750750
tag::file::EXTENSION => {
@@ -753,7 +753,7 @@ fn set_file_option(file: &mut FileDescriptorProto, path: &[i32], encoded: &[u8])
753753
let field = &mut file.extension[path[1] as usize];
754754
field.options = Some(Options::decode(encoded).unwrap());
755755
}
756-
p => panic!("unknown path element {}", p),
756+
p => panic!("unknown path element {p}"),
757757
}
758758
}
759759

@@ -795,7 +795,7 @@ fn set_message_option(message: &mut DescriptorProto, path: &[i32], encoded: &[u8
795795
let field = &mut message.extension[path[1] as usize];
796796
field.options = Some(Options::decode(encoded).unwrap());
797797
}
798-
p => panic!("unknown path element {}", p),
798+
p => panic!("unknown path element {p}"),
799799
}
800800
}
801801

@@ -808,6 +808,6 @@ fn set_enum_option(enum_: &mut EnumDescriptorProto, path: &[i32], encoded: &[u8]
808808
let value = &mut enum_.value[path[1] as usize];
809809
value.options = Some(Options::decode(encoded).unwrap());
810810
}
811-
p => panic!("unknown path element {}", p),
811+
p => panic!("unknown path element {p}"),
812812
}
813813
}

prost-reflect/src/descriptor/build/resolve.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ impl Visitor for ResolveVisitor<'_> {
404404
id: Identity::new(file, path, full_name, extension.name()),
405405
parent: parent_message,
406406
number: extension.number() as u32,
407-
json_name: format!("[{}]", full_name).into(),
407+
json_name: format!("[{full_name}]").into(),
408408
extendee: extendee.unwrap_or(MessageIndex::MAX),
409409
kind: kind.unwrap_or(KindIndex::Double),
410410
is_packed,
@@ -653,7 +653,7 @@ impl ResolveVisitor<'_> {
653653
Err(_) => {
654654
self.errors.push(DescriptorErrorKind::InvalidFieldDefault {
655655
value: default_value.to_owned(),
656-
kind: format!("{:?}", kind),
656+
kind: format!("{kind:?}"),
657657
found: Label::new(
658658
&self.pool.files,
659659
"found here",
@@ -753,7 +753,7 @@ impl ResolveVisitor<'_> {
753753
&mut self.pool.files[file as usize].raw,
754754
path,
755755
tag,
756-
format!(".{}", type_name),
756+
format!(".{type_name}"),
757757
ty,
758758
);
759759
Some(def)
@@ -899,7 +899,7 @@ fn set_type_name(
899899
match tag {
900900
tag::method::INPUT_TYPE => method.input_type = Some(type_name),
901901
tag::method::OUTPUT_TYPE => method.output_type = Some(type_name),
902-
p => panic!("unknown path element {}", p),
902+
p => panic!("unknown path element {p}"),
903903
}
904904
}
905905
tag::file::MESSAGE_TYPE | tag::file::EXTENSION => {
@@ -912,10 +912,10 @@ fn set_type_name(
912912
}
913913
}
914914
tag::field::EXTENDEE => field.extendee = Some(type_name),
915-
p => panic!("unknown path element {}", p),
915+
p => panic!("unknown path element {p}"),
916916
}
917917
}
918-
p => panic!("unknown path element {}", p),
918+
p => panic!("unknown path element {p}"),
919919
}
920920
}
921921

@@ -932,7 +932,7 @@ fn find_file_field_proto_mut<'a>(
932932
debug_assert_eq!(path.len(), 2);
933933
&mut file.extension[path[1] as usize]
934934
}
935-
p => panic!("unknown path element {}", p),
935+
p => panic!("unknown path element {p}"),
936936
}
937937
}
938938

@@ -953,7 +953,7 @@ fn find_message_field_proto<'a>(
953953
let nested_message = &mut message.nested_type[path[1] as usize];
954954
find_message_field_proto(nested_message, &path[2..])
955955
}
956-
p => panic!("unknown path element {}", p),
956+
p => panic!("unknown path element {p}"),
957957
}
958958
}
959959

0 commit comments

Comments
 (0)