Commit Graph

245 Commits

Author SHA1 Message Date
Dan Swain
1af7c4ee1d Clean up some dialyzer warnings (#110)
Mostly this was just configuring dialyzer.  The jsx version update is to
clear a dialyzer crash that the old version caused.
2016-12-30 13:12:41 -08:00
Jon Parise
a774cc968c Protocols -> Protocol in the module namespace (#108)
The singular convention is more common in the Elixir ecosystem. This
matches our singular "Generator" namespace name, too.
2016-12-30 12:41:59 -08:00
Jon Parise
a1efe75d0f Simplify the binary type ID mapping (#106)
We previously defined a @types map that was used to generate function
matches for each known type. Because we only use @types for that one
purpose, it's simpler and more readable to just write out the function
heads explicitly.

This change also renames `int_type` to `type_id` for consistency with
the typespec name.
2016-12-30 12:04:23 -08:00
Jon Parise
0550bcdfcc Tidier serialize/2 function clause formatting (#107) 2016-12-30 12:02:35 -08:00
Jon Parise
a335ce5dff Remove the default serialize/2 match for nil (#105)
The way we serialize `nil` is context-specific and should be handled by
the more specific type-aware clauses below.
2016-12-30 10:06:03 -08:00
Jon Parise
793ff8f20c Use pattern matching to serialize bool values (#104)
This eliminates the private bool_to_int/1 function and lets us return
constant binary result values directly.

We also strictly match on just the true and false atoms.

There is a nominal performance improvement, but nothing significant.
2016-12-30 09:28:49 -08:00
Jon Parise
5a6504aa6b Move skip_field/2 to the Binary protocol module (#103)
We were previously generating private copies of the "skip" functions in
each generated struct module. These functions are generic and have been
moved to the top-level Binary protocol module instead. The reduces the
size of the generated modules by a nice amount.

We only skip unrecognized fields so this code shouldn't be called very
often. In practice, however, we can't predict how often this case will
arise, so the performance of these function is important. Fortunately,
this change doesn't introduce a measurable performance cost.

Lastly, this change adds Binary module documentation and some initial
typespecs.
2016-12-29 21:58:53 -08:00
Jon Parise
ed0ee43c1d Remove Enum.reverse/1 calls from MapSet creation
Sets are inherently unordered so there's no reason to pass ordered lists
to MapSet.new/1. This change results in a minor performance improvement.
2016-12-29 17:14:18 -08:00
Preston Guillory
ba2f03d59d Remove UnionSerializationBenchmark (#101)
The changes to ParserUtils were fumbled and broke BinaryProtocolBenchmark,
which is the more valuable benchmark. UnionSerializationBenchmark was used to
check the performance impact of a particular commit and isn't really worth
maintaining.
2016-12-29 14:10:37 -08:00
Jon Parise
206d8d11ee Merge branch 'master' into thrift_tng 2016-12-29 10:42:33 -08:00
Steve Cohen
4695aaed34 Behaviour module generation (#99)
* Behaviour module generation

For the server side, I imagine that the user would specify a handler
module and pass it into the service. Then it would be called with the
appropriate arguments.
I thought it might be nice to have a behaviour for these modules that
users could be implement.

Behaviours here are fully typed with the correct success types.
2016-12-29 10:42:28 -08:00
Jon Parise
faed878956 Merge branch 'master' into thrift_tng 2016-12-29 09:46:06 -08:00
Preston Guillory
ceceea9a66 Improve iolist optimization (#94)
* Improve iolist optimization

The new function `optimize_iolist` combines the old `merge_binaries` and
`simplify_iolist` functions. It also improves on them slightly, for instance by
terminating iolists with a binary instead of the empty list, and by more
consistently combining adjacent binaries.

* Document iolist optimization steps
2016-12-29 09:28:39 -08:00
Jon Parise
cd95abad2e Simplify the Travis build matrix (#87) 2016-12-29 09:18:26 -08:00
Jon Parise
06d2d75680 Only build dialyxir in :dev
Also, exclude it from the list of runtime applications because it has no
runtime component.
2016-12-29 07:59:34 -08:00
Jon Parise
e79b711818 Add the u field to ParserUtil's User support 2016-12-28 18:01:44 -08:00
Jon Parise
6963b315db Add _bench.exs suffixes to benchfella scripts (#96)
This allows the `mix bench` command to automatically discover its test
scripts.

Also, we only need to build benchfella in :dev and not :test.
2016-12-28 16:35:15 -08:00
Preston Guillory
5a23bea4c6 Specialize boolean field serializer (#93)
It was producing a redundant case statement.

  case foo do
    nil -> <<>>
    _ ->
      [<<2, id::size(16)>>, case foo do
        nil   -> <<0>>
        false -> <<0>>
        _     -> <<1>>
      end]
  end

The new output is simpler, both in the number of case statements and in the
structure of the iolist returned.

  case foo do
    nil   -> <<>>
    false -> <<2, id::size(16), 0>>
    _     -> <<2, id::size(16), 1>>
  end
2016-12-28 15:15:14 -08:00
Steve Cohen
3316411fa1 More robust handling of void return types (#92)
* More robust handling of void return types

The erlang server replies to void responses with <<12, 0, 0, 0, 0>>
which is an empty struct and the stop byte from the respone
struct. Other implementations just reply with the stop byte from the
response struct. We can now parse both.

I also fixed a bug that would occur if the sequence ids or messages
would mismatch. I added tests for all cases.

* Formatting is more consistent
2016-12-28 13:45:56 -08:00
Preston Guillory
0fbee81867 Wrap long lines (#91) 2016-12-28 09:02:33 -08:00
Preston Guillory
14ba9f0183 Match unions with zero or one field set (#90)
* Match unions with zero or one field set

This uses matching in the `serialize` definition to enforce that only unions
with zero or one field can be serialized.
2016-12-27 16:09:04 -08:00
Preston Guillory
446b4c866a Re-order union serialization test fields (#88) 2016-12-27 12:01:33 -08:00
Preston Guillory
60da661c94 Remove bool_to_int (#89)
This moves a bit of complexity from struct_deserializer into
value_serializer(:bool). Things are a little more coherent overall, and it also
helps simplify struct_deserializer, which is getting complex.
2016-12-27 11:43:44 -08:00
Steve Cohen
220e7fe91e Added Union support (#81)
* Added Union support

Unions are basically like structs, but throw an exception if more than
one field is set.
2016-12-27 09:35:47 -08:00
Jon Parise
dbcb12519d Disable Logger console output in the test env
This cleans up `mix test` output a bit. Tests can still explicitly
capture Logger output to verify log output if they like.
2016-12-26 16:48:52 -08:00
Jon Parise
af6208ec8b Move the field serializer into its own function (#85)
This helps reduce the complexity of struct_deserializer/2 a bit without
changing the functionality.
2016-12-26 16:24:14 -08:00
Jon Parise
849573200c Bump the maximum tested OTP release to 19.2 2016-12-26 16:15:10 -08:00
Jon Parise
de5ac6f3f6 Use defp for internal module functions 2016-12-26 16:14:34 -08:00
Steve Cohen
0c7bcac1eb Generated Thrift client (#72)
* Generated Thrift client
This PR is the start of an auto-generated Framed Thrift Binary Protocol
client.
Some work was needed in order to make the client work. This included
modifying the existing generators to:

  * Properly handle void return types
  * Create exceptions using defexception rather than defstruct.

I also modified the thrift test case so it was able to pass context from
setup functions. This is necessary because testing is accomplished by
creating an erlang server off of a test client and running actual thrift
calls against it. I've validated a number of different scenarios, and
all appear to work
2016-12-24 17:29:44 -08:00
Jon Parise
07e7ba276f Format function head match assigments consistently 2016-12-24 16:18:27 -08:00
Jon Parise
9a062553f4 Replace some Enum.map calls with for loops
We weren't using the Enum.map results here so for loops are more
appropriate.
2016-12-24 12:47:50 -08:00
Jon Parise
a527b707d5 Merge pull request #78 from jparise/merger
Merge branch 'master' into thrift_tng
2016-12-23 14:42:21 -08:00
Jon Parise
ac9f53856f Merge branch 'master' into thrift_tng 2016-12-23 14:29:32 -08:00
Jon Parise
e10836ac67 Add a custom Credo configuration file
This is based on Ecto's configuration and tweaks a number of defaults
rules to be more lenient than the stock configuration.
2016-12-23 14:09:27 -08:00
Jon Parise
164d8d6abf We don't need to set MIX_ENV for mix coveralls
This is already handled by our `preferred_cli_env` setup.
2016-12-23 14:08:28 -08:00
Jon Parise
6b2a5a84da Test only the oldest and newest Elixir/OTP pairs
This speeds up our tests builds a bit by eliminating less useful
combinations.
2016-12-23 14:06:03 -08:00
Jon Parise
230106baa8 Try out Ebert for automated code reviews 2016-12-23 12:48:39 -08:00
Steve Cohen
ce6e90efee Added generation for service structs (#71)
* Added generation for service structs

Thrift models RPC function arguments and responses as structs. This adds
generation for struct args and responses

* Addressed PR comments

* Trying to get CI to pass
2016-12-21 13:12:25 -08:00
Preston Guillory
0e339417fa Add exception serialization (#70) 2016-12-20 10:29:42 -08:00
Preston Guillory
8776c40aac Return :error on deserialization failure (#63) 2016-12-13 10:05:26 -08:00
Jon Parise
81816b15cd Include README in docs and fix version linking 2016-12-09 12:35:05 -08:00
Steve Cohen
1e06f48b1e Skip unknown fields (#66)
* Skip unknown fields

If you have an old version of a schema, and are sent a message with
fields from a newer version, you should ignore them and continue
processing.

The old behavior was to crash, which causes problems in production
systems

* Moved binary matches to the function head

* PR fixes
2016-12-09 11:39:20 -08:00
Steve Cohen
1f922d9f33 Remove tng thrift (#67)
* Revert "Added support for ordinals (#62)"

This reverts commit b3ec59a87b.

* Revert "Add serialization test for i32, i64, double (#61)"

This reverts commit 2145c105e8.

* Revert "Fix CompactProtocol warning (#60)"

This reverts commit f5c5a1067e.

* Revert "Support file argument to thrift.generate (#59)"

This reverts commit a35c8a723b.

* Revert "Pure elixir implementation (#54)"

This reverts commit 819216f830.
2016-12-09 11:17:08 -08:00
Jon Parise
4c71e984e7 Fix Elixir 1.4 "function call ambiguity" warnings (#65) 2016-12-09 10:12:01 -08:00
Steve Cohen
b3ec59a87b Added support for ordinals (#62)
It's useful to be able to convert a value to a name, and to
enumerate the names in an enum. This PR adds both.
2016-12-01 11:44:45 -08:00
Preston Guillory
2145c105e8 Add serialization test for i32, i64, double (#61) 2016-11-30 16:25:11 -08:00
Preston Guillory
f5c5a1067e Fix CompactProtocol warning (#60)
A reference was left in the code to this module, but it doesn't exist (yet).
2016-11-30 13:09:35 -08:00
Preston Guillory
a35c8a723b Support file argument to thrift.generate (#59)
This gives the user more fine grained control over which .thrift files are
processed. For instance, a directory might contain many files but you only want
one or a few.
2016-11-30 13:04:44 -08:00
Preston Guillory
819216f830 Pure elixir implementation (#54)
A pure Elixir implementation of the Thrift binary protocol.

This PR includes serialization and deserialization for all thrift types as well as testing to make sure we match the thrift spec (which can be found here: https://erikvanoosten.github.io/thrift-missing-specification/#_binary_encoding)

The binary protocol is generated alongside the thrift data types, yielding a much faster implementation than the apache project's canonical one. 

Our benchmarks (using benchfella) indicate a speedup of between 10 and 20x.

## Binary Protocol Performance
benchmark name |  iterations | average time 
------------------|-----------|---------------
elixir serialization (left as IOList)                   |  2000  | 849.01 µs/op
elixir serialization (iolist_size)                        |  2000  | 933.83 µs/op
elixir serialization (converted to binary)        | 1000   | 1281.23 µs/op
elixir deserialization                                       |  1000   | 1178.46 µs/op
erlang serialization left as IOList                    |   100   | 10284.84 µs/op
erlang serialization (converted to binary)      |   100   | 11588.89 µs/op
erlang deserialization                                      |   100   | 21433.17 µs/op
2016-11-30 11:31:59 -08:00
Jon Parise
4857b40275 Preparing the 1.3.1 release 2016-11-15 16:12:35 -08:00