-module(yum@yaml@node). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/yum/yaml/node.gleam"). -export([new/3, synthetic_span/0, synthetic/1, kind/1, kind_name/1, span/1, style/1, tag/1, anchor/1, alias/1, with_tag/2, with_anchor/2, with_alias/2, as_mapping/1, get_keys/1, get_values/1, as_sequence/1, as_string/1, as_bool/1, as_int/1, as_float/1, as_null/1, get_index/2, get_key/2, get/2]). -export_type([node_/0, kind/0, kind_name/0, access_error/0, style/0, span/0, position/0, path_segment/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Inspect and query YAML nodes.\n" "\n" " A [`Node`](#Node) is one value inside a YAML document: a scalar, sequence,\n" " or mapping. This module provides accessors for the node kind, source span,\n" " source style, tags, anchors, aliases, typed scalar values, and nested path\n" " lookup.\n" "\n" " Nodes are used by both raw and resolved YAML documents. Parsing creates\n" " nodes with the structure and metadata found in the source. Resolving\n" " validates YAML-level metadata such as aliases and tags, and may expand or\n" " compose parts of the tree, but a resolved document still contains nodes.\n" "\n" " For example, [`tag`](#tag), [`anchor`](#anchor), and [`alias`](#alias)\n" " expose YAML metadata attached to a node. That metadata is not the same as\n" " the node's semantic [`Kind`](#Kind). Nodes created with\n" " [`yum/yaml/builder`](./builder.html) are synthetic and use\n" " [`synthetic_span`](#synthetic_span).\n" ). -opaque node_() :: {node, kind(), span(), style(), gleam@option:option(binary()), gleam@option:option(binary()), gleam@option:option(binary())}. -type kind() :: null | {bool, boolean()} | {int, integer()} | {float, float()} | pos_inf | neg_inf | nan | {string, binary()} | {sequence, list(node_())} | {mapping, list({node_(), node_()})}. -type kind_name() :: null_kind | bool_kind | int_kind | float_kind | pos_inf_kind | neg_inf_kind | nan_kind | string_kind | sequence_kind | mapping_kind. -type access_error() :: {expected_kind, kind_name(), kind_name(), span()}. -type style() :: plain_scalar | single_quoted_scalar | double_quoted_scalar | literal_block_scalar | folded_block_scalar | block_sequence | flow_sequence | block_mapping | flow_mapping | synthetic. -type span() :: {span, position(), position()}. -type position() :: {position, integer(), integer()}. -type path_segment() :: {key, binary()} | {index, integer()}. -file("src/yum/yaml/node.gleam", 258). ?DOC( " Creates a YAML node with explicit metadata.\n" "\n" " Most callers should prefer [`yum/yaml.parse`](../yaml.html#parse) plus\n" " [`yum/yaml.root`](../yaml.html#root) for parsed input or\n" " [`yum/yaml/builder`](./builder.html) for generated YAML. This constructor is\n" " public for tools that need to synthesize nodes while preserving their own\n" " source metadata.\n" ). -spec new(kind(), span(), style()) -> node_(). new(Kind, Span, Style) -> {node, Kind, Span, Style, none, none, none}. -file("src/yum/yaml/node.gleam", 271). ?DOC(" Returns the placeholder span used for generated nodes with no source.\n"). -spec synthetic_span() -> span(). synthetic_span() -> {span, {position, 0, 0}, {position, 0, 0}}. -file("src/yum/yaml/node.gleam", 265). ?DOC( " Creates a generated node with no original source location.\n" "\n" " This is the lower-level constructor used by [`yum/yaml/builder`](./builder.html).\n" ). -spec synthetic(kind()) -> node_(). synthetic(Kind) -> new(Kind, synthetic_span(), synthetic). -file("src/yum/yaml/node.gleam", 279). ?DOC( " Returns the semantic kind and value of a node.\n" "\n" " This is the broadest accessor. Prefer the stricter `as_*` functions when a\n" " caller expects one specific YAML kind and wants a typed error for mismatches.\n" ). -spec kind(node_()) -> kind(). kind(Node) -> erlang:element(2, Node). -file("src/yum/yaml/node.gleam", 566). -spec kind_name_of(kind()) -> kind_name(). kind_name_of(Kind) -> case Kind of null -> null_kind; {bool, _} -> bool_kind; {int, _} -> int_kind; {float, _} -> float_kind; pos_inf -> pos_inf_kind; neg_inf -> neg_inf_kind; nan -> nan_kind; {string, _} -> string_kind; {sequence, _} -> sequence_kind; {mapping, _} -> mapping_kind end. -file("src/yum/yaml/node.gleam", 285). ?DOC(" Returns the node kind without its associated value.\n"). -spec kind_name(node_()) -> kind_name(). kind_name(Node) -> _pipe = erlang:element(2, Node), kind_name_of(_pipe). -file("src/yum/yaml/node.gleam", 294). ?DOC( " Returns the source span for a node.\n" "\n" " Parsed nodes use 1-based row and column positions. Synthetic nodes created\n" " with [`yum/yaml/builder`](./builder.html) use [`synthetic_span`](#synthetic_span).\n" ). -spec span(node_()) -> span(). span(Node) -> erlang:element(3, Node). -file("src/yum/yaml/node.gleam", 302). ?DOC( " Returns the source style used to write a node.\n" "\n" " Style describes presentation, such as plain versus quoted scalars or block\n" " versus flow collections. It does not change the node's semantic kind.\n" ). -spec style(node_()) -> style(). style(Node) -> erlang:element(4, Node). -file("src/yum/yaml/node.gleam", 332). ?DOC( " Returns the YAML tag attached to a node, if one was written or added.\n" "\n" " Tags are metadata, not value casts. A tagged scalar keeps its parsed\n" " [`Kind`](#Kind); for example `!!str 123` is still parsed as an integer today,\n" " while the tag is available through this function.\n" "\n" " On raw YAML, this returns the tag form captured by the parser. On resolved\n" " YAML, tag handles are expanded where possible. For example:\n" "\n" " ```gleam\n" " import gleam/option\n" " import yum/yaml\n" " import yum/yaml/node\n" "\n" " pub fn example() {\n" " let assert Ok(document) = yaml.parse(\"value: !!str 123\")\n" " let assert option.Some(value) = document |> yaml.get([node.Key(\"value\")])\n" "\n" " assert node.tag(value) == option.Some(\"!str\")\n" "\n" " let assert Ok(document) = yaml.resolve(document)\n" " let assert option.Some(value) = document |> yaml.get([node.Key(\"value\")])\n" "\n" " assert node.tag(value) == option.Some(\"tag:yaml.org,2002:str\")\n" " }\n" " ```\n" ). -spec tag(node_()) -> gleam@option:option(binary()). tag(Node) -> erlang:element(5, Node). -file("src/yum/yaml/node.gleam", 341). ?DOC( " Returns the YAML anchor name attached to a node, if one was written or added.\n" "\n" " For source YAML like `defaults: &base { retries: 1 }`, the value node under\n" " `defaults` has anchor `base`. Resolving validates duplicate anchors but does\n" " not remove anchor metadata from nodes.\n" ). -spec anchor(node_()) -> gleam@option:option(binary()). anchor(Node) -> erlang:element(6, Node). -file("src/yum/yaml/node.gleam", 350). ?DOC( " Returns the YAML alias name attached to a node, if one was written or added.\n" "\n" " For source YAML like `copy: *base`, the value node under `copy` has alias\n" " `base`. Resolving checks that aliases refer to anchors seen earlier in the\n" " document, but alias metadata can still be inspected on the node.\n" ). -spec alias(node_()) -> gleam@option:option(binary()). alias(Node) -> erlang:element(7, Node). -file("src/yum/yaml/node.gleam", 359). ?DOC( " Returns a copy of the node with tag metadata.\n" "\n" " This function only sets metadata. It does not validate tag syntax or change\n" " the node's [`Kind`](#Kind).\n" ). -spec with_tag(node_(), binary()) -> node_(). with_tag(Node, Tag) -> {node, erlang:element(2, Node), erlang:element(3, Node), erlang:element(4, Node), {some, Tag}, erlang:element(6, Node), erlang:element(7, Node)}. -file("src/yum/yaml/node.gleam", 368). ?DOC( " Returns a copy of the node with anchor metadata.\n" "\n" " This function only sets metadata. Use [`yum/yaml.resolve`](../yaml.html#resolve)\n" " to validate anchor and alias relationships.\n" ). -spec with_anchor(node_(), binary()) -> node_(). with_anchor(Node, Anchor) -> {node, erlang:element(2, Node), erlang:element(3, Node), erlang:element(4, Node), erlang:element(5, Node), {some, Anchor}, erlang:element(7, Node)}. -file("src/yum/yaml/node.gleam", 377). ?DOC( " Returns a copy of the node with alias metadata.\n" "\n" " This function only sets metadata. Use [`yum/yaml.resolve`](../yaml.html#resolve)\n" " to check whether the alias refers to a known anchor.\n" ). -spec with_alias(node_(), binary()) -> node_(). with_alias(Node, Alias) -> {node, erlang:element(2, Node), erlang:element(3, Node), erlang:element(4, Node), erlang:element(5, Node), erlang:element(6, Node), {some, Alias}}. -file("src/yum/yaml/node.gleam", 562). -spec expected(node_(), kind_name()) -> access_error(). expected(Node, Kind) -> {expected_kind, Kind, kind_name(Node), erlang:element(3, Node)}. -file("src/yum/yaml/node.gleam", 384). ?DOC( " Returns mapping entries when the node is a mapping.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not a mapping.\n" ). -spec as_mapping(node_()) -> {ok, list({node_(), node_()})} | {error, access_error()}. as_mapping(Node) -> case erlang:element(2, Node) of {mapping, Entries} -> {ok, Entries}; _ -> {error, expected(Node, mapping_kind)} end. -file("src/yum/yaml/node.gleam", 396). ?DOC( " Returns all keys from a mapping node.\n" "\n" " The keys are returned as nodes because YAML mappings can use scalar,\n" " sequence, or mapping nodes as keys. Returns [`ExpectedKind`](#AccessError)\n" " when the node is not a mapping.\n" ). -spec get_keys(node_()) -> {ok, list(node_())} | {error, access_error()}. get_keys(Node) -> _pipe = Node, _pipe@1 = as_mapping(_pipe), gleam@result:map( _pipe@1, fun(_capture) -> gleam@list:map( _capture, fun(Entry) -> {Key, _} = Entry, Key end ) end ). -file("src/yum/yaml/node.gleam", 411). ?DOC( " Returns all values from a mapping node.\n" "\n" " Values are returned in source order. Returns [`ExpectedKind`](#AccessError)\n" " when the node is not a mapping.\n" ). -spec get_values(node_()) -> {ok, list(node_())} | {error, access_error()}. get_values(Node) -> _pipe = Node, _pipe@1 = as_mapping(_pipe), gleam@result:map( _pipe@1, fun(Node@1) -> gleam@list:map( Node@1, fun(Entry) -> {_, Value} = Entry, Value end ) end ). -file("src/yum/yaml/node.gleam", 425). ?DOC( " Returns sequence entries when the node is a sequence.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not a sequence.\n" ). -spec as_sequence(node_()) -> {ok, list(node_())} | {error, access_error()}. as_sequence(Node) -> case erlang:element(2, Node) of {sequence, Entries} -> {ok, Entries}; _ -> {error, expected(Node, sequence_kind)} end. -file("src/yum/yaml/node.gleam", 435). ?DOC( " Returns the string value when the node is a string.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not a string.\n" ). -spec as_string(node_()) -> {ok, binary()} | {error, access_error()}. as_string(Node) -> case erlang:element(2, Node) of {string, Value} -> {ok, Value}; _ -> {error, expected(Node, string_kind)} end. -file("src/yum/yaml/node.gleam", 445). ?DOC( " Returns the boolean value when the node is a boolean.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not a boolean.\n" ). -spec as_bool(node_()) -> {ok, boolean()} | {error, access_error()}. as_bool(Node) -> case erlang:element(2, Node) of {bool, Value} -> {ok, Value}; _ -> {error, expected(Node, bool_kind)} end. -file("src/yum/yaml/node.gleam", 455). ?DOC( " Returns the integer value when the node is an integer.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not an integer.\n" ). -spec as_int(node_()) -> {ok, integer()} | {error, access_error()}. as_int(Node) -> case erlang:element(2, Node) of {int, Value} -> {ok, Value}; _ -> {error, expected(Node, int_kind)} end. -file("src/yum/yaml/node.gleam", 467). ?DOC( " Returns the finite float value when the node is a float.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not a finite float.\n" " Special float values have separate kinds: [`PosInf`](#Kind),\n" " [`NegInf`](#Kind), and [`Nan`](#Kind).\n" ). -spec as_float(node_()) -> {ok, float()} | {error, access_error()}. as_float(Node) -> case erlang:element(2, Node) of {float, Value} -> {ok, Value}; _ -> {error, expected(Node, float_kind)} end. -file("src/yum/yaml/node.gleam", 477). ?DOC( " Returns `Nil` when the node is null.\n" "\n" " Returns [`ExpectedKind`](#AccessError) when the node is not null.\n" ). -spec as_null(node_()) -> {ok, nil} | {error, access_error()}. as_null(Node) -> case erlang:element(2, Node) of null -> {ok, nil}; _ -> {error, expected(Node, null_kind)} end. -file("src/yum/yaml/node.gleam", 546). ?DOC( " Returns a sequence item by zero-based index.\n" "\n" " Returns `None` when the node is not a sequence or when the index is out of\n" " bounds. Negative indexes always return `None`.\n" ). -spec get_index(node_(), integer()) -> gleam@option:option(node_()). get_index(Node, Index) -> case Index < 0 of true -> none; false -> case as_sequence(Node) of {ok, Entries} -> _pipe = Entries, _pipe@1 = gleam@list:drop(_pipe, Index), _pipe@2 = gleam@list:first(_pipe@1), gleam@option:from_result(_pipe@2); {error, _} -> none end end. -file("src/yum/yaml/node.gleam", 526). ?DOC( " Returns a mapping value by string key.\n" "\n" " Only string keys are matched. Returns `None` when the node is not a mapping,\n" " when the key is not present, or when a mapping entry uses a non-string key.\n" ). -spec get_key(node_(), binary()) -> gleam@option:option(node_()). get_key(Node, Key) -> case as_mapping(Node) of {ok, Entries} -> _pipe = Entries, _pipe@1 = gleam@list:find_map( _pipe, fun(Entry) -> {Entry_key, Value} = Entry, case as_string(Entry_key) of {ok, Entry_key@1} when Entry_key@1 =:= Key -> {ok, Value}; _ -> {error, nil} end end ), gleam@option:from_result(_pipe@1); {error, _} -> none end. -file("src/yum/yaml/node.gleam", 510). ?DOC( " Returns a nested node by following mapping keys and sequence indexes.\n" "\n" " This is a convenience wrapper around [`get_key`](#get_key) and\n" " [`get_index`](#get_index). It returns `None` when any path segment does not\n" " match the current node.\n" "\n" " ```gleam\n" " import gleam/option\n" " import yum/yaml\n" " import yum/yaml/node\n" "\n" " pub fn example() {\n" " let assert Ok(document) = yaml.parse(\"jobs:\\n test:\\n run: gleam test\")\n" " let root = yaml.root(document)\n" "\n" " let run = root |> node.get([\n" " node.Key(\"jobs\"),\n" " node.Key(\"test\"),\n" " node.Key(\"run\"),\n" " ])\n" "\n" " let value = run |> option.map(node.as_string)\n" "\n" " assert value == option.Some(Ok(\"gleam test\"))\n" " }\n" " ```\n" ). -spec get(node_(), list(path_segment())) -> gleam@option:option(node_()). get(Node, Path) -> case Path of [] -> {some, Node}; [{key, Key} | Rest] -> _pipe = get_key(Node, Key), gleam@option:then(_pipe, fun(_capture) -> get(_capture, Rest) end); [{index, Index} | Rest@1] -> _pipe@1 = get_index(Node, Index), gleam@option:then( _pipe@1, fun(_capture@1) -> get(_capture@1, Rest@1) end ) end.