defmodule Stellar.TxBuild.TimeBounds do @moduledoc """ `TimeBounds` struct definition. """ alias StellarBase.XDR.{TimePoint, TimeBounds, OptionalTimeBounds} @behaviour Stellar.TxBuild.XDR @type unix_date_time :: non_neg_integer() @type date_time :: DateTime.t() | unix_date_time() @type validation :: {:ok, unix_date_time()} | {:error, :atom} @type t :: %__MODULE__{min_time: unix_date_time(), max_time: unix_date_time()} defstruct [:min_time, :max_time] @impl true def new(time_bounds \\ [min_time: 0, max_time: 0], opts \\ []) def new(:none, _opts), do: new(min_time: 0, max_time: 0) def new([min_time: min_time, max_time: max_time], _opts) do with {:ok, min_time} <- validate_date_time(min_time), {:ok, max_time} <- validate_date_time(max_time) do %__MODULE__{min_time: min_time, max_time: max_time} end end @impl true def to_xdr(%__MODULE__{min_time: 0, max_time: 0}) do OptionalTimeBounds.new() end def to_xdr(%__MODULE__{min_time: min_time, max_time: max_time}) do min_time = TimePoint.new(min_time) max_time = TimePoint.new(max_time) min_time |> TimeBounds.new(max_time) |> OptionalTimeBounds.new() end @spec set_timeout(max_time :: date_time()) :: t() | {:error, atom()} def set_timeout(max_time), do: new(min_time: 0, max_time: max_time) @spec validate_date_time(date_time :: date_time()) :: validation() defp validate_date_time(%DateTime{} = date_time) do {:ok, DateTime.to_unix(date_time)} end defp validate_date_time(date_time) when is_integer(date_time) and date_time >= 0, do: {:ok, date_time} defp validate_date_time(_date_time), do: {:error, :invalid_time_bounds} end