From 8283ef7298ea2b7ee6b701e4182da72c8c7c6770 Mon Sep 17 00:00:00 2001 From: Erik Friese Date: Tue, 5 Sep 2023 21:38:51 +0200 Subject: [PATCH] bugfix map fields with values of message type were not serialized correctly --- betterproto-extras/src/descriptor_pool.rs | 91 +++++++++++++++-------- betterproto-extras/src/merging.rs | 2 +- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/betterproto-extras/src/descriptor_pool.rs b/betterproto-extras/src/descriptor_pool.rs index 64a0b42..88d1dfc 100644 --- a/betterproto-extras/src/descriptor_pool.rs +++ b/betterproto-extras/src/descriptor_pool.rs @@ -100,6 +100,16 @@ fn add_message_to_file( ..Default::default() }; proto.set_type(val); + if val == Type::Message { + set_type_name( + &message_name, + meta.get_class(&format!("{field_name}.value"))?, + &mut proto, + file, + &mut messages_to_add, + pool, + )?; + } proto }, ], @@ -147,41 +157,20 @@ fn add_message_to_file( } Some(t) => return Err(Error::UnsupportedWrapperType(t)), None => { - let cls = meta.get_class(field_name)?; - let cls_name = cls.qualified_name()?; - - match cls_name.as_str() { - "datetime.datetime" => { - field.type_name = - Some("google.protobuf.Timestamp".to_string()); - } - "datetime.timedelta" => { - field.type_name = - Some("google.protobuf.Duration".to_string()); - } - _ => { - let cls_name = format!("{}_{}", cls_name, cls.py_identifier()); - field.type_name = Some(cls_name.clone()); - - if message_name != cls_name - && pool.get_message_by_name(&cls_name).is_none() - && !file - .message_type - .iter() - .any(|item| item.name() == cls_name) - && !messages_to_add - .iter() - .any(|item| item.0 == cls_name) - { - messages_to_add.push((cls_name, cls.call0()?)); - } - } - } + set_type_name( + &message_name, + meta.get_class(field_name)?, + &mut field, + file, + &mut messages_to_add, + pool, + )?; } }, Type::Enum => { let cls = meta.get_class(field_name)?; - let cls_name = format!("{}_{}", cls.qualified_name()?, cls.py_identifier()); + let cls_name = + format!("{}_{}", cls.qualified_name()?, cls.py_identifier()); field.type_name = Some(cls_name.to_string()); if pool.get_enum_by_name(&cls_name).is_none() @@ -196,7 +185,11 @@ fn add_message_to_file( let item = item?; proto.value.push(EnumValueDescriptorProto { number: Some(item.getattr("value")?.extract()?), - name: Some(format!("{}_{}", cls_name, item.getattr("name")?.extract::<&str>()?)), + name: Some(format!( + "{}_{}", + cls_name, + item.getattr("name")?.extract::<&str>()? + )), ..Default::default() }); } @@ -260,3 +253,37 @@ fn map_type(str: &str) -> Result { _ => Err(Error::UnsupportedType(str.to_string())), } } + +fn set_type_name<'py>( + message_name: &str, + field_cls: &'py PyAny, + field: &mut FieldDescriptorProto, + file: &FileDescriptorProto, + messages_to_add: &mut Vec<(String, &'py PyAny)>, + pool: &DescriptorPool, +) -> Result<()> { + let cls_name = field_cls.qualified_name()?; + + match cls_name.as_str() { + "datetime.datetime" => { + field.type_name = Some("google.protobuf.Timestamp".to_string()); + } + "datetime.timedelta" => { + field.type_name = Some("google.protobuf.Duration".to_string()); + } + _ => { + let cls_name = format!("{}_{}", cls_name, field_cls.py_identifier()); + field.type_name = Some(cls_name.clone()); + + if message_name != cls_name + && pool.get_message_by_name(&cls_name).is_none() + && !file.message_type.iter().any(|item| item.name() == cls_name) + && !messages_to_add.iter().any(|item| item.0 == cls_name) + { + messages_to_add.push((cls_name, field_cls.call0()?)); + } + } + } + + Ok(()) +} diff --git a/betterproto-extras/src/merging.rs b/betterproto-extras/src/merging.rs index af8b26c..a326958 100644 --- a/betterproto-extras/src/merging.rs +++ b/betterproto-extras/src/merging.rs @@ -112,7 +112,7 @@ fn map_field_value(field_name: &str, field_value: Value, proto_meta: &PyAny) -> .into_iter() .map(|(k, v)| { let key = map_key(k, py); - let val = map_field_value(field_name, v, proto_meta)?; + let val = map_field_value(&format!("{field_name}.value"), v, proto_meta)?; Ok((key, val)) }) .collect();