🙌
[Feature #20594] エンコーディングを維持しながらバイト列を追加する String#byteconcat
[Feature #20594] A new String method to append bytes while preserving encoding
- エンコーディングを維持しながらバイト列を追加する
String#byteconcat
メソッドの提案 -
profobuf
やMessagePack
などのバイナリプロトコルを利用する場合に以下のようにシリアライズする
Post = Struct.new(:title, :body) do
def serialize(buf)
buf <<
255 << title.bytesize << title <<
255 << body.bytesize << body
end
end
Post.new("Hello", "World").serialize("somedata".b)
# => "somedata\xFF\x05Hello\xFF\x05World" #<Encoding:ASCII-8BIT>
- このときに問題になるのが
Encoding::ASCII_8BIT
に対してUTF-8
などの文字列を結合しようとした場合にエラーになる
Post.new("H€llo", "Wôrld").serialize("somedata".b)
# => incompatible character encodings: ASCII-8BIT and UTF-8 (Encoding::CompatibilityError)
- こういう問題を回避するためにバイト列単位で結合する
String#byteconcat
を追加する提案
class String
def byteconcat(*strings)
strings.map! do |s|
if s.is_a?(String) && s.encoding != encoding
s.dup.force_encoding(encoding)
else
s
end
end
concat(*strings)
end
end
Post = Struct.new(:title, :body) do
def serialize(buf)
buf.byteconcat(
255, title.bytesize, title,
255, body.bytesize, body,
)
end
end
Post.new("H€llo", "Wôrld").serialize("somedata".b)
# => "somedata\xFF\aH\xE2\x82\xACllo\xFF\x06W\xC3\xB4rld" #<Encoding:ASCII-8BIT>
- これ系のデータってそもそも
String
で扱うべきなんですかねー
Discussion