Skip to content

Commit 8a0569e

Browse files
committed
Simplify Service_info: replace file_name and package_service_names with file_descriptor_proto
Remove the file_name and package_service_names fields from the Service_info module interface, replacing them with a file_descriptor_proto field that contains the serialized FileDescriptorProto bytes. This provides a more canonical and self-contained reflection mechanism, since all metadata (file name, services, etc.) can be derived from the descriptor itself. - Remove package_service_name tracking from service code generation - Add file_descriptor_proto as serialized proto bytes to Service_info - Simplify emit_service_type to no longer return package_service_name - Update reflection tests to verify roundtrip deserialization - Update echo example to use the new Call.name accessor
1 parent b05c655 commit 8a0569e

4 files changed

Lines changed: 28 additions & 55 deletions

File tree

‎examples/echo/test.ml‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ let do_request ~handler request =
4848
|> function | Ok v -> v | Error e -> failwith (Printf.sprintf "Could not reply request: %s" (Ocaml_protoc_plugin.Result.show_error e))
4949

5050
let () =
51-
let name = Echo.Echo.package_service_name in
51+
let name = Echo.Echo.Call.name in
5252
let request = mk_request () in
5353
let reply = do_request ~handler:handle_request request in
54-
Printf.printf "Reply to %s: %s\n" name reply;
55-
assert (List.mem Echo.Echo.package_service_name Service_info.package_service_names)
54+
Printf.printf "Reply to %s: %s\n" name reply

‎src/ocaml_protoc_plugin/service.ml‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ let make_service_functions (type req) (type rep)
3131

3232
module type Service_info = sig
3333
type t
34-
val file_name : string
34+
val file_descriptor_proto : string
3535
val file_descriptor : t
36-
val package_service_names : string list
3736
end

‎src/plugin/emit.ml‎

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -147,27 +147,19 @@ let emit_service_type ~scope ~comment_db ~type_db ServiceDescriptorProto.{ name;
147147

148148
let proto_path = Scope.get_proto_path scope in
149149
let ocaml_service_name = Type_db.get_service type_db ~proto_path name in
150-
let package_service_name =
151-
match String.split_on_char ~sep:'.' proto_path with
152-
| [] | "":: [] -> name
153-
| "" :: packages | packages ->
154-
(String.concat ~sep:"." packages) ^ "." ^ name
155-
in
156150

157151
let signature = Code.init () in
158152
let implementation = Code.init () in
159153
Code.emit_comment ~position:`Leading signature (Comment_db.get_service_comments comment_db ~proto_path ~name);
160154
Code.emit signature `Begin "module %s : sig" ocaml_service_name;
161155
Code.emit implementation `Begin "module %s = struct" ocaml_service_name;
162-
Code.emit signature `None "val package_service_name : string";
163-
Code.emit implementation `None {|let package_service_name = "%s"|} package_service_name;
164156

165157
List.iter ~f:(emit_method ~scope:(Scope.push scope name) ~type_db signature implementation name) methods;
166158
Code.emit signature `End "end%s" (Code.append_deprecaton_if ~deprecated `Item "");
167159
Code.emit signature `None "";
168160
Code.emit implementation `End "end%s" (Code.append_deprecaton_if ~deprecated `Item "");
169161
Code.emit implementation `None "";
170-
signature, implementation, package_service_name
162+
signature, implementation
171163

172164
let emit_extension ~scope ~params ~comment_db ~type_db field =
173165
let FieldDescriptorProto.{ name; extendee; options; _ } = field in
@@ -393,23 +385,20 @@ let rec wrap_packages ~params ~syntax ~options ~comment_db ~type_db ~scope messa
393385
| [] ->
394386
let { module_name = _; implementation; signature; deprecated = _; comments = _ } =
395387
emit_message ~params ~syntax ~scope ~comment_db ~type_db message_type in
396-
let package_service_names =
397-
List.map ~f:(fun service ->
398-
let signature', implementation', package_service_name = emit_service_type ~scope ~type_db ~comment_db service in
399-
Code.append implementation implementation';
400-
Code.append signature signature';
401-
package_service_name
402-
) services
403-
in
404-
signature, implementation, package_service_names
388+
List.iter ~f:(fun service ->
389+
let signature', implementation' = emit_service_type ~scope ~type_db ~comment_db service in
390+
Code.append implementation implementation';
391+
Code.append signature signature'
392+
) services;
393+
signature, implementation
405394
| package :: packages ->
406395
let signature = Code.init () in
407396
let implementation = Code.init () in
408397
let proto_path = Scope.get_proto_path scope in
409398
let package_name = Type_db.get_package_name type_db ~proto_path package in
410399
let scope = Scope.push scope package in
411400

412-
let signature', implementation', package_service_names =
401+
let signature', implementation' =
413402
wrap_packages ~params ~syntax ~options ~scope ~type_db ~comment_db message_type services packages
414403
in
415404
Code.emit implementation `Begin "module rec %s : sig" package_name;
@@ -420,7 +409,7 @@ let rec wrap_packages ~params ~syntax ~options ~comment_db ~type_db ~scope messa
420409
Code.emit signature `Begin "module rec %s : sig" package_name;
421410
Code.append signature signature';
422411
Code.emit signature `End "end";
423-
signature, implementation, package_service_names
412+
signature, implementation
424413

425414

426415
let emit_header implementation ~proto_name ~syntax ~params =
@@ -448,15 +437,13 @@ let emit_header implementation ~proto_name ~syntax ~params =
448437
(* Code.emit implementation `None "%s" (Code.append_deprecaton_if ~deprecated `Floating ""); *)
449438
()
450439

451-
let emit_service_info implementation fd file_name package_service_names =
440+
let emit_service_info implementation fd =
441+
let file_descriptor_bytes = Spec.Descriptor.Google.Protobuf.FileDescriptorProto.to_proto fd |> Ocaml_protoc_plugin.Writer.contents |> String.escaped in
452442
let file_descriptor = Spec.Descriptor.Google.Protobuf.FileDescriptorProto.show fd in
453443
Code.emit implementation `Begin "module Service_info : Runtime'.Service.Service_info with type t = Descriptor.Google.Protobuf.FileDescriptorProto.t = struct";
454444
Code.emit implementation `None "type t = Descriptor.Google.Protobuf.FileDescriptorProto.t";
455-
Code.emit implementation `None {|let file_name = "%s"|} file_name;
445+
Code.emit implementation `None {|let file_descriptor_proto = "%s"|} file_descriptor_bytes;
456446
Code.emit implementation `None {|let file_descriptor = %s|} file_descriptor;
457-
Code.emit implementation `Begin "let package_service_names = [";
458-
List.iter ~f:(fun name -> Code.emit implementation `None {|"%s";|} name) package_service_names;
459-
Code.emit implementation `End "]";
460447
Code.emit implementation `End "end"
461448

462449
let parse_proto_file ~params ~scope ~type_db filedescriptorproto =
@@ -496,15 +483,15 @@ let parse_proto_file ~params ~scope ~type_db filedescriptorproto =
496483
Code.emit implementation `End "end";
497484
Code.emit implementation `None "(**/**)";
498485

499-
let _signature', implementation', package_service_names =
486+
let _signature', implementation' =
500487
wrap_packages ~params ~syntax ~options ~scope ~type_db ~comment_db message_type services (Option.value_map ~default:[] ~f:(String.split_on_char ~sep:'.') package)
501488
in
502489

503490
Code.append implementation implementation';
504491
Code.emit implementation `None "";
505492

506493
if params.service_info then
507-
emit_service_info implementation filedescriptorproto proto_name package_service_names;
494+
emit_service_info implementation filedescriptorproto;
508495

509496
let output_file_name =
510497
Type_db.get_module_name type_db proto_name

‎test/reflection_test.ml‎

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,20 @@
1-
module S = Reflection
2-
module P = Reflection_parts
3-
4-
let%test _ =
5-
S.Service_info.file_name = "reflection.proto"
6-
7-
let%test _ =
8-
S.Service_info.package_service_names = [ "test.reflection.EmptyService"; "test.reflection.SomeService" ]
1+
open Ocaml_protoc_plugin
92

10-
let%test _ =
11-
P.Service_info.file_name ="reflection_parts.proto"
12-
13-
let%test _ =
14-
List.is_empty P.Service_info.package_service_names
3+
module S = Reflection
154

16-
let%test_module "Construct service_info by itself" = (module
5+
let%test_module "file_descriptor" = (module
176
struct
187
open Google_types_pp.Descriptor.Google.Protobuf
198

20-
let package = S.Service_info.file_descriptor.package |> Option.get
9+
let fd = S.Service_info.file_descriptor
2110

2211
let%test "file_name" =
23-
S.Service_info.file_name = (S.Service_info.file_descriptor.name |> Option.get)
12+
fd.name = Some "reflection.proto"
13+
14+
let%test "has_services" =
15+
List.length fd.service = 2
2416

25-
let%test "package_service_names" =
26-
let services =
27-
S.Service_info.file_descriptor.service
28-
|> List.map
29-
@@ fun ServiceDescriptorProto.{name; _} -> Option.fold name ~none:"" ~some:(Printf.sprintf "%s.%s" package)
30-
in
31-
services = S.Service_info.package_service_names
17+
let%test "file_descriptor_proto_roundtrip" =
18+
let fd' = Reader.create S.Service_info.file_descriptor_proto |> FileDescriptorProto.from_proto_exn in
19+
fd.name = fd'.name
3220
end)

0 commit comments

Comments
 (0)