Krikri::PluginHelpers::TextFileIO
Ansible's file-editing modules (lineinfile, blockinfile) gained an
encoding option in 2.21: they open the destination in TEXT mode with
that codec instead of reading raw bytes. This is the shared codec
layer for those plugins, since Crystal has no transcoder of its own:
everything krikri manipulates stays UTF-8, and a non-UTF-8 file is
converted at the edges.
Codec names resolve through PythonCodecs (CPython's registry), so an unknown name fails with the module-crash wording real Ansible shows ("Task failed: Module failed: unknown encoding: <name>"), and an undecodable file fails with CPython's UnicodeDecodeError text - the lineinfile/blockinfile open() uses the strict error handler, not replace's surrogateescape.
Class methods
Bytes to UTF-8 text: {text, nil}, or {"", failure message} when the content does not decode. The empty value rather than nil keeps every caller on a non-nilable tuple: a failure message is what makes the pair's value meaningless, not its absence.
UTF-8 text to the file's own encoding: {bytes, nil} or {empty bytes, failure message}.