|
@@ -2608,7 +2608,7 @@ non_empty_string(_) -> {error, invalid_string}.
|
|
|
servers_sc(Meta0, ParseOpts) ->
|
|
servers_sc(Meta0, ParseOpts) ->
|
|
|
%% if this filed has a default value
|
|
%% if this filed has a default value
|
|
|
%% then it is not NOT required
|
|
%% then it is not NOT required
|
|
|
- %% NOTE: maps:is_key is not the solution beause #{default => undefined} is legit
|
|
|
|
|
|
|
+ %% NOTE: maps:is_key is not the solution because #{default => undefined} is legit
|
|
|
HasDefault = (maps:get(default, Meta0, undefined) =/= undefined),
|
|
HasDefault = (maps:get(default, Meta0, undefined) =/= undefined),
|
|
|
Required = maps:get(required, Meta0, not HasDefault),
|
|
Required = maps:get(required, Meta0, not HasDefault),
|
|
|
Meta = #{
|
|
Meta = #{
|
|
@@ -2661,17 +2661,18 @@ normalize_host_port_str(Str) ->
|
|
|
%% NOTE: Validator is called after converter.
|
|
%% NOTE: Validator is called after converter.
|
|
|
servers_validator(Opts, Required) ->
|
|
servers_validator(Opts, Required) ->
|
|
|
fun(Str0) ->
|
|
fun(Str0) ->
|
|
|
- Str = str(Str0),
|
|
|
|
|
- case Str =:= "" orelse Str =:= "undefined" of
|
|
|
|
|
- true when Required ->
|
|
|
|
|
- %% it's a required field
|
|
|
|
|
- %% but value is set to an empty string (from environment override)
|
|
|
|
|
- %% or when the filed is not set in config file
|
|
|
|
|
|
|
+ case str(Str0) of
|
|
|
|
|
+ "" ->
|
|
|
|
|
+ %% Empty string is not allowed even if the field is not required
|
|
|
|
|
+ %% remove field from config if it's empty
|
|
|
|
|
+ throw("cannot_be_empty");
|
|
|
|
|
+ "undefined" when Required ->
|
|
|
|
|
+ %% when the filed is not set in config file
|
|
|
%% NOTE: assuming nobody is going to name their server "undefined"
|
|
%% NOTE: assuming nobody is going to name their server "undefined"
|
|
|
throw("cannot_be_empty");
|
|
throw("cannot_be_empty");
|
|
|
- true ->
|
|
|
|
|
|
|
+ "undefined" ->
|
|
|
ok;
|
|
ok;
|
|
|
- _ ->
|
|
|
|
|
|
|
+ Str ->
|
|
|
%% it's valid as long as it can be parsed
|
|
%% it's valid as long as it can be parsed
|
|
|
_ = parse_servers(Str, Opts),
|
|
_ = parse_servers(Str, Opts),
|
|
|
ok
|
|
ok
|
|
@@ -2816,20 +2817,17 @@ is_port_number(Port) ->
|
|
|
end.
|
|
end.
|
|
|
|
|
|
|
|
parse_port(Port) ->
|
|
parse_port(Port) ->
|
|
|
- try
|
|
|
|
|
- P = list_to_integer(string:strip(Port)),
|
|
|
|
|
- true = (P > 0),
|
|
|
|
|
- true = (P =< 65535),
|
|
|
|
|
- P
|
|
|
|
|
- catch
|
|
|
|
|
- _:_ ->
|
|
|
|
|
- throw("bad_port_number")
|
|
|
|
|
|
|
+ case string:to_integer(string:strip(Port)) of
|
|
|
|
|
+ {P, ""} when P < 0 -> throw("port_number_too_small");
|
|
|
|
|
+ {P, ""} when P > 65535 -> throw("port_number_too_large");
|
|
|
|
|
+ {P, ""} -> P;
|
|
|
|
|
+ _ -> throw("bad_port_number")
|
|
|
end.
|
|
end.
|
|
|
|
|
|
|
|
quic_feature_toggle(Desc) ->
|
|
quic_feature_toggle(Desc) ->
|
|
|
sc(
|
|
sc(
|
|
|
%% true, false are for user facing
|
|
%% true, false are for user facing
|
|
|
- %% 0, 1 are for internal represtation
|
|
|
|
|
|
|
+ %% 0, 1 are for internal representation
|
|
|
typerefl:alias("boolean", typerefl:union([true, false, 0, 1])),
|
|
typerefl:alias("boolean", typerefl:union([true, false, 0, 1])),
|
|
|
#{
|
|
#{
|
|
|
desc => Desc,
|
|
desc => Desc,
|