Skip to content

Instantly share code, notes, and snippets.

@Akii
Created January 10, 2020 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Akii/3a75f3c4aae6108f17c96ef427288702 to your computer and use it in GitHub Desktop.
Save Akii/3a75f3c4aae6108f17c96ef427288702 to your computer and use it in GitHub Desktop.
defmodule Stuff do
use Combine
defmodule ContentRangeRequest do
@moduledoc """
Represents the Range header sent by the client
"""
defstruct key: :id, id: nil, offset: 0, limit: 0, order: :asc
end
@spec parse_range(String.t(), integer(), integer()) :: %ContentRangeRequest{}
def parse_range(range, max_offset \\ 500, max_limit \\ 500) do
range_p =
either(
many1(alphanumeric()) |> ignore(space()) |> many1(alphanumeric()) |> ignore(string("; ")),
many1(alphanumeric()) |> ignore(string("; "))
)
limit_p = fn a -> a |> ignore(string("limit ")) |> integer() |> ignore(string("; ")) end
offset_p = fn a -> a |> ignore(string("offset ")) |> integer() |> ignore(string("; ")) end
order_p = fn a ->
a
|> ignore(string("order "))
|> either(
string("asc"),
string("desc")
)
end
content_range =
Combine.parse(
range,
range_p
|> limit_p.()
|> offset_p.()
|> order_p.()
)
case content_range do
[key, key_val, limit, offset, order] ->
%ContentRangeRequest{
key: String.to_atom(Enum.join(key)),
id: Enum.join(key_val),
offset: min(offset, max_offset),
limit: min(limit, max_limit),
order: if(order == "desc", do: :desc, else: :asc)
}
[key, limit, offset, order] ->
%ContentRangeRequest{
key: String.to_atom(Enum.join(key)),
id: nil,
offset: min(offset, max_offset),
limit: min(limit, max_limit),
order: if(order == "desc", do: :desc, else: :asc)
}
_ ->
%ContentRangeRequest{}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment