Packages

A library to deal with files in chunks (e.g. chunked file upload).

Current section

Files

Jump to
chunker lib disc_based helper.ex
Raw

lib/disc_based/helper.ex

defmodule Chunker.DiscBased.Helper do
@moduledoc false
alias Chunker.InvalidIndexError
def file_stream(path) do
file = File.stream!(path, [:append], 4096)
{:ok, file}
rescue
e in RuntimeError -> {:error, e}
end
def write_chunk_map(chunked_file, chunks) do
content = Enum.join(chunks, ",")
File.write(chunk_map_path(chunked_file), content)
end
def read_chunk_map(chunked_file) do
case File.read(chunk_map_path(chunked_file)) do
{:ok, content} -> string_to_integer_list(content)
err -> err
end
end
defp chunk_map_path(chunked_file) do
Path.join(chunked_file.chunked_path, "chunk_map")
end
def chunk_path(chunked_file, index) when is_integer(index) and index >= 0 do
Path.join(chunked_file.chunked_path, to_string(index) <> ".chunk")
end
def mapped_chunk_path(chunked_file, chunks, index) when is_integer(index) and index >= 0 do
case Enum.fetch(chunks, index) do
{:ok, chunk_index} -> {:ok, chunk_path(chunked_file, chunk_index)}
:error -> {:error, %InvalidIndexError{}}
end
end
def add_chunk(chunked_file, data, index, chunk_map_modifier) when is_integer(index) do
with {:ok, chunks} <- read_chunk_map(chunked_file),
chunk_index <- next_chunk_index(chunks),
chunk_path <- chunk_path(chunked_file, chunk_index),
:ok <- File.write(chunk_path, data),
new_chunks <- chunk_map_modifier.(chunks, chunk_index, index) do
write_chunk_map(chunked_file, new_chunks)
else
err -> err
end
end
## Helper fucntions ##
defp next_chunk_index(chunks) do
Enum.max(chunks, fn -> -1 end) + 1
end
defp string_split(string, delimiter) do
case String.split(string, delimiter) do
[""] -> []
result -> result
end
end
defp string_to_integer_list(string) do
string_list = string_split(string, ",")
int_list =
string_list
|> Enum.map(&Integer.parse(&1))
|> Enum.map(fn x ->
case x do
{int, _} -> int
err -> err
end
end)
if Enum.any?(int_list, &(!is_integer(&1))) do
{:error, "Integer could not be parsed."}
else
{:ok, int_list}
end
end
end