Page MenuHomePhorge

No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/open_api_spex/error.ex b/lib/open_api_spex/error.ex
new file mode 100644
index 0000000..8d65999
--- /dev/null
+++ b/lib/open_api_spex/error.ex
@@ -0,0 +1,58 @@
+defmodule OpenApiSpex.Error do
+ defstruct reason: nil,
+ value: nil,
+ format: nil,
+ type: nil,
+ name: nil,
+ path: []
+
+ def new(:invalid_type, type, value) do
+ %__MODULE__{reason: :invalid_type, type: type, value: value}
+ end
+
+ def new(:polymorphic_failed, value, polymorphic_type) do
+ %__MODULE__{reason: :polymorphic_failed, value: value, type: polymorphic_type}
+ end
+
+ def new(:invalid_format, format, value) do
+ %__MODULE__{reason: :invalid_format, format: format, value: value}
+ end
+
+ def new(:unexpected_field, name) do
+ %__MODULE__{reason: :unexpected_field, name: name}
+ end
+
+ def new(:no_value_required_for_discriminator, property_name) do
+ %__MODULE__{reason: :no_value_required_for_discriminator, name: property_name}
+ end
+
+ def new(:unknown_schema, name) do
+ %__MODULE__{reason: :unknown_schema, name: name}
+ end
+
+ def message(%{reason: :invalid_type, type: type, value: value}) do
+ "Invalid #{type}: #{inspect(value)}"
+ end
+
+ def message(%{reason: :polymorphic_failed, type: polymorphic_type}) do
+ "Failed to cast to any schema in #{polymorphic_type}"
+ end
+
+ def message(%{reason: :unexpected_field, value: value}) do
+ "Unexpected field with value #{inspect(value)}"
+ end
+
+ def message(%{reason: :no_value_required_for_discriminator, name: field}) do
+ "No value for required disciminator property: #{field}"
+ end
+
+ def message(%{reason: :unknown_schema, name: name}) do
+ "Unknown schema: #{name}"
+ end
+end
+
+defimpl String.Chars, for: OpenApiSpex.Error do
+ def to_string(error) do
+ OpenApiSpex.Error.message(error)
+ end
+end
diff --git a/test/cast_primitive_test.exs b/test/cast_primitive_test.exs
new file mode 100644
index 0000000..035bd4a
--- /dev/null
+++ b/test/cast_primitive_test.exs
@@ -0,0 +1,49 @@
+defmodule OpenApiSpex.CastPrimitiveTest do
+ use ExUnit.Case
+ alias OpenApiSpex.{Error, Schema}
+ import OpenApiSpex.CastPrimitive
+
+ describe "cast/3" do
+ test "boolean" do
+ schema = %Schema{type: :boolean}
+ assert cast(true, schema) == {:ok, true}
+ assert cast(false, schema) == {:ok, false}
+ assert cast("true", schema) == {:ok, true}
+ assert cast("false", schema) == {:ok, false}
+ assert {:error, error} = cast("other", schema)
+ assert %Error{reason: :invalid_type} = error
+ assert error.value == "other"
+ end
+
+ test "integer" do
+ schema = %Schema{type: :integer}
+ assert cast(1, schema) == {:ok, 1}
+ assert cast(1.5, schema) == {:ok, 2}
+ assert cast("1", schema) == {:ok, 1}
+ assert cast("1.5", schema) == {:ok, 2}
+ assert {:error, error} = cast("other", schema)
+ assert %Error{reason: :invalid_type} = error
+ assert error.value == "other"
+ end
+
+ test "number" do
+ schema = %Schema{type: :number}
+ assert cast(1, schema) == {:ok, 1.0}
+ assert cast(1.5, schema) == {:ok, 1.5}
+ assert cast("1", schema) == {:ok, 1.0}
+ assert cast("1.5", schema) == {:ok, 1.5}
+ assert {:error, error} = cast("other", schema)
+ assert %Error{reason: :invalid_type} = error
+ assert error.value == "other"
+ end
+
+ test "string" do
+ schema = %Schema{type: :string}
+ assert cast("hello", schema) == {:ok, "hello"}
+ assert cast("", schema) == {:ok, ""}
+ assert {:error, error} = cast(%{}, schema)
+ assert %Error{reason: :invalid_type} = error
+ assert error.value == %{}
+ end
+ end
+end
diff --git a/test/support/cast_primitive.ex b/test/support/cast_primitive.ex
new file mode 100644
index 0000000..af8ff09
--- /dev/null
+++ b/test/support/cast_primitive.ex
@@ -0,0 +1,77 @@
+defmodule OpenApiSpex.CastPrimitive do
+ @moduledoc false
+ alias OpenApiSpex.Error
+
+ def cast(value, _schema, _schemas \\ %{})
+
+ def cast(value, %{type: :boolean}, _schemas),
+ do: cast_boolean(value)
+
+ def cast(value, %{type: :integer}, _schemas),
+ do: cast_integer(value)
+
+ def cast(value, %{type: :number}, _schemas),
+ do: cast_number(value)
+
+ def cast(value, %{type: :string}, _schemas),
+ do: cast_string(value)
+
+ ## Private functions
+
+ defp cast_boolean(value) when is_boolean(value) do
+ {:ok, value}
+ end
+
+ defp cast_boolean("true"), do: {:ok, true}
+ defp cast_boolean("false"), do: {:ok, false}
+
+ defp cast_boolean(value) do
+ {:error, Error.new(:invalid_type, :integer, value)}
+ end
+
+ defp cast_integer(value) when is_integer(value) do
+ {:ok, value}
+ end
+
+ defp cast_integer(value) when is_number(value) do
+ {:ok, round(value)}
+ end
+
+ defp cast_integer(value) when is_binary(value) do
+ case Float.parse(value) do
+ {value, ""} -> cast_integer(value)
+ _ -> {:error, Error.new(:invalid_type, :integer, value)}
+ end
+ end
+
+ defp cast_integer(value) do
+ {:error, Error.new(:invalid_type, :integer, value)}
+ end
+
+ defp cast_number(value) when is_number(value) do
+ {:ok, value}
+ end
+
+ defp cast_number(value) when is_integer(value) do
+ {:ok, value / 1}
+ end
+
+ defp cast_number(value) when is_binary(value) do
+ case Float.parse(value) do
+ {value, ""} -> {:ok, value}
+ _ -> {:error, Error.new(:invalid_type, :number, value)}
+ end
+ end
+
+ defp cast_number(value) do
+ {:error, Error.new(:invalid_type, :number, value)}
+ end
+
+ defp cast_string(value) when is_binary(value) do
+ {:ok, value}
+ end
+
+ defp cast_string(value) do
+ {:error, Error.new(:invalid_type, :string, value)}
+ end
+end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 30, 5:49 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41510
Default Alt Text
(5 KB)

Event Timeline