     end
   end
 
-  @spec do_not(Xema.Schema.t(), any) :: result
-  defp do_not(%{not: nil}, _value), do: :ok
-
-  defp do_not(%{not: schema}, value) do
-    case validate(schema, value) do
+  @spec do_not(Xema.Schema.t(), any, keyword) :: result
+  defp do_not(%{not: nil}, _value, _opts), do: :ok
+
+  defp do_not(%{not: schema}, value, opts) do
+    case validate(schema, value, opts) do
       :ok -> {:error, :not}
       _ -> :ok
     end
   end
 
-  @spec all_of(Xema.Schema.t(), any) :: result
-  defp all_of(%{all_of: nil}, _value), do: :ok
-
-  defp all_of(%{all_of: schemas}, value) do
-    case do_all_of(schemas, value) do
+  @spec all_of(Xema.Schema.t(), any, keyword) :: result
+  defp all_of(%{all_of: nil}, _value, _opts), do: :ok
+
+  defp all_of(%{all_of: schemas}, value, opts) do
+    case do_all_of(schemas, value, opts) do
       true -> :ok
       false -> {:error, :all_of}
     end
   end
 
-  @spec do_all_of(list, any) :: boolean
-  defp do_all_of(schemas, value),
-    do: Enum.all?(schemas, fn schema -> validate(schema, value) == :ok end)
-
-  @spec any_of(Xema.Schema.t(), any) :: result
-  defp any_of(%{any_of: nil}, _value), do: :ok
-
-  defp any_of(%{any_of: schemas}, value) do
-    case do_any_of(schemas, value) do
+  @spec do_all_of(list, any, keyword) :: boolean
+  defp do_all_of(schemas, value, opts),
+    do: Enum.all?(schemas, fn schema -> validate(schema, value, opts) == :ok end)
+
+  @spec any_of(Xema.Schema.t(), any, keyword) :: result
+  defp any_of(%{any_of: nil}, _value, _opts), do: :ok
+
+  defp any_of(%{any_of: schemas}, value, opts) do
+    case do_any_of(schemas, value, opts) do
       true -> :ok
       false -> {:error, :any_of}
     end
   end
 
-  @spec do_any_of(list, any) :: boolean
-  defp do_any_of(schemas, value),
-    do: Enum.any?(schemas, fn schema -> validate(schema, value) == :ok end)
-
-  @spec one_of(Xema.Schema.t(), any) :: result
-  defp one_of(%{one_of: nil}, _value), do: :ok
-
-  defp one_of(%{one_of: schemas}, value) do
-    case do_one_of(schemas, value) == 1 do
+  @spec do_any_of(list, any, keyword) :: boolean
+  defp do_any_of(schemas, value, opts),
+    do: Enum.any?(schemas, fn schema -> validate(schema, value, opts) == :ok end)
+
+  @spec one_of(Xema.Schema.t(), any, keyword) :: result
+  defp one_of(%{one_of: nil}, _value, _opts), do: :ok
+
+  defp one_of(%{one_of: schemas}, value, opts) do
+    case do_one_of(schemas, value, opts) == 1 do
       true -> :ok
       false -> {:error, :one_of}
     end
   end
 
-  @spec do_one_of(list, any) :: integer
-  defp do_one_of(schemas, value) do
+  @spec do_one_of(list, any, keyword) :: integer
+  defp do_one_of(schemas, value, opts) do
     schemas
     |> Enum.filter(fn schema ->
-      case validate(schema, value) do
+      case validate(schema, value, opts) do
         :ok -> true
         {:error, _} -> false
       end

  defp validate(nil, schema, value, _opts),
    do: {:error, %{value: value, type: schema.as}}

  defp validate(:list, schema, value, _opts) do
    with :ok <- min_items(schema, value),
         :ok <- max_items(schema, value),
         :ok <- items(schema, value),
         :ok <- unique(schema, value),
         do: :ok
  end

  defp validate(:map, schema, value, _opts) do
    with :ok <- size(schema, value),
         :ok <- keys(schema, value),
         :ok <- required(schema, value),
         :ok <- dependencies(schema, value),
         {:ok, patts_rest} <- patterns(schema, value),
         {:ok, props_rest} <- properties(schema, value),
         value <- intersection(props_rest, patts_rest),
         :ok <- additionals(schema, value),
         do: :ok
  end


    end
  end

  defp additionals(%{additional_properties: schema}, map, opts)
       when is_map(schema) do
    result =
      Enum.reduce(map, %{}, fn {key, value}, acc ->
        case validate(schema, value, opts) do
          :ok -> acc
          {:error, reason} -> Map.put(acc, key, reason)
        end
