Skip to content

Commit 54129d0

Browse files
authored
Merge pull request #24 from blockscout/lok52/repeated-internal-struct
Add support for repeated messages generation
2 parents d3c8629 + ce4874e commit 54129d0

File tree

11 files changed

+265
-697
lines changed

11 files changed

+265
-697
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ members = [
99
]
1010

1111
[workspace.package]
12-
version = "0.2.1"
12+
version = "0.2.2"
1313
edition = "2021"
1414
license = "MIT"
1515
repository = "https://github.com/blockscout/actix-prost"

actix-prost-build/src/conversions.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,32 @@ impl ConversionsGenerator {
404404
) -> Option<ProcessedType> {
405405
self.try_process_option(m_type, f, convert_field, res)
406406
.or(self.try_process_map(m_type, f, convert_field, res))
407+
.or(self.try_process_array(m_type, f, convert_field, res))
408+
}
409+
410+
fn try_process_array(
411+
&mut self,
412+
m_type: MessageType,
413+
f: &Field,
414+
convert_field: Option<&ConvertFieldOptions>,
415+
res: &mut Vec<TokenStream>,
416+
) -> Option<ProcessedType> {
417+
let name = f.ident.as_ref().unwrap();
418+
419+
let field_desc = convert_field.map(|cf| &cf.field)?;
420+
let el_type = match (field_desc.cardinality(), field_desc.kind()) {
421+
(Cardinality::Repeated, Kind::Message(m)) if !m.is_map_entry() => Some(m),
422+
_ => None,
423+
}?;
424+
// TODO: Proto name might not be the same as Rust struct name
425+
let rust_struct_name = self.messages.get(el_type.name())?.ident.clone();
426+
427+
let new_struct_name = self.build_internal_nested_struct(m_type, &rust_struct_name, res);
428+
429+
let convert = &self.convert_prefix;
430+
let ty = quote!(::prost::alloc::vec::Vec<#new_struct_name>);
431+
let conversion = quote!(#convert::try_convert(from.#name)?);
432+
Some((ty, conversion))
407433
}
408434

409435
fn try_process_option(

tests/proto/conversions.proto

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ message MapValue {
2525
string address = 1 [ (convert_options.convert) = { type : "ethers::types::Address" } ];
2626
}
2727

28+
message RepeatedValue {
29+
option (convert_options.derive) = { name: "serde::Serialize" };
30+
option (convert_options.derive) = { name: "serde::Deserialize" };
31+
option (convert_options.derive) = { name: "PartialEq" };
32+
option (convert_options.derive) = { name: "Eq" };
33+
34+
string address = 1
35+
[ (convert_options.convert) = {type : "ethers::types::Address"} ];
36+
}
37+
2838
message ConversionsRequest {
2939
option (convert_options.derive) = { name: "serde::Serialize" };
3040
option (convert_options.derive) = { name: "serde::Deserialize" };
@@ -35,13 +45,16 @@ message ConversionsRequest {
3545
option (convert_options.extra_fields) = { name: "field2", type: "i32" };
3646
map<string, MapValue> map_field = 1;
3747

48+
string query = 2
49+
[ (convert_options.convert) = {override : "Default::default()"} ];
50+
repeated string addresses = 3 [ (convert_options.convert) = {
51+
type : "std::collections::HashSet<ethers::types::Address>"
52+
} ];
53+
3854
enum NestedEnum {
3955
NESTED_OK = 0;
4056
NESTED_ERROR = 1;
4157
}
42-
43-
string query = 2 [ (convert_options.convert) = { override : "Default::default()" } ];
44-
repeated string addresses = 3 [ (convert_options.convert) = { type : "std::collections::HashSet<ethers::types::Address>" } ];
4558
NestedEnum nested_enum = 4;
4659
Nested nested = 5 [ (convert_options.convert) = { required : true } ];
4760

@@ -67,6 +80,7 @@ message ConversionsRequest {
6780
// Decimal conversions
6881
string decimal_field = 15 [ (convert_options.convert) = { type : "rust_decimal::Decimal" } ];
6982

83+
repeated RepeatedValue repeated = 16;
7084
}
7185

7286
message ConversionsResponse {

tests/proto/errors.swagger.yaml

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -46,122 +46,7 @@ definitions:
4646
properties:
4747
'@type':
4848
type: string
49-
description: |-
50-
A URL/resource name that uniquely identifies the type of the serialized
51-
protocol buffer message. This string must contain at least
52-
one "/" character. The last segment of the URL's path must represent
53-
the fully qualified name of the type (as in
54-
`path/google.protobuf.Duration`). The name should be in a canonical form
55-
(e.g., leading "." is not accepted).
56-
57-
In practice, teams usually precompile into the binary all types that they
58-
expect it to use in the context of Any. However, for URLs which use the
59-
scheme `http`, `https`, or no scheme, one can optionally set up a type
60-
server that maps type URLs to message definitions as follows:
61-
62-
* If no scheme is provided, `https` is assumed.
63-
* An HTTP GET on the URL must yield a [google.protobuf.Type][]
64-
value in binary format, or produce an error.
65-
* Applications are allowed to cache lookup results based on the
66-
URL, or have them precompiled into a binary to avoid any
67-
lookup. Therefore, binary compatibility needs to be preserved
68-
on changes to types. (Use versioned type names to manage
69-
breaking changes.)
70-
71-
Note: this functionality is not currently available in the official
72-
protobuf release, and it is not used for type URLs beginning with
73-
type.googleapis.com. As of May 2023, there are no widely used type server
74-
implementations and no plans to implement one.
75-
76-
Schemes other than `http`, `https` (or the empty scheme) might be
77-
used with implementation specific semantics.
7849
additionalProperties: {}
79-
description: |-
80-
`Any` contains an arbitrary serialized protocol buffer message along with a
81-
URL that describes the type of the serialized message.
82-
83-
Protobuf library provides support to pack/unpack Any values in the form
84-
of utility functions or additional generated methods of the Any type.
85-
86-
Example 1: Pack and unpack a message in C++.
87-
88-
Foo foo = ...;
89-
Any any;
90-
any.PackFrom(foo);
91-
...
92-
if (any.UnpackTo(&foo)) {
93-
...
94-
}
95-
96-
Example 2: Pack and unpack a message in Java.
97-
98-
Foo foo = ...;
99-
Any any = Any.pack(foo);
100-
...
101-
if (any.is(Foo.class)) {
102-
foo = any.unpack(Foo.class);
103-
}
104-
// or ...
105-
if (any.isSameTypeAs(Foo.getDefaultInstance())) {
106-
foo = any.unpack(Foo.getDefaultInstance());
107-
}
108-
109-
Example 3: Pack and unpack a message in Python.
110-
111-
foo = Foo(...)
112-
any = Any()
113-
any.Pack(foo)
114-
...
115-
if any.Is(Foo.DESCRIPTOR):
116-
any.Unpack(foo)
117-
...
118-
119-
Example 4: Pack and unpack a message in Go
120-
121-
foo := &pb.Foo{...}
122-
any, err := anypb.New(foo)
123-
if err != nil {
124-
...
125-
}
126-
...
127-
foo := &pb.Foo{}
128-
if err := any.UnmarshalTo(foo); err != nil {
129-
...
130-
}
131-
132-
The pack methods provided by protobuf library will by default use
133-
'type.googleapis.com/full.type.name' as the type URL and the unpack
134-
methods only use the fully qualified type name after the last '/'
135-
in the type URL, for example "foo.bar.com/x/y.z" will yield type
136-
name "y.z".
137-
138-
JSON
139-
====
140-
The JSON representation of an `Any` value uses the regular
141-
representation of the deserialized, embedded message, with an
142-
additional field `@type` which contains the type URL. Example:
143-
144-
package google.profile;
145-
message Person {
146-
string first_name = 1;
147-
string last_name = 2;
148-
}
149-
150-
{
151-
"@type": "type.googleapis.com/google.profile.Person",
152-
"firstName": <string>,
153-
"lastName": <string>
154-
}
155-
156-
If the embedded message type is well-known and has a custom JSON
157-
representation, that representation will be embedded adding a field
158-
`value` which holds the custom JSON in addition to the `@type`
159-
field. Example (for message [google.protobuf.Duration][]):
160-
161-
{
162-
"@type": "type.googleapis.com/google.protobuf.Duration",
163-
"value": "1.212s"
164-
}
16550
rpcStatus:
16651
type: object
16752
properties:

tests/proto/rest.swagger.yaml

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -228,122 +228,7 @@ definitions:
228228
properties:
229229
'@type':
230230
type: string
231-
description: |-
232-
A URL/resource name that uniquely identifies the type of the serialized
233-
protocol buffer message. This string must contain at least
234-
one "/" character. The last segment of the URL's path must represent
235-
the fully qualified name of the type (as in
236-
`path/google.protobuf.Duration`). The name should be in a canonical form
237-
(e.g., leading "." is not accepted).
238-
239-
In practice, teams usually precompile into the binary all types that they
240-
expect it to use in the context of Any. However, for URLs which use the
241-
scheme `http`, `https`, or no scheme, one can optionally set up a type
242-
server that maps type URLs to message definitions as follows:
243-
244-
* If no scheme is provided, `https` is assumed.
245-
* An HTTP GET on the URL must yield a [google.protobuf.Type][]
246-
value in binary format, or produce an error.
247-
* Applications are allowed to cache lookup results based on the
248-
URL, or have them precompiled into a binary to avoid any
249-
lookup. Therefore, binary compatibility needs to be preserved
250-
on changes to types. (Use versioned type names to manage
251-
breaking changes.)
252-
253-
Note: this functionality is not currently available in the official
254-
protobuf release, and it is not used for type URLs beginning with
255-
type.googleapis.com. As of May 2023, there are no widely used type server
256-
implementations and no plans to implement one.
257-
258-
Schemes other than `http`, `https` (or the empty scheme) might be
259-
used with implementation specific semantics.
260231
additionalProperties: {}
261-
description: |-
262-
`Any` contains an arbitrary serialized protocol buffer message along with a
263-
URL that describes the type of the serialized message.
264-
265-
Protobuf library provides support to pack/unpack Any values in the form
266-
of utility functions or additional generated methods of the Any type.
267-
268-
Example 1: Pack and unpack a message in C++.
269-
270-
Foo foo = ...;
271-
Any any;
272-
any.PackFrom(foo);
273-
...
274-
if (any.UnpackTo(&foo)) {
275-
...
276-
}
277-
278-
Example 2: Pack and unpack a message in Java.
279-
280-
Foo foo = ...;
281-
Any any = Any.pack(foo);
282-
...
283-
if (any.is(Foo.class)) {
284-
foo = any.unpack(Foo.class);
285-
}
286-
// or ...
287-
if (any.isSameTypeAs(Foo.getDefaultInstance())) {
288-
foo = any.unpack(Foo.getDefaultInstance());
289-
}
290-
291-
Example 3: Pack and unpack a message in Python.
292-
293-
foo = Foo(...)
294-
any = Any()
295-
any.Pack(foo)
296-
...
297-
if any.Is(Foo.DESCRIPTOR):
298-
any.Unpack(foo)
299-
...
300-
301-
Example 4: Pack and unpack a message in Go
302-
303-
foo := &pb.Foo{...}
304-
any, err := anypb.New(foo)
305-
if err != nil {
306-
...
307-
}
308-
...
309-
foo := &pb.Foo{}
310-
if err := any.UnmarshalTo(foo); err != nil {
311-
...
312-
}
313-
314-
The pack methods provided by protobuf library will by default use
315-
'type.googleapis.com/full.type.name' as the type URL and the unpack
316-
methods only use the fully qualified type name after the last '/'
317-
in the type URL, for example "foo.bar.com/x/y.z" will yield type
318-
name "y.z".
319-
320-
JSON
321-
====
322-
The JSON representation of an `Any` value uses the regular
323-
representation of the deserialized, embedded message, with an
324-
additional field `@type` which contains the type URL. Example:
325-
326-
package google.profile;
327-
message Person {
328-
string first_name = 1;
329-
string last_name = 2;
330-
}
331-
332-
{
333-
"@type": "type.googleapis.com/google.profile.Person",
334-
"firstName": <string>,
335-
"lastName": <string>
336-
}
337-
338-
If the embedded message type is well-known and has a custom JSON
339-
representation, that representation will be embedded adding a field
340-
`value` which holds the custom JSON in addition to the `@type`
341-
field. Example (for message [google.protobuf.Duration][]):
342-
343-
{
344-
"@type": "type.googleapis.com/google.protobuf.Duration",
345-
"value": "1.212s"
346-
}
347232
restGet:
348233
type: object
349234
properties:

0 commit comments

Comments
 (0)