Sinter.Types (Sinter v0.0.1)

View Source

Core type system for Sinter validation.

This module defines the type specifications supported by Sinter and provides the fundamental validation and coercion functions that power the unified validation engine.

Supported Types

  • Primitive Types: :string, :integer, :float, :boolean, :atom, :any, :map
  • Array Types: {:array, inner_type}
  • Union Types: {:union, [type1, type2, ...]}
  • Tuple Types: {:tuple, [type1, type2, ...]}
  • Map Types: {:map, key_type, value_type} or :map

Type Validation

The validate/3 function is the core validation engine:

iex> Sinter.Types.validate(:string, "hello", [])
{:ok, "hello"}

iex> Sinter.Types.validate(:integer, "not a number", [])
{:error, [%Sinter.Error{code: :type, ...}]}

Type Coercion

The coerce/2 function provides safe type conversion:

iex> Sinter.Types.coerce(:integer, "42")
{:ok, 42}

iex> Sinter.Types.coerce(:integer, "not a number")
{:error, [%Sinter.Error{code: :coercion, ...}]}

Summary

Functions

Attempts to coerce a value to the specified type.

Converts a type specification to JSON Schema format.

Validates a value against a type specification.

Types

composite_type()

@type composite_type() ::
  {:array, type_spec()}
  | {:array, type_spec(), keyword()}
  | {:union, [type_spec()]}
  | {:tuple, [type_spec()]}
  | {:map, type_spec(), type_spec()}

constraint()

@type constraint() ::
  {:min_length, pos_integer()}
  | {:max_length, pos_integer()}
  | {:min_items, non_neg_integer()}
  | {:max_items, pos_integer()}
  | {:gt, number()}
  | {:gteq, number()}
  | {:lt, number()}
  | {:lteq, number()}
  | {:format, Regex.t()}
  | {:choices, [term()]}

primitive_type()

@type primitive_type() :: :string | :integer | :float | :boolean | :atom | :any | :map

type_spec()

@type type_spec() :: primitive_type() | composite_type()

Functions

coerce(type_spec, value)

@spec coerce(type_spec(), term()) :: {:ok, term()} | {:error, [Sinter.Error.t()]}

Attempts to coerce a value to the specified type.

Coercion is safe and predictable - it never raises exceptions and only performs well-defined conversions.

Parameters

  • type_spec - The target type specification
  • value - The value to coerce

Returns

  • {:ok, coerced_value} on successful coercion
  • {:error, [%Sinter.Error{}]} on coercion failure

Examples

iex> Sinter.Types.coerce(:string, :hello)
{:ok, "hello"}

iex> Sinter.Types.coerce(:integer, "42")
{:ok, 42}

iex> {:error, [error]} = Sinter.Types.coerce(:integer, "not a number")
iex> error.code
:coercion

to_json_schema(type_spec)

@spec to_json_schema(type_spec()) :: map()

Converts a type specification to JSON Schema format.

This function maps Sinter types to their JSON Schema equivalents, enabling JSON Schema generation for LLM providers.

Examples

iex> Sinter.Types.to_json_schema(:string)
%{"type" => "string"}

iex> Sinter.Types.to_json_schema({:array, :integer})
%{"type" => "array", "items" => %{"type" => "integer"}}

validate(type_spec, value, path \\ [])

@spec validate(type_spec(), term(), [atom() | String.t() | integer()]) ::
  {:ok, term()} | {:error, [Sinter.Error.t()]}

Validates a value against a type specification.

This is the core validation function that all other validation ultimately uses. It checks if a value matches the expected type and satisfies any constraints.

Parameters

  • type_spec - The type specification to validate against
  • value - The value to validate
  • path - The path for error reporting (default: [])

Returns

  • {:ok, validated_value} on success
  • {:error, [%Sinter.Error{}]} on validation failure

Examples

iex> Sinter.Types.validate(:string, "hello", [])
{:ok, "hello"}

iex> Sinter.Types.validate(:integer, 42, [])
{:ok, 42}

iex> Sinter.Types.validate({:array, :string}, ["a", "b"], [])
{:ok, ["a", "b"]}

iex> {:error, [error]} = Sinter.Types.validate(:string, 123, [])
iex> error.code
:type