Module: Philiprehberger::SafeYaml

Defined in:
lib/philiprehberger/safe_yaml.rb,
lib/philiprehberger/safe_yaml/loader.rb,
lib/philiprehberger/safe_yaml/schema.rb,
lib/philiprehberger/safe_yaml/version.rb

Defined Under Namespace

Modules: Loader Classes: Error, Schema, SchemaError, SizeError

Constant Summary collapse

VERSION =
'0.5.0'

Class Method Summary collapse

Class Method Details

.dump(data, permitted_classes: []) ⇒ String

Safely dumps data to a YAML string with type validation.

Parameters:

  • data (Object)

    the data to serialize

  • permitted_classes (Array<Class>) (defaults to: [])

    additional classes allowed for serialization

Returns:

  • (String)

    the YAML string

Raises:

  • (Error)

    if data contains unsafe types



44
45
46
# File 'lib/philiprehberger/safe_yaml.rb', line 44

def self.dump(data, permitted_classes: [])
  Loader.dump(data, permitted_classes: permitted_classes)
end

.dump_file(data, path, permitted_classes: []) ⇒ String

Safely dumps data to a YAML file with type validation.

Parameters:

  • data (Object)

    the data to serialize

  • path (String)

    path to write the YAML file

  • permitted_classes (Array<Class>) (defaults to: [])

    additional classes allowed for serialization

Returns:

  • (String)

    the YAML string written to the file

Raises:

  • (Error)

    if data contains unsafe types



55
56
57
# File 'lib/philiprehberger/safe_yaml.rb', line 55

def self.dump_file(data, path, permitted_classes: [])
  Loader.dump_file(data, path, permitted_classes: permitted_classes)
end

.load(string, **opts) ⇒ Object

Safely loads a YAML string with restricted types.

Parameters:

Returns:

  • (Object)

    the parsed YAML object

Raises:



24
25
26
# File 'lib/philiprehberger/safe_yaml.rb', line 24

def self.load(string, **opts)
  Loader.load(string, **opts)
end

.load_and_validate(string, schema:, **opts) ⇒ Object

Loads and validates a YAML string against a schema in one step.

Parameters:

Returns:

  • (Object)

    the parsed and validated YAML data

Raises:



66
67
68
69
70
# File 'lib/philiprehberger/safe_yaml.rb', line 66

def self.load_and_validate(string, schema:, **opts)
  data = Loader.load(string, **opts)
  schema.validate!(data)
  data
end

.load_file(path, **opts) ⇒ Object

Safely loads a YAML file with restricted types.

Parameters:

Returns:

  • (Object)

    the parsed YAML object

Raises:

  • (SizeError)

    if file content exceeds max_size



34
35
36
# File 'lib/philiprehberger/safe_yaml.rb', line 34

def self.load_file(path, **opts)
  Loader.load_file(path, **opts)
end

.load_with_defaults(string, defaults: {}, **opts) ⇒ Hash

Loads a YAML string and deep merges over default values.

Parameters:

  • string (String)

    the YAML string to parse

  • defaults (Hash) (defaults to: {})

    default values to merge under parsed data

  • opts (Hash)

Returns:

  • (Hash)

    the merged result with parsed values taking precedence



87
88
89
90
# File 'lib/philiprehberger/safe_yaml.rb', line 87

def self.load_with_defaults(string, defaults: {}, **opts)
  data = Loader.load(string, **opts)
  Loader.deep_merge(defaults, data || {})
end

.merge(*sources, as_files: nil, **load_opts) ⇒ Hash

Loads multiple YAML sources through the safe loader and deep merges them in order, with later sources winning on conflicts.

Each source may be either inline YAML or a path to a YAML file. The following heuristic distinguishes the two: when as_files is nil (the default), a String source is treated as a file path if File.file?(source) returns true, and as inline YAML otherwise. Pass as_files: false to force every source to be parsed as inline YAML, or as_files: true to force every source to be read as a file.

All sources are loaded through Philiprehberger::SafeYaml::Loader.load so size, alias, and permitted-class limits passed via load_opts apply uniformly.

Merge semantics:

  • Nested Hashes are merged recursively.

  • Non-Hash conflicts (including arrays) are replaced by the later source’s value. Arrays are not concatenated.

  • An empty source list returns an empty Hash.

Parameters:

  • sources (Array<String>)

    inline YAML strings or file paths

  • as_files (Boolean, nil) (defaults to: nil)

    nil auto-detect (default), true treat all sources as file paths, false treat all as inline YAML

  • load_opts (Hash)

    options forwarded to Philiprehberger::SafeYaml::Loader.load (e.g. permitted_classes:, max_aliases:, max_size:)

Returns:

  • (Hash)

    the deeply merged result

Raises:

  • (ArgumentError)

    if any source does not parse to a Hash

  • (SizeError)

    if a source exceeds max_size



119
120
121
122
123
124
125
126
127
128
# File 'lib/philiprehberger/safe_yaml.rb', line 119

def self.merge(*sources, as_files: nil, **load_opts)
  sources.each_with_index.reduce({}) do |acc, (source, idx)|
    result = load_source(source, idx, as_files, load_opts)
    unless result.is_a?(Hash)
      raise ArgumentError,
            "merge sources must yield Hash, got #{result.class} from source #{idx}"
    end
    Loader.deep_merge(acc, result)
  end
end

.sanitize(string) ⇒ String

Sanitizes a YAML string by stripping full-line comments and normalizing whitespace.

Parameters:

  • string (String)

    the raw YAML string

Returns:

  • (String)

    the cleaned YAML string

Raises:

  • (Error)

    if the sanitized string is not valid YAML



77
78
79
# File 'lib/philiprehberger/safe_yaml.rb', line 77

def self.sanitize(string)
  Loader.sanitize(string)
end