Current section
Files
Jump to
Current section
Files
lib/yamlscript.ex
defmodule YAMLScript do
# Copyright 2023-2026 Ingy dot Net
# This code is licensed under MIT license (See License for details)
@moduledoc """
Elixir binding/API for the libys shared library.
This module is an Elixir port of the Python 'yamlscript' module,
the reference implementation for YAMLScript FFI bindings to libys.
The `load/1` function takes a YAMLScript string as input and
returns `{:ok, data}` where data is the value the YAMLScript code
evaluates to, or `{:error, message}`. The `load!/1` variant returns
the data directly and raises `YAMLScript.Error` on failure.
"""
@on_load :load_nif
@doc false
def load_nif do
path = :filename.join(:code.priv_dir(:yamlscript), ~c"yamlscript_nif")
:erlang.load_nif(path, 0)
end
@doc """
Compile and eval a YAMLScript string and return the result.
"""
@spec load(String.t()) :: {:ok, term()} | {:error, String.t()}
def load(input) when is_binary(input) do
case nif_load_ys_to_json(input) do
{:error, message} ->
{:error, message}
json when is_binary(json) ->
# Decode the JSON response and check for a libys error:
resp = JSON.decode!(json)
cond do
err = resp["error"] ->
{:error, err["cause"]}
Map.has_key?(resp, "data") ->
{:ok, resp["data"]}
true ->
{:error, "Unexpected response from 'libys'"}
end
end
end
@doc """
Like `load/1` but returns the data directly and raises
`YAMLScript.Error` on failure.
"""
@spec load!(String.t()) :: term()
def load!(input) do
case load(input) do
{:ok, data} -> data
{:error, message} -> raise YAMLScript.Error, message: message
end
end
defp nif_load_ys_to_json(_input) do
:erlang.nif_error(:nif_not_loaded)
end
end
defmodule YAMLScript.Error do
@moduledoc "Error raised by `YAMLScript.load!/1`."
defexception [:message]
end