62
62
63
63
-include (" avro_internal.hrl" ).
64
64
65
- -opaque store () :: ets :tab () | {dict , dict :dict ()}.
66
- -type option_key () :: access | name | dict .
65
+ -type store () :: ets :tab () | {dict , dict :dict ()} | map () .
66
+ -type option_key () :: access | name | dict | map .
67
67
-type options () :: [option_key () | {option_key (), term ()}].
68
68
-type filename () :: file :filename_all ().
69
69
@@ -81,12 +81,20 @@ new() -> new([]).
81
81
% % mode in ets:new and defines what processes can have access to
82
82
% % * `{name, atom()}' - used to create a named ets table.
83
83
% % * `dict' - use dict as store backend, ignore `access' and `name' options
84
+ % % * `map' - use map as store backend, ignore `access' and `name' options
84
85
% % @end
85
86
-spec new (options ()) -> store ().
86
87
new (Options ) ->
87
88
case proplists :get_bool (dict , Options ) of
88
- true -> {dict , dict :new ()};
89
- false -> new_ets (Options )
89
+ true ->
90
+ {dict , dict :new ()};
91
+ false ->
92
+ case proplists :get_bool (map , Options ) of
93
+ true ->
94
+ #{};
95
+ false ->
96
+ new_ets (Options )
97
+ end
90
98
end .
91
99
92
100
% % @doc Create a new schema store and improt the given schema JSON files.
@@ -98,6 +106,7 @@ new(Options, Files) ->
98
106
% % @doc Return true if the given arg is a schema store.
99
107
-spec is_store (term ()) -> boolean ().
100
108
is_store ({dict , _ }) -> true ;
109
+ is_store (Map ) when is_map (Map ) -> true ;
101
110
is_store (T ) -> is_integer (T ) orelse is_atom (T ) orelse is_reference (T ).
102
111
103
112
% % @doc Make a schema lookup function from store.
@@ -143,12 +152,13 @@ import_schema_json(Json, Store) ->
143
152
% % @doc Delete the ets table.
144
153
-spec close (store ()) -> ok .
145
154
close ({dict , _ }) -> ok ;
155
+ close (Map ) when is_map (Map ) -> ok ;
146
156
close (Store ) ->
147
157
ets :delete (Store ),
148
158
ok .
149
159
150
160
% % @doc To make dialyzer happy.
151
- -spec ensure_store (atom () | integer () | reference () | { dict , dict : dict ()} ) ->
161
+ -spec ensure_store (atom () | integer () | reference () | store () ) ->
152
162
store ().
153
163
ensure_store (Store ) ->
154
164
true = is_store (Store ),
@@ -194,6 +204,7 @@ get_all_types(Store) ->
194
204
195
205
-spec to_list (store ()) -> [{name (), avro_type ()}].
196
206
to_list ({dict , Dict }) -> dict :to_list (Dict );
207
+ to_list (Map ) when is_map (Map ) -> maps :to_list (Map );
197
208
to_list (Store ) -> ets :tab2list (Store ).
198
209
199
210
-spec new_ets (options ()) -> store ().
@@ -212,8 +223,8 @@ new_ets(Options) ->
212
223
-spec add_by_assigned_name (undefined | name_raw (),
213
224
type_or_name (), store ()) -> store ().
214
225
add_by_assigned_name (undefined , _Type , Store ) -> Store ;
215
- add_by_assigned_name (AssignedName , Type , Store ) ->
216
- do_add_type_by_names ([ ? NAME (AssignedName )], Type , Store ).
226
+ add_by_assigned_name (AssignedName , TypeOrName , Store ) ->
227
+ add_type_by_name ( ? NAME (AssignedName ), TypeOrName , Store ).
217
228
218
229
% % @private Parse file basename. try to strip ".avsc" or ".json" extension.
219
230
-spec parse_basename (filename ()) -> name ().
@@ -241,13 +252,19 @@ import_schema_json(AssignedName, Json, Store) ->
241
252
do_add_type (Type , Store ) ->
242
253
FullName = avro :get_type_fullname (Type ),
243
254
Aliases = avro :get_aliases (Type ),
244
- do_add_type_by_names ([FullName |Aliases ], Type , Store ).
255
+ Store1 = add_type_by_name (FullName , Type , Store ),
256
+ add_aliases (Aliases , FullName , Store1 ).
257
+
258
+ add_aliases ([], _FullName , Store ) ->
259
+ Store ;
260
+ add_aliases ([Alias | More ], FullName , Store ) ->
261
+ NewStore = put_type_to_store (Alias , FullName , Store ),
262
+ add_aliases (More , FullName , NewStore ).
245
263
246
264
% % @private
247
- -spec do_add_type_by_names ([fullname ()], avro_type (), store ()) ->
265
+ -spec add_type_by_name ([fullname ()], avro_type (), store ()) ->
248
266
store () | no_return ().
249
- do_add_type_by_names ([], _Type , Store ) -> Store ;
250
- do_add_type_by_names ([Name |Rest ], Type , Store ) ->
267
+ add_type_by_name (Name , Type , Store ) ->
251
268
case get_type_from_store (Name , Store ) of
252
269
{ok , Type } ->
253
270
Store ;
@@ -257,27 +274,45 @@ do_add_type_by_names([Name|Rest], Type, Store) ->
257
274
% % old / new types.
258
275
erlang :error ({name_clash , Name , Type , OtherType });
259
276
false ->
260
- Store1 = put_type_to_store (Name , Type , Store ),
261
- do_add_type_by_names (Rest , Type , Store1 )
277
+ put_type_to_store (Name , Type , Store )
262
278
end .
263
279
264
280
% % @private
265
- -spec put_type_to_store (fullname (), avro_type (), store ()) -> store ().
281
+ -spec put_type_to_store (fullname (), name () | avro_type (), store ()) -> store ().
266
282
put_type_to_store (Name , Type , {dict , Dict }) ->
267
283
NewDict = dict :store (Name , Type , Dict ),
268
284
{dict , NewDict };
285
+ put_type_to_store (Name , Type , Map ) when is_map (Map ) ->
286
+ Map #{Name => Type };
269
287
put_type_to_store (Name , Type , Store ) ->
270
288
true = ets :insert (Store , {Name , Type }),
271
289
Store .
272
290
273
- % % @private
291
+ % % @private Get type by name or alias.
274
292
-spec get_type_from_store (fullname (), store ()) -> false | {ok , avro_type ()}.
275
- get_type_from_store (Name , {dict , Dict }) ->
293
+ get_type_from_store (NameRef , Store ) ->
294
+ case do_get_type_from_store (NameRef , Store ) of
295
+ false ->
296
+ false ;
297
+ {ok , FullName } when is_binary (FullName ) ->
298
+ do_get_type_from_store (FullName , Store );
299
+ {ok , Type } ->
300
+ {ok , Type }
301
+ end .
302
+
303
+ % % @private
304
+ -spec do_get_type_from_store (fullname (), store ()) -> false | {ok , fullname () | avro_type ()}.
305
+ do_get_type_from_store (Name , {dict , Dict }) ->
276
306
case dict :find (Name , Dict ) of
277
307
error -> false ;
278
308
{ok , Type } -> {ok , Type }
279
309
end ;
280
- get_type_from_store (Name , Store ) ->
310
+ do_get_type_from_store (Name , Map ) when is_map (Map ) ->
311
+ case maps :find (Name , Map ) of
312
+ error -> false ;
313
+ {ok , Type } -> {ok , Type }
314
+ end ;
315
+ do_get_type_from_store (Name , Store ) ->
281
316
case ets :lookup (Store , Name ) of
282
317
[] -> false ;
283
318
[{Name , Type }] -> {ok , Type }
0 commit comments