defmodule Z.String do
@moduledoc """
A module for validating a string
"""
alias Z.{Result, Error, Issue, Any}
use Z.Type, options: Z.Any.__z__(:options) ++ [:trim, :length]
def check(result, :conversions, rules, context) do
result
|> Any.check(:conversions, rules, context)
end
def check(result, :mutations, rules, context) do
result
|> Any.check(:mutations, rules, context)
|> maybe_check(:trim, rules, context)
end
def check(result, :assertions, rules, context) do
result
|> Any.check(:assertions, rules, context)
|> maybe_check(:length, rules, context)
end
def check(result, _rule, _options, _context) when result.value == nil do
result
end
def check(result, :type, options, context) when not is_binary(result.value) do
message = Keyword.get(options, :message, "input is not a valid string")
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_type(),
message,
context
)
)
end
def check(result, :type, options, context) do
if String.valid?(result.value) do
result
else
message = Keyword.get(options, :message, "input is not a valid string")
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_string(),
message,
context
)
)
end
end
def check(result, _rule, _options, _context) when not is_binary(result.value) do
result
end
def check(result, :trim, false, _context) do
result
end
def check(result, :trim, true, _context) do
result |> Result.set_value(result.value |> String.trim())
end
def check(result, :trim, to_trim, context) when not is_binary(to_trim) do
message = "unable to trim string with to_trim: #{inspect(to_trim)}, to_trim must be a string"
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_arguments(),
message,
context
)
)
end
def check(result, :trim, to_trim, _context) do
result |> Result.set_value(result.value |> String.trim(to_trim))
end
def check(result, :length, {length, _options}, context) when not is_integer(length) do
message = "unable to check length with length: #{inspect(length)}, length must be an integer"
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_arguments(),
message,
context
)
)
end
def check(result, :length, {length, options}, context) do
cond do
String.length(result.value) < length ->
message = Keyword.get(options, :message, "input does not have correct length")
result
|> Result.add_issue(
Issue.new(
Error.Codes.too_small(),
message,
context
)
)
String.length(result.value) > length ->
message = Keyword.get(options, :message, "input does not have correct length")
result
|> Result.add_issue(
Issue.new(
Error.Codes.too_big(),
message,
context
)
)
true ->
result
end
end
def check(result, :length, length, context) do
check(result, :length, {length, []}, context)
end
def check(result, :min, {length, _options}, context) when not is_integer(length) do
message =
"unable to check min length with length: #{inspect(length)}, length must be an integer"
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_arguments(),
message,
context
)
)
end
def check(result, :min, {length, options}, context) do
message = Keyword.get(options, :message, "input is too short")
if String.length(result.value) >= length do
result
else
result
|> Result.add_issue(
Issue.new(
Error.Codes.too_small(),
message,
context
)
)
end
end
def check(result, :min, length, context) do
check(result, :min, {length, []}, context)
end
def check(result, :max, {length, _options}, context) when not is_integer(length) do
message =
"unable to check max length with length: #{inspect(length)}, length must be an integer"
result
|> Result.add_issue(
Issue.new(
Error.Codes.invalid_arguments(),
message,
context
)
)
end
def check(result, :max, {length, options}, context) do
message = Keyword.get(options, :message, "input is too long")
if String.length(result.value) <= length do
result
else
result
|> Result.add_issue(
Issue.new(
Error.Codes.too_big(),
message,
context
)
)
end
end
def check(result, :max, length, context) do
check(result, :max, {length, []}, context)
end
end