https://zenn.dev/foxtail88/articles/1bbb3108db0b21

先日、こちらの記事を拝見して「おもしろい!」と感じました。

Twitterなんかで「𝙈𝙮 𝙣𝙚𝙬 𝙜𝙚𝙖𝙧...」という文字を見かけるたびに、これみんなどうやってタイプしてるんだろう?と気になっていたので、なるほど、こうしたツールやWebサイトを利用するのね、と得心しました。

上記記事ではCLIをリリースして下さっています。もっと幅広く使えるツールも作ってみたいな、ということで目をつけたのがGoのtransform.Transformerの実装です。以下ではその詳細を述べていきます。

transform.Transformer?

Goの持ち味の1つが、io.Reader/io.Writerによる入出力の抽象化&ストリーム化です。それらのインタフェースを活用することで、幅広い入出力に効率良く処理をかませることができます。

その活用例の一つとして、ShiftJISでエンコーディングされたファイルの読み込みなどがあります。下記の記事でも解説されていますが、GoはUTF-8で文字列を扱うため、ShiftJISでエンコーディングされたコードを読み込むには、transform.NewReader(io.Reader, japanese.ShiftJIS.NewDecoder())によってio.Readerを作成し、これを所望のストリーム処理に繋げます。

transform.NewReaderの第2引数はtransform.Transformerインタフェースであり、次のメソッドを持つ構造体であればオリジナルの変換処理を実装することができます。

type Transformer interface {
	Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
	Reset()
}

Transform関数が肝で、srcから読み取ったバイト列に所望の変換を行い、dstに書き込みます。入力のsrcが何度かに分けられる場合を想定しマルチバイト文字の際は文字途中での分割に対する配慮が必要ですし、書き込みたいバイト列に対しdstの長さが不足する際は余剰分を留保しておく必要があるなど、なかなか実装が面倒な子ではあります。しかしこれを実装することで様々な入出力の間に文字列の変換を入れることができるのは、大きな魅力ではないでしょうか。

ということで、Unicodeで表現できる範囲内で書体を変えるようなtransform.Transformerの実装を作ってみます。

今回の実装

作成したパッケージは下記です。

a-z, A-Z, 0-9の文字を所望の書体に変換します。これらの文字は1バイト文字なので、その分だけtransform.Transformerの実装は簡単でした。

現状は次の書体に対応しています。