% @doc called ltr to disambiguate from "char" % % In "A + B + AB", this is one of the individual letters. % % a letter is a binary. atom is more natural representation but this is http, % can't be spamming the atoms table. % % mathematically, this is a variable like "a", "b", "c", etc -module(wfc_ltr). -export_type([ ltr/0 ]). -export([ validate/1, from_binary/1, to_binary/1 ]). % @doc % a character is binary data that would be a valid atom % % [a-z][A-Za-z0-9_]+ % % - leads with lowercase letter % - underscores ok % - numbers ok % - no non-ascii chars -opaque ltr() :: {c, binary()}. %%----------------------- %% constructors/destructors %%----------------------- -spec validate(Ltr) -> Result when Ltr :: ltr(), Result :: ok | {error, Reason :: string()}. % @doc validate if a candidate ltr is well-formed and the inner binary is % legal validate({c, Binary}) -> case from_binary(Binary) of {ok, {c, X}} when X =:= Binary -> ok; Error -> Error end; validate(Term) -> Error = wfc_utils:emsg("wfc_ltr:validate failed; malformed ltr: ~p", [Term]), {error, Error}. -spec from_binary(Binary) -> Result when Binary :: binary(), Result :: {ok, ltr()} | {error, Reason :: string()}. % @doc % make sure the binary is a legal ltr and wrap it in a {c, Binary} tuple % @end %% initial char must be [a-z] from_binary(<>) when $a =< L, L =< $z -> new2(<>, Rest); from_binary(Char = <>) -> {error, wfc_utils:emsg("wfc_ltr:from_binary(~p): illegal lead character: ~p", [Char, L])}; from_binary(Char) -> wfc_utils:err("wfc_ltr:from_binary(~p): malformed argument", [Char]). %% rest must be [A-Za-z0-9_] new2(Acc, <>) when ($A =< L andalso L =< $Z) orelse ($a =< L andalso L =< $z) orelse ($0 =< L andalso L =< $9) orelse (L =:= $_) -> new2(<>, Rest); new2(Acc, <<>>) -> {ok, {c, Acc}}; new2(Acc, Rest = <>) -> WholeChar = <>, Error = wfc_utils:emsg("wfc_ltr:new2(~p, ~p): illegal character in ltr: ~p; WholeChar: ~p", [Acc, Rest, BadChar, WholeChar]), {error, Error}. -spec to_binary(ltr()) -> Result when Result :: {ok, binary()} | {error, string()}. to_binary({c, X}) -> {ok, X}; to_binary(Bad) -> {error, wfc_utils:str("wfc_ltr:to_binary: bad letter: ~tp", [Bad])}.