Description
IO::EncodingOptions
is a weird type. It is marked as public, but is essentially a record
with 2 fields that are used exclusively by the private types IO::Encoder
and IO::Decoder
, wrappers around the iconv interface. There are no public interfaces that produce or consume IO::EncodingOptions
values at all.
That type's #invalid
field is even weirder (this time the same goes for public methods like String#encode
and File.tempfile
). It is a Symbol?
and the only acceptable values are nil
and :skip
. This sounds like an opportunity to introduce an enum:
enum String::InvalidAction # alternatively `String::InvalidByteSequenceAction`
Raise # an exception is raised on invalid byte sequences
Skip # invalid byte sequences are ignored
# :nodoc:
def self.from_invalid(invalid)
if invalid.nil?
Raise
elsif invalid == :skip
Skip
else
raise ArgumentError.new "Valid values for `invalid` option are `nil` and `:skip`, not #{invalid.inspect}"
end
end
end
The overloads that take a Symbol?
should be deprecated in favor of this enum:
class String
def encode(encoding : String, invalid : String::InvalidAction = :raise) : Bytes; ...; end
@[Deprecated]
def encode(encoding : String, invalid : Nil) : Bytes
encode(encoding, String::InvalidAction.from_invalid(invalid))
end
# How to we deprecate `Symbol?` and restriction-less overloads properly?
# (they will be matched for `invalid: :skip`, but we still want to support autocasting here)
end
IO::EncodingOptions
can be deprecated too, and IO::Encoder
/ IO::Decoder
should use an equivalent internal type, unless there is a reason to support this struct in the public interface of encoding-related methods.
Activity