Packages

Implements Google Partial Response protocol in Erlang.

Current section

Files

Jump to
fieldmask src fieldmask.erl
Raw

src/fieldmask.erl

%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
-module(fieldmask).
-export([mask/2, parse/1, apply_mask/2]).
-type value() :: null
| number()
| boolean()
| binary()
| [value()]
| #{binary() => value()}.
%% type of a JSON value represented in jsone's map object format.
-type mask_expr() :: string() | binary().
%% type of mask expression. You may use a string or a binary as mask expression.
-type mask() :: '*'
| {'*', mask()}
| [submask()].
-type submask() :: binary()
| {binary(), mask()}.
%% @doc select the parts specified in the `Mask' expression of a `Value'
-spec mask(mask_expr(), value()) -> value().
mask(Mask, Value) ->
{ok, M} = parse(Mask),
apply_mask(M, Value).
%% @doc parse the `Mask' expression to internal representation
-spec parse(mask_expr()) -> Result
when Result :: {ok, mask()} | Error,
Error :: {error, {Line, module(), Reason}},
Line :: pos_integer(),
Reason :: term().
parse(Mask) ->
case fieldmask_lexer:string(unicode:characters_to_list(Mask)) of
{ok, Tokens, _} ->
fieldmask_parser:parse(Tokens);
{error, Error, _} ->
{error, Error}
end.
%% @doc apply `Mask' in internal representation to a `Value'
-spec apply_mask(mask(), value()) -> value().
apply_mask(Mask, Value) when is_list(Value) ->
[apply_mask(Mask, E) || E <- Value];
apply_mask('*', Value) ->
Value;
apply_mask({'*', Submask}, Value) ->
maps:map(fun(_, V) -> apply_mask(Submask, V) end, Value);
apply_mask({Key, Submask}, Value) when is_binary(Key) ->
apply_mask(Submask, apply_mask(Key, Value));
apply_mask(Mask, Value) when is_list(Mask)->
maps:from_list(
[{case E of
{Key, _} ->
Key;
_ ->
E
end,
apply_mask(E, Value)}|| E <- Mask]);
apply_mask(Key, Value) when is_binary(Key) ->
maps:get(Key, Value).