encodings/encoding_fallbacks_parens.rb

tests/_examples/encodings/encoding_fallbacks_parens.rb in the metorex repository.

# `fallback:` is asked what to write for each character the destination
# cannot spell. A Hash is looked up, default included, and a Proc, a lambda,
# a Method or anything else answering `[]` is handed the character.
text = "B�"
p(text.encode(Encoding::US_ASCII, fallback: { "�" => "bar" }))

defaulted = {}
defaulted.default = "dflt"
p(text.encode(Encoding::US_ASCII, fallback: defaulted))

p(text.encode(Encoding::US_ASCII, fallback: proc { |character| character.bytes().inspect() }))
p(text.encode(Encoding::US_ASCII, fallback: ->(character) { character.ord().to_s(16) }))

def spelled_out(character) = "U+#{character.ord().to_s(16).upcase()}"
p(text.encode(Encoding::US_ASCII, fallback: method(:spelled_out)))

class Lookup
  def [](character) = "lookup"
end
p(text.encode(Encoding::US_ASCII, fallback: Lookup.new()))

# An answer that is not a String is read through `to_str`.
class Word
  def to_str() = "word"
end
p(text.encode(Encoding::US_ASCII, fallback: { "�" => Word.new() }))

# `undef: :replace` is used ahead of a fallback.
p(text.encode(Encoding::US_ASCII, undef: :replace, replace: "foo", fallback: proc { "bar" }))

# A character nothing answers for is refused as undefined, and an answer the
# destination cannot spell either is refused as too big.
def refusal()
  yield()
rescue StandardError => problem
  [problem.class(), problem.message()]
end

p(refusal() { text.encode(Encoding::US_ASCII, fallback: { "foo" => "bar" }) })
p(refusal() { text.encode(Encoding::US_ASCII, fallback: Object.new()) })
p(refusal() { text.encode(Encoding::US_ASCII, fallback: { "�" => Object.new() }) })
p(refusal() { text.encode(Encoding::US_ASCII, fallback: { "�" => "○" }) })

Output:

"Bbar"
"Bdflt"
"B[239, 191, 189]"
"Bfffd"
"BU+FFFD"
"Blookup"
"Bword"
"Bfoo"
[Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII"]
[Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII"]
[TypeError, "no implicit conversion of Object into String"]
[ArgumentError, "too big fallback string"]