aboutsummaryrefslogtreecommitdiff
path: root/shard/lib/data/data.ex
blob: 8d2b277dd749f43b4122c9e93c0fb762d923b8f6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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