Packages

A mutable byte array for Erlang.

Current section

Files

Jump to
k6_bytea src k6_bytea.erl
Raw

src/k6_bytea.erl

-module(k6_bytea).
-vsn("1.1.2").
-export([count/0, new/1, delete/1, size/1, get/3, set/3, from_binary/1, to_binary/1]).
-on_load(init/0).
-opaque bytea() :: bytea_opaque_resource_type.
%% The byte array resource handle.
-export_type([bytea/0]).
%% Test support
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
%% ===================================================================
%% NIF initialisation and hooks
%% ===================================================================
%% @private @doc Finds the NIF shared object and attempts to load it.
init() ->
SoName =
case code:priv_dir(?MODULE) of
{error, bad_name} ->
case filelib:is_dir(filename:join(["..", priv])) of
true ->
filename:join(["..", priv, ?MODULE]);
false ->
filename:join([priv, ?MODULE])
end;
Dir ->
filename:join(Dir, ?MODULE)
end,
ok = erlang:load_nif(SoName, 0).
%% @doc Returns the number of currently allocated byte arrays.
-spec count() -> integer().
count() ->
erlang:nif_error(nif_not_loaded).
%% @doc Creates a new byte array and returns it.
-spec new(Size::integer()) -> bytea().
new(_) ->
erlang:nif_error(nif_not_loaded).
%% @doc Frees a byte array immediately. It is no longer valid for use by this
%% module; any attempts will result in `badarg'.
-spec delete(Bytea::bytea()) -> ok.
delete(_) ->
erlang:nif_error(nif_not_loaded).
%% @doc Returns the size of the byte array in bytes.
-spec size(Bytea::bytea()) -> integer().
size(_) ->
erlang:nif_error(nif_not_loaded).
%% @doc Gets `Len' bytes from the byte array, starting at `From'. If the slice
%% specified exceeds any boundaries, `badarg' results.
-spec get(Bytea::bytea(), From::integer(), Len::integer()) -> binary().
get(_, _, _) ->
erlang:nif_error(nif_not_loaded).
%% @doc Replaces the substring of byte array, starting at `From', with `Value'.
%% If the slice so specified exceeds boundaries of the byte array, `badarg'
%% results.
-spec set(Bytea::bytea(), From::integer(), Value::binary()) -> ok.
set(_, _, _) ->
erlang:nif_error(nif_not_loaded).
%% @doc Creates a new byte array from the given binary string.
-spec from_binary(Binary::binary()) -> bytea().
from_binary(Binary) ->
Size = erlang:size(Binary),
Bytea = ?MODULE:new(Size),
?MODULE:set(Bytea, 0, Binary),
Bytea.
%% @doc Gets the entire contents of the byte array as a binary string.
-spec to_binary(Bytea::bytea()) -> binary().
to_binary(Bytea) ->
Size = ?MODULE:size(Bytea),
?MODULE:get(Bytea, 0, Size).
%% ===================================================================
%% Unit tests
%% ===================================================================
-ifdef(TEST).
allocation_test() ->
Bytea = ?MODULE:new(256),
?assertMatch(<<>>, Bytea),
?assertEqual(1, ?MODULE:count()),
?assertEqual(256, ?MODULE:size(Bytea)),
?assertEqual(ok, ?MODULE:delete(Bytea)),
?assertError(badarg, ?MODULE:size(Bytea)),
?assertError(badarg, ?MODULE:delete(Bytea)),
?MODULE:new(128),
erlang:garbage_collect(),
% This seems prone to error.
?assertEqual(0, ?MODULE:count()).
usage_test() ->
Bytea = ?MODULE:new(5),
?assertEqual(<<0, 0, 0, 0, 0>>, ?MODULE:get(Bytea, 0, 5)),
?assertEqual(ok, ?MODULE:set(Bytea, 2, <<$H, $I>>)),
?assertEqual(<<0, $H, $I, 0>>, ?MODULE:get(Bytea, 1, 4)),
?assertEqual(ok, ?MODULE:delete(Bytea)),
?assertError(badarg, ?MODULE:get(Bytea, 0, 1)),
?assertError(badarg, ?MODULE:set(Bytea, 0, <<1>>)).
-endif.