defmodule SData do @moduledoc """ Utility functions Compare functions are functions that compares stored items and provides a total order. They must return: - `:after` if the first argument is more recent - `:duplicate` if the two items are the same - `:before` if the first argument is older These functions must only return :duplicate for equal items. """ @doc""" Calculate the hash of an Erlang term by first converting it to its binary representation. Equivalent to `bin_hash(term_bin(term))`. """ def term_hash(term, algo \\ :sha256) do :crypto.hash(algo, (:erlang.term_to_binary term)) end @doc""" Convert any Erlang term to a binary representation. """ def term_bin(term) do :erlang.term_to_binary term end @doc""" Calculate the hash of a binary. """ def bin_hash(bin, algo \\ :sha256) do :crypto.hash(algo, bin) end @doc""" Calculate the hash of a file. """ def file_hash(path, algo \\ :sha256) do File.stream!(path, [], 65536) |> Enum.reduce(:crypto.hash_init(algo), &(:crypto.hash_update(&2, &1))) |> :crypto.hash_final() end @doc""" Recover an Erlang term from its binary representation. """ def term_unbin(bin) do :erlang.binary_to_term(bin, [:safe]) end @doc""" Compare function for arbitrary terms using the Erlang order """ def cmp_term(a, b) do cond do a > b -> :after a < b -> :before a == b -> :duplicate end end @doc""" Compare function for timestamped strings """ def cmp_ts_str({ts1, str1}, {ts2, str2}) do cond do ts1 > ts2 -> :after ts1 < ts2 -> :before str1 > str2 -> :after str1 < str2 -> :before true -> :duplicate end end @doc""" Merge function for nils """ def merge_true(true, true), do: true end