@@ -36,11 +36,18 @@ package sz
3636// #cgo nocallback sz_hash_state_update
3737// #cgo noescape sz_hash_state_digest
3838// #cgo nocallback sz_hash_state_digest
39+ // #cgo noescape sz_sha256_state_init
40+ // #cgo nocallback sz_sha256_state_init
41+ // #cgo noescape sz_sha256_state_update
42+ // #cgo nocallback sz_sha256_state_update
43+ // #cgo noescape sz_sha256_state_digest
44+ // #cgo nocallback sz_sha256_state_digest
3945// #define SZ_DYNAMIC_DISPATCH 1
4046// #include <stringzilla/stringzilla.h>
4147import "C"
4248import (
4349 "fmt"
50+ "io"
4451 "unsafe"
4552)
4653
@@ -185,8 +192,8 @@ func (h *Hasher) Digest() uint64 {
185192 return uint64 (C .sz_hash_state_digest (& h .state ))
186193}
187194
188- // SHA256 computes the SHA-256 cryptographic hash of the input data.
189- func Sha256 (data []byte ) [32 ]byte {
195+ // HashSha256 computes the SHA-256 cryptographic hash of the input data.
196+ func HashSha256 (data []byte ) [32 ]byte {
190197 var state C.sz_sha256_state_t
191198 C .sz_sha256_state_init (& state )
192199 if len (data ) > 0 {
@@ -197,45 +204,66 @@ func Sha256(data []byte) [32]byte {
197204 return digest
198205}
199206
200- // Sha256Hasher is a streaming SHA-256 hasher.
201- type Sha256Hasher struct {
207+ // Sha256 is a streaming SHA-256 hasher that implements hash.Hash and io.Writer .
208+ type Sha256 struct {
202209 state C.sz_sha256_state_t
203210}
204211
212+ // Compile-time interface checks
213+ var _ io.Writer = (* Sha256 )(nil )
214+
205215// NewSha256 creates a new streaming SHA-256 hasher.
206- func NewSha256 () * Sha256Hasher {
207- h := & Sha256Hasher {}
216+ func NewSha256 () * Sha256 {
217+ h := & Sha256 {}
208218 C .sz_sha256_state_init (& h .state )
209219 return h
210220}
211221
212- // Write adds data to the streaming SHA-256 hasher.
213- func (h * Sha256Hasher ) Write (p []byte ) * Sha256Hasher {
214- if len (p ) == 0 {
215- return h
222+ // Write adds data to the streaming SHA-256 hasher. Implements io.Writer.
223+ func (h * Sha256 ) Write (p []byte ) ( n int , err error ) {
224+ if len (p ) > 0 {
225+ C . sz_sha256_state_update ( & h . state , ( * C . char )( unsafe . Pointer ( & p [ 0 ])), C . ulong ( len ( p )))
216226 }
217- C .sz_sha256_state_update (& h .state , (* C .char )(unsafe .Pointer (& p [0 ])), C .ulong (len (p )))
218- return h
227+ return len (p ), nil
219228}
220229
221- // Digest returns the current SHA-256 hash without consuming the state.
222- func (h * Sha256Hasher ) Digest () [32 ]byte {
230+ // Sum appends the current hash to b and returns the resulting slice.
231+ // It does not change the underlying hash state. Implements hash.Hash.
232+ func (h * Sha256 ) Sum (b []byte ) []byte {
233+ digest := h .Digest ()
234+ return append (b , digest [:]... )
235+ }
236+
237+ // Reset resets the hasher to its initial state. Implements hash.Hash.
238+ func (h * Sha256 ) Reset () {
239+ C .sz_sha256_state_init (& h .state )
240+ }
241+
242+ // Size returns the number of bytes Sum will return. Implements hash.Hash.
243+ func (h * Sha256 ) Size () int {
244+ return 32
245+ }
246+
247+ // BlockSize returns the hash's underlying block size. Implements hash.Hash.
248+ func (h * Sha256 ) BlockSize () int {
249+ return 64
250+ }
251+
252+ // Digest returns the current SHA-256 hash as a 32-byte array without consuming the state.
253+ // This is a convenience method in addition to the standard hash.Hash interface.
254+ func (h * Sha256 ) Digest () [32 ]byte {
223255 var digest [32 ]byte
224256 C .sz_sha256_state_digest (& h .state , (* C .uchar )(unsafe .Pointer (& digest [0 ])))
225257 return digest
226258}
227259
228260// Hexdigest returns the current SHA-256 hash as a lowercase hexadecimal string.
229- func (h * Sha256Hasher ) Hexdigest () string {
261+ // This is a convenience method matching Python's hashlib interface.
262+ func (h * Sha256 ) Hexdigest () string {
230263 digest := h .Digest ()
231264 return fmt .Sprintf ("%x" , digest )
232265}
233266
234- // Reset resets the hasher to its initial state.
235- func (h * Sha256Hasher ) Reset () {
236- C .sz_sha256_state_init (& h .state )
237- }
238-
239267// Count returns the number of overlapping or non-overlapping instances of `substr` in `str`.
240268// If `substr` is an empty string, returns 1 + the length of the `str`.
241269// https://pkg.go.dev/strings#Count
0 commit comments