Skip to content

Commit e1d4a23

Browse files
authored
Support extension (#83)
* init implementation for extension only get_extension/put_extension without encoding/decoding and protoc * support decoding and encoding for extension * generate code for extensions * finish extension * ci: fix integration test * improve docs * mix format * update README and CLI doc * filter extension module by name first * regenerate protos * doc: add custom options to README
1 parent 99e4212 commit e1d4a23

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1514
-468
lines changed

.formatter.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

22
[
33
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],
4-
locals_without_parens: [field: 2, field: 3, oneof: 2],
4+
locals_without_parens: [field: 2, field: 3, oneof: 2, extend: 4, extensions: 1],
55
export: [
6-
locals_without_parens: [field: 2, field: 3, oneof: 2]
6+
locals_without_parens: [field: 2, field: 3, oneof: 2, extend: 4, extensions: 1]
77
]
88
]

.travis.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ language: elixir
33
git:
44
depth: 3
55
elixir:
6-
- 1.6
76
- 1.7
87
- 1.8
98
- 1.9
@@ -12,9 +11,8 @@ otp_release:
1211
- 21.3
1312
- 22.0
1413
matrix:
15-
exclude:
16-
- elixir: 1.6
17-
otp_release: 22.0
14+
allow_failures:
15+
- otp_release: 20.3
1816
env:
1917
- MIX_ENV=test VERBOSE_TESTS=true
2018
install:
@@ -23,8 +21,8 @@ install:
2321
- mix deps.get
2422
- mix eqc.install --mini --force
2523
before_script:
26-
- wget https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-linux-x86_64.zip
27-
- unzip protoc-3.3.0-linux-x86_64.zip
24+
- wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protoc-3.11.2-linux-x86_64.zip
25+
- unzip protoc-3.11.2-linux-x86_64.zip
2826
- export PATH=$PATH:$PWD/bin/
2927
script:
3028
- mix test

Makefile

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,16 @@ protoc-gen-elixir:
44
mix escript.build .
55

66
clean:
7-
rm protoc-gen-elixir
7+
rm -f protoc-gen-elixir
88

99
# PROTO_LIB should be your local path to https://github.com/google/protobuf/tree/master/src/google/protobuf
10-
gen_google_proto: protoc-gen-elixir
10+
gen-google-protos: protoc-gen-elixir
1111
$(call ndef,PROTO_LIB)
12-
protoc -I $(PROTO_LIB) --elixir_out=lib/google --plugin=./protoc-gen-elixir $(PROTO_LIB)/descriptor.proto
13-
protoc -I $(PROTO_LIB) --elixir_out=lib/google --plugin=./protoc-gen-elixir $(PROTO_LIB)/compiler/plugin.proto
12+
protoc -I $(PROTO_LIB) --elixir_out=lib/google --plugin=./protoc-gen-elixir descriptor.proto
13+
protoc -I $(PROTO_LIB) --elixir_out=lib/google --plugin=./protoc-gen-elixir compiler/plugin.proto
1414

15-
# it's a hack until extension is implemented
16-
# 1047 is allocated to this project by Google
17-
sed -i "" '/field :ruby_package, 45/a \
18-
\ \ field :elixir_module_prefix, 1047, optional: true, type: :string\
19-
' lib/google/descriptor.pb.ex
15+
gen-protos: protoc-gen-elixir
16+
protoc -I src -I test/protobuf/protoc/proto --elixir_out=test/protobuf/protoc/proto_gen --plugin=./protoc-gen-elixir test/protobuf/protoc/proto/*.proto
17+
protoc -I src --elixir_out=lib --plugin=./protoc-gen-elixir elixirpb.proto
2018

21-
sed -i "" '/ :ruby_package,/a \
22-
\ \ \ \ :elixir_module_prefix,\
23-
' lib/google/descriptor.pb.ex
24-
25-
.PHONY: clean gen_google_proto
19+
.PHONY: clean gen_google_proto gen_test_protos

README.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ The package can be installed by adding `protobuf` to your list of dependencies i
2222
```elixir
2323
def deps do
2424
[
25-
{:protobuf, "~> 0.5.3"},
25+
{:protobuf, "~> 0.7.1"},
2626
# Only for files generated from Google's protos.
2727
# Can be ignored if you don't use Google's protos.
28+
# Or you can generate the code by yourself.
2829
{:google_protos, "~> 0.1"}
2930
]
3031
end
@@ -44,6 +45,7 @@ end
4445
* [x] Validate values
4546
* [x] Generate typespecs
4647
* [x] oneof
48+
* [x] (proto2) Extension (Experiment, see `Protobuf.Extension`)
4749

4850
## Usage
4951

@@ -94,7 +96,6 @@ struct = Foo.decode(encoded)
9496

9597
Note:
9698
- You should use `YourModule.new` instead of using the struct directly because default values will be set for all fields.
97-
- Default values will be set by default in `decode`, which can be changed by `:use_default` option.
9899
- Validation is done in `encode`. An error will be raised if the struct is invalid(like type is not matched).
99100

100101
### Descriptor support
@@ -126,6 +127,26 @@ $ protoc --elixir_out=./lib --plugin=./protoc-gen-elixir *.proto
126127
$ protoc -I protos --elixir_out=./lib protos/hello.proto
127128
```
128129

130+
### Custom options
131+
132+
Since extensions(`Protobuf.Extension`) is supported now, some options are defined, like custom module_prefix.
133+
134+
1. Copy src/elixirpb.proto to your protos path
135+
2. Import elixirpb.proto and use the options
136+
137+
```proto
138+
syntax = "proto2";
139+
140+
package your.pkg;
141+
142+
import "elixirpb.proto";
143+
144+
option (elixirpb.file).module_prefix = "Foo.Bar";
145+
```
146+
3. Generate code as before
147+
148+
More options will be added in the future, see elixirpb.proto comments for details.
149+
129150
## Tests
130151

131152
Before you can run the test suite, you must install `eqc_gen`:

lib/application.ex

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
defmodule Protobuf.Application do
2+
use Application
3+
4+
@moduledoc """
5+
When extensions feature is enabled, all modules are scanned to fetch
6+
runtime information for extensions, see `Protobuf.Extension` for details.
7+
8+
No children are created now.
9+
"""
10+
11+
@doc false
12+
def start(_type, _args) do
13+
if Application.get_env(:protobuf, :extensions, :disabled) == :enabled do
14+
mods = get_all_modules()
15+
Protobuf.Extension.cal_extensions(mods)
16+
else
17+
# Extensions in Protobuf should always be calculated for generating code
18+
{:ok, mods} = :application.get_key(:protobuf, :modules)
19+
Protobuf.Extension.cal_extensions(mods)
20+
end
21+
22+
children = []
23+
Supervisor.start_link(children, strategy: :one_for_one)
24+
end
25+
26+
defp get_all_modules() do
27+
case :code.get_mode() do
28+
:embedded ->
29+
:erlang.loaded()
30+
31+
:interactive ->
32+
for {app, _, _} <- Application.loaded_applications() do
33+
{:ok, modules} = :application.get_key(app, :modules)
34+
modules
35+
end
36+
|> Enum.concat()
37+
end
38+
end
39+
end

lib/elixirpb.pb.ex

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
defmodule Elixirpb.FileOptions do
2+
@moduledoc false
3+
use Protobuf, syntax: :proto2
4+
5+
@type t :: %__MODULE__{
6+
module_prefix: String.t()
7+
}
8+
defstruct [:module_prefix]
9+
10+
field :module_prefix, 1, optional: true, type: :string
11+
end
12+
13+
defmodule Elixirpb.PbExtension do
14+
@moduledoc false
15+
use Protobuf, syntax: :proto2
16+
17+
extend Google.Protobuf.FileOptions, :file, 1047, optional: true, type: Elixirpb.FileOptions
18+
end

lib/google/compiler/plugin.pb.ex

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,6 @@ defmodule Google.Protobuf.Compiler.CodeGeneratorRequest do
3434
field :compiler_version, 3, optional: true, type: Google.Protobuf.Compiler.Version
3535
end
3636

37-
defmodule Google.Protobuf.Compiler.CodeGeneratorResponse do
38-
@moduledoc false
39-
use Protobuf, syntax: :proto2
40-
41-
@type t :: %__MODULE__{
42-
error: String.t(),
43-
file: [Google.Protobuf.Compiler.CodeGeneratorResponse.File.t()]
44-
}
45-
defstruct [:error, :file]
46-
47-
field :error, 1, optional: true, type: :string
48-
field :file, 15, repeated: true, type: Google.Protobuf.Compiler.CodeGeneratorResponse.File
49-
end
50-
5137
defmodule Google.Protobuf.Compiler.CodeGeneratorResponse.File do
5238
@moduledoc false
5339
use Protobuf, syntax: :proto2
@@ -63,3 +49,17 @@ defmodule Google.Protobuf.Compiler.CodeGeneratorResponse.File do
6349
field :insertion_point, 2, optional: true, type: :string
6450
field :content, 15, optional: true, type: :string
6551
end
52+
53+
defmodule Google.Protobuf.Compiler.CodeGeneratorResponse do
54+
@moduledoc false
55+
use Protobuf, syntax: :proto2
56+
57+
@type t :: %__MODULE__{
58+
error: String.t(),
59+
file: [Google.Protobuf.Compiler.CodeGeneratorResponse.File.t()]
60+
}
61+
defstruct [:error, :file]
62+
63+
field :error, 1, optional: true, type: :string
64+
field :file, 15, repeated: true, type: Google.Protobuf.Compiler.CodeGeneratorResponse.File
65+
end

0 commit comments

Comments
 (0)