HasherにRawSpanのプリミティブを追加する
Add RawSpan primitive to Hasher
このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。
01 何が問題だったのか
Hasher に値を混ぜ込む(combine する)APIには、これまで主に次の2種類がありました。
- 任意の
Hashableな値を受け取り、その値のhash(into:)の実装に処理を委ねるジェネリックなcombine(_:) UnsafeRawBufferPointerを受け取り、バッファの中身のバイト列を直接混ぜ込むプリミティブなcombine(bytes:)
var hasher = Hasher()
hasher.combine(42) // Hashable な値を混ぜ込む
let bytes: [UInt8] = [0x01, 0x02, 0x03]
bytes.withUnsafeBytes { buffer in // バイト列を直接混ぜ込むには unsafe なAPIが必要
hasher.combine(bytes: buffer)
}
Swiftには UnsafeRawBufferPointer の安全な代替として RawSpan 型が導入されています。しかし Hasher のプリミティブなAPIは UnsafeRawBufferPointer しか受け取れないため、バイト列をそのままハッシュ値の計算に使いたい場合には、unsafe なAPIに頼らざるを得ませんでした。
02 どのように解決されるのか
Hasher に、RawSpan を受け取るプリミティブなAPIが追加されます。
extension Hasher {
@export(implementation)
public mutating func combine(bytes: RawSpan)
}
既存の combine(bytes: UnsafeRawBufferPointer) のオーバーロードとして提供され、RawSpan が指すバイト列をそのまま Hasher の状態に混ぜ込みます。InlineArray や Array などの span.bytes から得た RawSpan を渡せるので、unsafe なAPIを使わずにバイト列をハッシュできます。
var values: InlineArray<_, UInt8> = [0x01, 0x02, 0x03]
var hasher = Hasher()
hasher.combine(bytes: values.span.bytes)
let hashValue = hasher.finalize()
UnsafeRawBufferPointer と RawSpan は曖昧にならないため、既存のコードに影響はありません。このAPIを利用するには、RawSpan 型自体が使えるデプロイメントターゲットである必要があります。
03 今後の見通し
RawSpan の Hashable への適合
将来的に RawSpan 自体を Hashable に適合させることも検討の余地があるとされています。このProposalは、既存の Hasher のプリミティブなAPIを新しい標準ライブラリの型に対応させることだけに焦点を当てています。
仮に RawSpan が Hashable に適合すれば、既存のジェネリックな combine(_:) に RawSpan を渡せるようになります。ただし、その場合でも今回のAPIが不要になるわけではなく、unsafe なAPIを使わずにバイト列をハッシュするためのプリミティブなAPIは引き続き重要だと述べられています。