ATProto Browser

ATProto Browser

Experimental browser for the Atmosphere

Record data

{
  "uri": "at://did:plc:bnqkww7bjxaacajzvu5gswdf/link.pastesphere.snippet/3ldgv2d3kbs27",
  "cid": "bafyreiage7yur32nxq7rvs3v35ioi63dneptizxy7vrlqoruqd5bscd3yy",
  "value": {
    "body": "defmodule BloomFilter do\n\n  @moduledoc \"\"\"\n  A small Bloom Filter in Elixir\n  \"\"\"\n\n  @default_hash_fns [:sha256, :sha512, :blake2b]\n\n  defstruct bits: <<0::size(64)>>, hash_fns: @default_hash_fns\n\n  @type hashfn :: :crypto.hash_algorithm() | :phash2 | function()\n  @type hashfns :: [hashfn()]\n\n  @type t :: %BloomFilter{\n    bits: bitstring(),\n    hash_fns: hashfns()\n  }\n\n\n  @spec new(pos_integer(), hashfns()) :: t()\n  def new(size \\\\ 64, hash_fns \\\\ @default_hash_fns) do\n    %BloomFilter{bits: <<0::size(size)>>, hash_fns: hash_fns}\n  end\n\n  @spec default_hash_fns() :: hashfns()\n  def default_hash_fns, do: @default_hash_fns\n\n  @spec hash(hashfn(), term()) :: binary()\n  defp hash(:phash2, key), do: <<:erlang.phash2(key)>>\n\n  defp hash(hash_fn, key) when is_function(hash_fn), do: hash_fn.(key)\n\n  defp hash(hash_fn, key) when is_atom(hash_fn), do: :crypto.hash(hash_fn, key)\n\n  @spec hashes(t(), term()) :: [non_neg_integer()]\n  defp hashes(%{hash_fns: hash_fns, bits: bits}, key) do\n    for hash_fn <- hash_fns do\n      hash_fn\n      |> hash(key)\n      |> :binary.decode_unsigned\n      |> rem(bit_size(bits))\n    end\n  end\n\n  @spec bit_at(bitstring(), non_neg_integer()) :: 0 | 1\n  defp bit_at(bits, i) do\n    <<slice::bitstring-size(i), _rest::bitstring>> = bits\n    <<_::size(i - 1), bit::1>> = slice\n    bit\n  end\n\n  @spec set_bit(bitstring(), non_neg_integer(), 0 | 1) :: bitstring()\n  defp set_bit(bits, i, value) do\n    <<slice::bitstring-size(i), rest::bitstring>> = bits\n    <<a::bitstring-size(i - 1), _::1>> = slice\n    <<a::bitstring, value::1, rest::bitstring>>\n  end\n\n  @spec add(t(), term()) :: t()\n  def add(%BloomFilter{bits: bits} = bf, key) do\n    Enum.reduce(hashes(bf, key), bits, fn i, bit_string ->\n      set_bit(bit_string, i, 1)\n    end)\n    |> then(fn bits -> %BloomFilter{bf | bits: bits} end)\n  end\n\n  @spec contains?(t(), term()) :: boolean()\n  def contains?(%BloomFilter{} = bf, key) do\n    Enum.all?(hashes(bf, key), fn i ->\n      bit_at(bf.bits, i) == 1\n    end)\n  end\n\n  defimpl String.Chars, for: __MODULE__ do\n    def to_string(bloom_filter) do\n      \"#BloomFilter\\n\\tbits: \" <> (bloom_filter.bits\n      |> print_bits) <> \"\\n\\thash_fns: \" <> inspect(bloom_filter.hash_fns)\n    end\n\n    def print_bits(bitstring) when is_bitstring(bitstring) do\n      print_bits(bitstring, 0, \"\")\n    end\n\n    defp print_bits(<<bit::size(1), rest::bitstring>>, index, result) do\n      print_bits(rest, index + 1, \"#{result}#{bit}\")\n    end\n\n    defp print_bits(<<>>, _index, result) do\n      result\n    end\n  end\n\n  defimpl Inspect, for: __MODULE__ do\n    def inspect(bloom_filter, _opts) do\n      bloom_filter\n      |> String.Chars.to_string\n    end\n  end\nend",
    "type": "Elixir",
    "$type": "link.pastesphere.snippet",
    "title": "bloomfilter.ex",
    "createdAt": "2024-12-16T17:45:54.379Z",
    "description": "A small Bloom Filter implementation in Elixir"
  }
}