Current section
Files
Jump to
Current section
Files
src/purl_composer.erl
-module(purl_composer).
-feature(maybe_expr, enable).
-include("internal/doc.hrl").
-include("purl.hrl").
?MODULEDOC(false).
-export([compose_uri/1]).
-spec compose_uri(Purl) -> uri_string:uri_map() when Purl :: purl:t().
compose_uri(#purl{} = Purl) ->
maps:filter(fun(_Key, Value) -> Value =/= undefined end, #{
fragment => encode_subpath(Purl#purl.subpath),
path => encode_uri_path(Purl),
query => encode_qualifiers(Purl#purl.qualifiers),
scheme => <<"pkg">>
}).
-spec encode_uri_path(Purl) -> unicode:chardata() when Purl :: purl:t().
encode_uri_path(#purl{version = undefined, type = Type, name = Name, namespace = Namespace}) ->
Segments = [Type | encode_namespace(Namespace)] ++ [encode_name(Name)],
Path = lists:join("/", Segments),
iolist_to_binary(Path);
encode_uri_path(#purl{version = Version} = Purl) ->
Path = [
encode_uri_path(Purl#purl{version = undefined}),
"@",
encode_version(Version)
],
iolist_to_binary(Path).
-spec encode_namespace(Namespace) -> [unicode:chardata()] when Namespace :: purl:namespace().
encode_namespace(Namespace) -> lists:map(fun encode/1, Namespace).
-spec encode_name(Name) -> unicode:chardata() when Name :: purl:name().
encode_name(Name) -> encode(Name, "/").
-spec encode_qualifiers(Qualifiers) -> unicode:chardata() | undefined when
Qualifiers :: purl:qualifiers().
encode_qualifiers(Qualifiers) when Qualifiers =:= #{} ->
undefined;
encode_qualifiers(Qualifiers) ->
Encoded = lists:map(
fun({Key, Value}) ->
[Key, "=", encode(Value, "&+")]
end,
maps:to_list(Qualifiers)
),
Joined = lists:join("&", Encoded),
iolist_to_binary(Joined).
-spec encode_version(Version) -> unicode:chardata() when Version :: unicode:chardata().
encode_version(Version) -> encode(Version, "/").
-spec encode_subpath(Subpath) -> unicode:chardata() | undefined when Subpath :: purl:subpath().
encode_subpath([]) ->
undefined;
encode_subpath(Subpath) ->
Encoded = lists:map(fun encode/1, Subpath),
Joined = lists:join("/", Encoded),
iolist_to_binary(Joined).
-spec encode(Data) -> unicode:chardata() when Data :: unicode:chardata().
encode(Data) -> encode(Data, []).
-spec encode(Data, AdditionalCodepoints) -> unicode:chardata() when
Data :: unicode:chardata(), AdditionalCodepoints :: unicode:charlist().
encode(Data, AdditionalCodepoints) ->
AllowedCharacters = uri_string:allowed_characters(),
{reserved, Reserved} = lists:keyfind(reserved, 1, AllowedCharacters),
{unreserved, Unreserved} = lists:keyfind(unreserved, 1, AllowedCharacters),
PurlUnsafe = "#?@[]",
UnescapedCharacters = ((Reserved ++ Unreserved) -- PurlUnsafe) -- AdditionalCodepoints,
uri_string:quote(Data, UnescapedCharacters).