Last active
May 27, 2019 10:15
-
-
Save andreapavoni/438c3e1ef27b243c4074b89556165892 to your computer and use it in GitHub Desktop.
A simple protol to encode struct(s) as a serialized event payload. When used with `Protocol.derive` it accepts `only` and `except` options for black/white-listing of attributes. Mostly ripped from Poison.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule EventPayloadEncoderError do | |
@type t :: %__MODULE__{message: String.t(), value: any} | |
defexception message: nil, value: nil | |
def message(%{message: nil, value: value}) do | |
"unable to serialize value: #{inspect(value)}" | |
end | |
def message(%{message: message}) do | |
message | |
end | |
end | |
defprotocol EventPayloadEncoder do | |
@fallback_to_any true | |
@spec encode(t) :: Map.t() | |
def encode(value) | |
end | |
defimpl EventPayloadEncoder, for: Map do | |
@compile :inline_list_funcs | |
def encode(map), do: map | |
end | |
defimpl EventPayloadEncoder, for: Any do | |
alias EventPayloadEncoder | |
alias EventPayloadEncoderError | |
defmacro __deriving__(module, struct, options) do | |
deriving(module, struct, options) | |
end | |
def deriving(module, _struct, options) do | |
only = options[:only] | |
except = options[:except] | |
extractor = | |
cond do | |
only -> | |
quote(do: Map.take(struct, unquote(only))) | |
except -> | |
except = [:__struct__ | except] | |
quote(do: Map.drop(struct, unquote(except))) | |
true -> | |
quote(do: :maps.remove(:__struct__, struct)) | |
end | |
quote do | |
defimpl EventPayloadEncoder, for: unquote(module) do | |
def encode(struct) do | |
EventPayloadEncoder.Map.encode(unquote(extractor)) | |
end | |
end | |
end | |
end | |
def encode(%{__struct__: _} = struct) do | |
EventPayloadEncoder.Map.encode(Map.from_struct(struct)) | |
end | |
def encode(value, _options) do | |
raise EventPayloadEncoderError, value: value | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment