# Copyright 2021 Nicolas Jouanin # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # SPDX-FileCopyrightText: 2021 Nicolas Jouanin # SPDX-License-Identifier: Apache-2.0 defmodule Polyjuice.Util.Identifiers.V1.RoomIdentifier do @type t :: %__MODULE__{ sigil: String.t(), opaque_id: String.t(), domain: String.t() } alias Polyjuice.Util.Identifiers.V1.RoomIdentifier @enforce_keys [:sigil, :opaque_id, :domain] defstruct [ :sigil, :opaque_id, :domain ] @sigil "!" @behaviour Polyjuice.Util.Identifiers @randomize_length 15 def generate(domain) do {:ok, room} = Polyjuice.Util.Randomizer.randomize(@randomize_length, :downcase_numeric) |> Polyjuice.Util.Identifiers.V1.RoomIdentifier.new(domain) room end @impl Polyjuice.Util.Identifiers def new!(identifier) do case parse(identifier) do {:ok, room} -> room {:error, error} -> raise ArgumentError, to_string(error) end end @impl Polyjuice.Util.Identifiers def new([opaque_id, domain]), do: new(opaque_id, domain) @impl Polyjuice.Util.Identifiers def new({opaque_id, domain}), do: new(opaque_id, domain) @impl Polyjuice.Util.Identifiers def new(%{opaque_id: opaque_id, domain: domain}), do: new(opaque_id, domain) @impl Polyjuice.Util.Identifiers def new(identifier), do: parse(identifier) @spec new(String.t(), String.t()) :: {:ok, RoomIdentifier.t()} | {:error, atom} def new(opaque_id, domain) do room = %RoomIdentifier{sigil: @sigil, opaque_id: opaque_id, domain: domain} if valid?(room) do {:ok, room} else {:error, :invalid_room_id} end end @impl Polyjuice.Util.Identifiers def valid?(%RoomIdentifier{} = this) do String.length(this.domain) > 0 && String.length(this.opaque_id) > 0 end @impl Polyjuice.Util.Identifiers def valid?(identifier_string) do case parse(identifier_string) do {:ok, _} -> true _ -> false end end def fqid(%RoomIdentifier{} = this) do "#{@sigil}#{this.opaque_id}:#{this.domain}" end @impl Polyjuice.Util.Identifiers @spec parse(String.t()) :: {:ok, RoomIdentifier.t()} | {:error, atom} def parse(id) do with @sigil <> id <- id, [opaque_id, domain] <- String.split(id, ":", parts: 2, trim: true) do new(opaque_id, domain) else _ -> {:error, :invalid_room_id} end end end defimpl String.Chars, for: Polyjuice.Util.Identifiers.V1.RoomIdentifier do def to_string(this), do: Polyjuice.Util.Identifiers.V1.RoomIdentifier.fqid(this) end