Current section
Files
Jump to
Current section
Files
src/sift@string.erl
-module(sift@string).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/sift/string.gleam").
-export([min_length/2, max_length/2, length/2, non_empty/1, matches/2, starts_with/2, ends_with/2, contains/2, email/1, url/1, uuid/1, numeric/1, alpha/1, alphanumeric/1, trimmed/1, one_of/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" String validators — length, pattern matching, format checks (email, url, uuid).\n").
-file("src/sift/string.gleam", 7).
?DOC(" String must have at least n graphemes\n").
-spec min_length(integer(), EFM) -> fun((binary()) -> {ok, binary()} |
{error, EFM}).
min_length(N, Msg) ->
fun(Value) -> case string:length(Value) >= N of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 17).
?DOC(" String must have at most n graphemes\n").
-spec max_length(integer(), EFP) -> fun((binary()) -> {ok, binary()} |
{error, EFP}).
max_length(N, Msg) ->
fun(Value) -> case string:length(Value) =< N of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 27).
?DOC(" String must have exactly n graphemes\n").
-spec length(integer(), EFS) -> fun((binary()) -> {ok, binary()} | {error, EFS}).
length(N, Msg) ->
fun(Value) -> case string:length(Value) =:= N of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 37).
?DOC(" String must not be empty (shorthand for min_length(1))\n").
-spec non_empty(EFV) -> fun((binary()) -> {ok, binary()} | {error, EFV}).
non_empty(Msg) ->
min_length(1, Msg).
-file("src/sift/string.gleam", 48).
?DOC(
" String must match the given regex pattern.\n"
"\n"
" ```gleam\n"
" let validator = string.matches(\"^[A-Z]{3}$\", \"must be 3 uppercase letters\")\n"
" validator(\"ABC\") // -> Ok(\"ABC\")\n"
" validator(\"abc\") // -> Error(\"must be 3 uppercase letters\")\n"
" ```\n"
).
-spec matches(binary(), EFY) -> fun((binary()) -> {ok, binary()} | {error, EFY}).
matches(Pattern, Msg) ->
fun(Value) -> case gleam@regexp:from_string(Pattern) of
{ok, Re} ->
case gleam@regexp:check(Re, Value) of
true ->
{ok, Value};
false ->
{error, Msg}
end;
{error, _} ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 78).
?DOC(" String must start with the given prefix\n").
-spec starts_with(binary(), EGF) -> fun((binary()) -> {ok, binary()} |
{error, EGF}).
starts_with(Prefix, Msg) ->
fun(Value) -> case gleam_stdlib:string_starts_with(Value, Prefix) of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 88).
?DOC(" String must end with the given suffix\n").
-spec ends_with(binary(), EGI) -> fun((binary()) -> {ok, binary()} |
{error, EGI}).
ends_with(Suffix, Msg) ->
fun(Value) -> case gleam_stdlib:string_ends_with(Value, Suffix) of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 98).
?DOC(" String must contain the given substring\n").
-spec contains(binary(), EGL) -> fun((binary()) -> {ok, binary()} | {error, EGL}).
contains(Substring, Msg) ->
fun(Value) -> case gleam_stdlib:contains_string(Value, Substring) of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 114).
?DOC(
" Must look like an email (contains exactly one @, something before and after).\n"
"\n"
" ```gleam\n"
" let validator = string.email(\"invalid email\")\n"
" validator(\"jo@example.com\") // -> Ok(\"jo@example.com\")\n"
" validator(\"nope\") // -> Error(\"invalid email\")\n"
" ```\n"
).
-spec email(EGO) -> fun((binary()) -> {ok, binary()} | {error, EGO}).
email(Msg) ->
matches(<<"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"/utf8>>, Msg).
-file("src/sift/string.gleam", 125).
?DOC(
" Must look like a URL (http:// or https://).\n"
"\n"
" ```gleam\n"
" let validator = string.url(\"invalid url\")\n"
" validator(\"https://example.com\") // -> Ok(\"https://example.com\")\n"
" validator(\"example.com\") // -> Error(\"invalid url\")\n"
" ```\n"
).
-spec url(EGR) -> fun((binary()) -> {ok, binary()} | {error, EGR}).
url(Msg) ->
matches(<<"^https?://[^\\s]+$"/utf8>>, Msg).
-file("src/sift/string.gleam", 136).
?DOC(
" Must be a valid UUID v4 format.\n"
"\n"
" ```gleam\n"
" let validator = string.uuid(\"invalid uuid\")\n"
" validator(\"550e8400-e29b-41d4-a716-446655440000\") // -> Ok(..)\n"
" validator(\"not-a-uuid\") // -> Error(\"invalid uuid\")\n"
" ```\n"
).
-spec uuid(EGU) -> fun((binary()) -> {ok, binary()} | {error, EGU}).
uuid(Msg) ->
matches(
<<"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"/utf8>>,
Msg
).
-file("src/sift/string.gleam", 150).
?DOC(
" All characters must be digits (0-9).\n"
"\n"
" ```gleam\n"
" let validator = string.numeric(\"digits only\")\n"
" validator(\"123\") // -> Ok(\"123\")\n"
" validator(\"12a\") // -> Error(\"digits only\")\n"
" ```\n"
).
-spec numeric(EGX) -> fun((binary()) -> {ok, binary()} | {error, EGX}).
numeric(Msg) ->
matches(<<"^[0-9]+$"/utf8>>, Msg).
-file("src/sift/string.gleam", 161).
?DOC(
" All characters must be letters (a-zA-Z).\n"
"\n"
" ```gleam\n"
" let validator = string.alpha(\"letters only\")\n"
" validator(\"abc\") // -> Ok(\"abc\")\n"
" validator(\"abc1\") // -> Error(\"letters only\")\n"
" ```\n"
).
-spec alpha(EHA) -> fun((binary()) -> {ok, binary()} | {error, EHA}).
alpha(Msg) ->
matches(<<"^[a-zA-Z]+$"/utf8>>, Msg).
-file("src/sift/string.gleam", 172).
?DOC(
" All characters must be letters or digits.\n"
"\n"
" ```gleam\n"
" let validator = string.alphanumeric(\"alphanumeric only\")\n"
" validator(\"abc123\") // -> Ok(\"abc123\")\n"
" validator(\"abc 123\") // -> Error(\"alphanumeric only\")\n"
" ```\n"
).
-spec alphanumeric(EHD) -> fun((binary()) -> {ok, binary()} | {error, EHD}).
alphanumeric(Msg) ->
matches(<<"^[a-zA-Z0-9]+$"/utf8>>, Msg).
-file("src/sift/string.gleam", 183).
?DOC(
" String must have no leading or trailing whitespace.\n"
"\n"
" ```gleam\n"
" let validator = string.trimmed(\"no surrounding spaces\")\n"
" validator(\"hello\") // -> Ok(\"hello\")\n"
" validator(\" hello\") // -> Error(\"no surrounding spaces\")\n"
" ```\n"
).
-spec trimmed(EHG) -> fun((binary()) -> {ok, binary()} | {error, EHG}).
trimmed(Msg) ->
fun(Value) -> case gleam@string:trim(Value) =:= Value of
true ->
{ok, Value};
false ->
{error, Msg}
end end.
-file("src/sift/string.gleam", 192).
-spec list_contains(list(binary()), binary()) -> boolean().
list_contains(Items, Target) ->
case Items of
[] ->
false;
[First | Rest] ->
case First =:= Target of
true ->
true;
false ->
list_contains(Rest, Target)
end
end.
-file("src/sift/string.gleam", 68).
?DOC(
" String must be one of the given values.\n"
"\n"
" ```gleam\n"
" let validator = string.one_of([\"admin\", \"user\", \"guest\"], \"invalid role\")\n"
" validator(\"admin\") // -> Ok(\"admin\")\n"
" validator(\"root\") // -> Error(\"invalid role\")\n"
" ```\n"
).
-spec one_of(list(binary()), EGC) -> fun((binary()) -> {ok, binary()} |
{error, EGC}).
one_of(Values, Msg) ->
fun(Value) -> case list_contains(Values, Value) of
true ->
{ok, Value};
false ->
{error, Msg}
end end.