Skip to content

Commit 3d2adab

Browse files
committed
x
1 parent 6da82c1 commit 3d2adab

2 files changed

Lines changed: 153 additions & 121 deletions

File tree

alt_core_api/tools/protoc_gen_arduinoif/common.py

Lines changed: 4 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@
77
import types
88
from functools import lru_cache
99
from pathlib import Path
10-
from typing import Dict, List, NamedTuple, Optional, Tuple
10+
from typing import List, NamedTuple, Tuple
1111

12-
from google.protobuf.descriptor_pb2 import (
13-
DescriptorProto,
14-
EnumDescriptorProto,
15-
FieldDescriptorProto,
16-
ServiceDescriptorProto,
17-
)
12+
from google.protobuf.descriptor_pb2 import EnumDescriptorProto, ServiceDescriptorProto
13+
14+
from .method_spec import MethodSpec
1815

1916
__all__ = [
2017
"full_service_name",
@@ -27,26 +24,6 @@
2724
]
2825

2926

30-
_DEFAULT_FIELD_CPP_TYPES: Dict[int, str] = {
31-
FieldDescriptorProto.TYPE_BOOL: "bool",
32-
FieldDescriptorProto.TYPE_INT32: "int32_t",
33-
FieldDescriptorProto.TYPE_INT64: "int64_t",
34-
FieldDescriptorProto.TYPE_UINT32: "uint32_t",
35-
FieldDescriptorProto.TYPE_UINT64: "uint64_t",
36-
FieldDescriptorProto.TYPE_SINT32: "int32_t",
37-
FieldDescriptorProto.TYPE_SINT64: "int64_t",
38-
FieldDescriptorProto.TYPE_FIXED32: "uint32_t",
39-
FieldDescriptorProto.TYPE_FIXED64: "uint64_t",
40-
FieldDescriptorProto.TYPE_SFIXED32: "int32_t",
41-
FieldDescriptorProto.TYPE_SFIXED64: "int64_t",
42-
FieldDescriptorProto.TYPE_FLOAT: "float",
43-
FieldDescriptorProto.TYPE_DOUBLE: "double",
44-
FieldDescriptorProto.TYPE_STRING: "const char *",
45-
FieldDescriptorProto.TYPE_BYTES: "const uint8_t *",
46-
FieldDescriptorProto.TYPE_ENUM: "int32_t",
47-
}
48-
49-
5027
class OptionsView:
5128
def __init__(self, options) -> None:
5229
self._options = options
@@ -74,100 +51,6 @@ def bool(self, extension, default: bool = False) -> bool:
7451
return default
7552
return bool(self._options.Extensions[extension])
7653

77-
78-
class MethodSpec(NamedTuple):
79-
decl: str
80-
call_name: str
81-
arg_names: List[str]
82-
returns_void: bool
83-
source_virtual: bool
84-
emit_api: bool
85-
emit_service: bool
86-
visibility: str
87-
88-
@classmethod
89-
def build(
90-
cls,
91-
method,
92-
*,
93-
opts_pb2,
94-
message_map: Dict[str, DescriptorProto],
95-
default_types: Optional[Dict[int, str]] = None,
96-
) -> "MethodSpec":
97-
default_field_types = default_types or _DEFAULT_FIELD_CPP_TYPES
98-
method_opts = OptionsView(method.options)
99-
100-
source_virtual = method_opts.bool(opts_pb2.source_virtual, True)
101-
emit_api = method_opts.bool(opts_pb2.emit_api, True)
102-
emit_service = method_opts.bool(opts_pb2.emit_service, True)
103-
visibility = method_opts.string(opts_pb2.method_visibility).strip().lower()
104-
if not visibility:
105-
visibility = "public"
106-
if visibility not in {"public", "protected", "private"}:
107-
raise ValueError(
108-
f"{method.name}: unsupported method_visibility '{visibility}' "
109-
"(expected: public, protected, private)"
110-
)
111-
112-
method_name = method_opts.string(opts_pb2.cpp_name).strip() or method.name
113-
114-
def resolve_field(field: FieldDescriptorProto) -> Tuple[str, str]:
115-
field_opts = OptionsView(field.options)
116-
field_type = (
117-
field_opts.string(opts_pb2.cpp_type).strip()
118-
or default_field_types.get(field.type, "int32_t")
119-
)
120-
field_name = field_opts.string(opts_pb2.field_cpp_name).strip() or field.name
121-
return field_type, field_name
122-
123-
return_type = method_opts.string(opts_pb2.cpp_return).strip()
124-
if not return_type:
125-
output_message = message_map.get(method.output_type)
126-
if output_message is None:
127-
return_type = "void"
128-
else:
129-
return_type = (
130-
resolve_field(output_message.field[0])[0]
131-
if len(output_message.field) == 1
132-
else "void"
133-
)
134-
135-
arg_names: List[str] = []
136-
param_decls: List[str] = []
137-
arg_types = method_opts.string_list(opts_pb2.cpp_arg_types)
138-
if arg_types:
139-
arg_names = [f"arg{index}" for index in range(len(arg_types))]
140-
param_decls = [
141-
f"{arg_type} {arg_name}"
142-
for arg_type, arg_name in zip(arg_types, arg_names)
143-
]
144-
else:
145-
input_message = message_map.get(method.input_type)
146-
if input_message is not None:
147-
for field in sorted(input_message.field, key=lambda f: f.number):
148-
field_type, field_name = resolve_field(field)
149-
param_decls.append(f"{field_type} {field_name}")
150-
arg_names.append(field_name)
151-
152-
params_blob = ", ".join(param_decls)
153-
decl = (
154-
f"{method_name}({params_blob})"
155-
if method_name.startswith("operator ")
156-
else f"{return_type} {method_name}({params_blob})"
157-
)
158-
159-
return cls(
160-
decl=decl,
161-
call_name=method_name,
162-
arg_names=arg_names,
163-
returns_void=(return_type == "void"),
164-
source_virtual=source_virtual,
165-
emit_api=emit_api,
166-
emit_service=emit_service,
167-
visibility=visibility,
168-
)
169-
170-
17154
class PlannedMethod(NamedTuple):
17255
spec: MethodSpec
17356
in_ifc: bool
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
from __future__ import annotations
4+
5+
from typing import Dict, List, NamedTuple, Optional, Tuple
6+
7+
from google.protobuf.descriptor_pb2 import DescriptorProto, FieldDescriptorProto
8+
9+
__all__ = [
10+
"MethodSpec",
11+
]
12+
13+
_DEFAULT_FIELD_CPP_TYPES: Dict[int, str] = {
14+
FieldDescriptorProto.TYPE_BOOL: "bool",
15+
FieldDescriptorProto.TYPE_INT32: "int32_t",
16+
FieldDescriptorProto.TYPE_INT64: "int64_t",
17+
FieldDescriptorProto.TYPE_UINT32: "uint32_t",
18+
FieldDescriptorProto.TYPE_UINT64: "uint64_t",
19+
FieldDescriptorProto.TYPE_SINT32: "int32_t",
20+
FieldDescriptorProto.TYPE_SINT64: "int64_t",
21+
FieldDescriptorProto.TYPE_FIXED32: "uint32_t",
22+
FieldDescriptorProto.TYPE_FIXED64: "uint64_t",
23+
FieldDescriptorProto.TYPE_SFIXED32: "int32_t",
24+
FieldDescriptorProto.TYPE_SFIXED64: "int64_t",
25+
FieldDescriptorProto.TYPE_FLOAT: "float",
26+
FieldDescriptorProto.TYPE_DOUBLE: "double",
27+
FieldDescriptorProto.TYPE_STRING: "const char *",
28+
FieldDescriptorProto.TYPE_BYTES: "const uint8_t *",
29+
FieldDescriptorProto.TYPE_ENUM: "int32_t",
30+
}
31+
32+
33+
def _has_extension(options, extension) -> bool:
34+
try:
35+
return options.HasExtension(extension)
36+
except (AttributeError, KeyError):
37+
return False
38+
39+
40+
def _option_string(options, extension) -> str:
41+
if not _has_extension(options, extension):
42+
return ""
43+
return str(options.Extensions[extension])
44+
45+
46+
def _option_string_list(options, extension) -> List[str]:
47+
try:
48+
values = options.Extensions[extension]
49+
except (AttributeError, KeyError):
50+
return []
51+
return [text for text in (str(value).strip() for value in values) if text]
52+
53+
54+
def _option_bool(options, extension, default: bool = False) -> bool:
55+
if not _has_extension(options, extension):
56+
return default
57+
return bool(options.Extensions[extension])
58+
59+
60+
class MethodSpec(NamedTuple):
61+
decl: str
62+
call_name: str
63+
arg_names: List[str]
64+
returns_void: bool
65+
source_virtual: bool
66+
emit_api: bool
67+
emit_service: bool
68+
visibility: str
69+
70+
@classmethod
71+
def build(
72+
cls,
73+
method,
74+
*,
75+
opts_pb2,
76+
message_map: Dict[str, DescriptorProto],
77+
default_types: Optional[Dict[int, str]] = None,
78+
) -> "MethodSpec":
79+
default_field_types = default_types or _DEFAULT_FIELD_CPP_TYPES
80+
method_opts = method.options
81+
82+
source_virtual = _option_bool(method_opts, opts_pb2.source_virtual, True)
83+
emit_api = _option_bool(method_opts, opts_pb2.emit_api, True)
84+
emit_service = _option_bool(method_opts, opts_pb2.emit_service, True)
85+
86+
visibility = _option_string(method_opts, opts_pb2.method_visibility).strip().lower()
87+
if not visibility:
88+
visibility = "public"
89+
if visibility not in {"public", "protected", "private"}:
90+
raise ValueError(
91+
f"{method.name}: unsupported method_visibility '{visibility}' "
92+
"(expected: public, protected, private)"
93+
)
94+
95+
method_name = _option_string(method_opts, opts_pb2.cpp_name).strip() or method.name
96+
97+
def resolve_field(field: FieldDescriptorProto) -> Tuple[str, str]:
98+
field_opts = field.options
99+
field_type = (
100+
_option_string(field_opts, opts_pb2.cpp_type).strip()
101+
or default_field_types.get(field.type, "int32_t")
102+
)
103+
field_name = _option_string(field_opts, opts_pb2.field_cpp_name).strip() or field.name
104+
return field_type, field_name
105+
106+
return_type = _option_string(method_opts, opts_pb2.cpp_return).strip()
107+
if not return_type:
108+
output_message = message_map.get(method.output_type)
109+
if output_message is None:
110+
return_type = "void"
111+
elif len(output_message.field) == 1:
112+
return_type = resolve_field(output_message.field[0])[0]
113+
else:
114+
return_type = "void"
115+
116+
arg_names: List[str] = []
117+
param_decls: List[str] = []
118+
arg_types = _option_string_list(method_opts, opts_pb2.cpp_arg_types)
119+
if arg_types:
120+
arg_names = [f"arg{index}" for index in range(len(arg_types))]
121+
param_decls = [
122+
f"{arg_type} {arg_name}"
123+
for arg_type, arg_name in zip(arg_types, arg_names)
124+
]
125+
else:
126+
input_message = message_map.get(method.input_type)
127+
if input_message is not None:
128+
for field in sorted(input_message.field, key=lambda f: f.number):
129+
field_type, field_name = resolve_field(field)
130+
param_decls.append(f"{field_type} {field_name}")
131+
arg_names.append(field_name)
132+
133+
params_blob = ", ".join(param_decls)
134+
decl = (
135+
f"{method_name}({params_blob})"
136+
if method_name.startswith("operator ")
137+
else f"{return_type} {method_name}({params_blob})"
138+
)
139+
140+
return cls(
141+
decl=decl,
142+
call_name=method_name,
143+
arg_names=arg_names,
144+
returns_void=(return_type == "void"),
145+
source_virtual=source_virtual,
146+
emit_api=emit_api,
147+
emit_service=emit_service,
148+
visibility=visibility,
149+
)

0 commit comments

Comments
 (0)