-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add hash #1273
Merged
Merged
feat: add hash #1273
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2013 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package encoding defines interfaces shared by other packages that | ||
// convert data to and from byte-level and textual representations. | ||
// Packages that check for these interfaces include encoding/gob, | ||
// encoding/json, and encoding/xml. As a result, implementing an | ||
// interface once can make a type useful in multiple encodings. | ||
// Standard types that implement these interfaces include time.Time and net.IP. | ||
// The interfaces come in pairs that produce and consume encoded data. | ||
// | ||
// Adding encoding/decoding methods to existing types may constitute a breaking change, | ||
// as they can be used for serialization in communicating with programs | ||
// written with different library versions. | ||
// The policy for packages maintained by the Go project is to only allow | ||
// the addition of marshaling functions if no existing, reasonable marshaling exists. | ||
package encoding | ||
|
||
// BinaryMarshaler is the interface implemented by an object that can | ||
// marshal itself into a binary form. | ||
// | ||
// MarshalBinary encodes the receiver into a binary form and returns the result. | ||
type BinaryMarshaler interface { | ||
MarshalBinary() (data []byte, err error) | ||
} | ||
|
||
// BinaryUnmarshaler is the interface implemented by an object that can | ||
// unmarshal a binary representation of itself. | ||
// | ||
// UnmarshalBinary must be able to decode the form generated by MarshalBinary. | ||
// UnmarshalBinary must copy the data if it wishes to retain the data | ||
// after returning. | ||
type BinaryUnmarshaler interface { | ||
UnmarshalBinary(data []byte) error | ||
} | ||
|
||
// TextMarshaler is the interface implemented by an object that can | ||
// marshal itself into a textual form. | ||
// | ||
// MarshalText encodes the receiver into UTF-8-encoded text and returns the result. | ||
type TextMarshaler interface { | ||
MarshalText() (text []byte, err error) | ||
} | ||
|
||
// TextUnmarshaler is the interface implemented by an object that can | ||
// unmarshal a textual representation of itself. | ||
// | ||
// UnmarshalText must be able to decode the form generated by MarshalText. | ||
// UnmarshalText must copy the text if it wishes to retain the text | ||
// after returning. | ||
type TextUnmarshaler interface { | ||
UnmarshalText(text []byte) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2009 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package adler32 implements the Adler-32 checksum. | ||
// | ||
// It is defined in RFC 1950: | ||
// | ||
// Adler-32 is composed of two sums accumulated per byte: s1 is | ||
// the sum of all bytes, s2 is the sum of all s1 values. Both sums | ||
// are done modulo 65521. s1 is initialized to 1, s2 to zero. The | ||
// Adler-32 checksum is stored as s2*65536 + s1 in most- | ||
// significant-byte first (network) order. | ||
package adler32 | ||
|
||
import ( | ||
"errors" | ||
"hash" | ||
) | ||
|
||
const ( | ||
// mod is the largest prime that is less than 65536. | ||
mod = 65521 | ||
// nmax is the largest n such that | ||
// 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1. | ||
// It is mentioned in RFC 1950 (search for "5552"). | ||
nmax = 5552 | ||
) | ||
|
||
// The size of an Adler-32 checksum in bytes. | ||
const Size = 4 | ||
|
||
// digest represents the partial evaluation of a checksum. | ||
// The low 16 bits are s1, the high 16 bits are s2. | ||
type digest uint32 | ||
|
||
func (d *digest) Reset() { *d = 1 } | ||
|
||
// New returns a new hash.Hash32 computing the Adler-32 checksum. Its | ||
// Sum method will lay the value out in big-endian byte order. The | ||
// returned Hash32 also implements encoding.BinaryMarshaler and | ||
// encoding.BinaryUnmarshaler to marshal and unmarshal the internal | ||
// state of the hash. | ||
func New() hash.Hash32 { | ||
d := new(digest) | ||
d.Reset() | ||
return d | ||
} | ||
|
||
func (d *digest) Size() int { return Size } | ||
|
||
func (d *digest) BlockSize() int { return 4 } | ||
|
||
const ( | ||
magic = "adl\x01" | ||
marshaledSize = len(magic) + 4 | ||
) | ||
|
||
func (d *digest) MarshalBinary() ([]byte, error) { | ||
b := make([]byte, 0, marshaledSize) | ||
b = append(b, magic...) | ||
b = appendUint32(b, uint32(*d)) | ||
return b, nil | ||
} | ||
|
||
func (d *digest) UnmarshalBinary(b []byte) error { | ||
if len(b) < len(magic) || string(b[:len(magic)]) != magic { | ||
return errors.New("hash/adler32: invalid hash state identifier") | ||
} | ||
if len(b) != marshaledSize { | ||
return errors.New("hash/adler32: invalid hash state size") | ||
} | ||
*d = digest(readUint32(b[len(magic):])) | ||
return nil | ||
} | ||
|
||
func appendUint32(b []byte, x uint32) []byte { | ||
a := [4]byte{ | ||
byte(x >> 24), | ||
byte(x >> 16), | ||
byte(x >> 8), | ||
byte(x), | ||
} | ||
return append(b, a[:]...) | ||
} | ||
|
||
func readUint32(b []byte) uint32 { | ||
_ = b[3] | ||
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 | ||
} | ||
|
||
// Add p to the running checksum d. | ||
func update(d digest, p []byte) digest { | ||
s1, s2 := uint32(d&0xffff), uint32(d>>16) | ||
for len(p) > 0 { | ||
var q []byte | ||
if len(p) > nmax { | ||
p, q = p[:nmax], p[nmax:] | ||
} | ||
for len(p) >= 4 { | ||
s1 += uint32(p[0]) | ||
s2 += s1 | ||
s1 += uint32(p[1]) | ||
s2 += s1 | ||
s1 += uint32(p[2]) | ||
s2 += s1 | ||
s1 += uint32(p[3]) | ||
s2 += s1 | ||
p = p[4:] | ||
} | ||
for _, x := range p { | ||
s1 += uint32(x) | ||
s2 += s1 | ||
} | ||
s1 %= mod | ||
s2 %= mod | ||
p = q | ||
} | ||
return digest(s2<<16 | s1) | ||
} | ||
|
||
func (d *digest) Write(p []byte) (nn int, err error) { | ||
*d = update(*d, p) | ||
return len(p), nil | ||
} | ||
|
||
func (d *digest) Sum32() uint32 { return uint32(*d) } | ||
|
||
func (d *digest) Sum(in []byte) []byte { | ||
s := uint32(*d) | ||
return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) | ||
} | ||
|
||
// Checksum returns the Adler-32 checksum of data. | ||
func Checksum(data []byte) uint32 { return uint32(update(1, data)) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright 2009 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package hash provides interfaces for hash functions. | ||
package hash | ||
|
||
import "io" | ||
|
||
// Hash is the common interface implemented by all hash functions. | ||
// | ||
// Hash implementations in the standard library (e.g. hash/crc32 and | ||
// crypto/sha256) implement the encoding.BinaryMarshaler and | ||
// encoding.BinaryUnmarshaler interfaces. Marshaling a hash implementation | ||
// allows its internal state to be saved and used for additional processing | ||
// later, without having to re-write the data previously written to the hash. | ||
// The hash state may contain portions of the input in its original form, | ||
// which users are expected to handle for any possible security implications. | ||
// | ||
// Compatibility: Any future changes to hash or crypto packages will endeavor | ||
// to maintain compatibility with state encoded using previous versions. | ||
// That is, any released versions of the packages should be able to | ||
// decode data written with any previously released version, | ||
// subject to issues such as security fixes. | ||
// See the Go compatibility document for background: https://golang.org/doc/go1compat | ||
type Hash interface { | ||
// Write (via the embedded io.Writer interface) adds more data to the running hash. | ||
// It never returns an error. | ||
io.Writer | ||
|
||
// Sum appends the current hash to b and returns the resulting slice. | ||
// It does not change the underlying hash state. | ||
Sum(b []byte) []byte | ||
|
||
// Reset resets the Hash to its initial state. | ||
Reset() | ||
|
||
// Size returns the number of bytes Sum will return. | ||
Size() int | ||
|
||
// BlockSize returns the hash's underlying block size. | ||
// The Write method must be able to accept any amount | ||
// of data, but it may operate more efficiently if all writes | ||
// are a multiple of the block size. | ||
BlockSize() int | ||
} | ||
|
||
// Hash32 is the common interface implemented by all 32-bit hash functions. | ||
type Hash32 interface { | ||
Hash | ||
Sum32() uint32 | ||
} | ||
|
||
// Hash64 is the common interface implemented by all 64-bit hash functions. | ||
type Hash64 interface { | ||
Hash | ||
Sum64() uint64 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Test that the hashes in the standard library implement | ||
// BinaryMarshaler, BinaryUnmarshaler, | ||
// and lock in the current representations. | ||
|
||
package hash | ||
|
||
import ( | ||
"bytes" | ||
"crypto/md5" | ||
"crypto/sha1" | ||
"crypto/sha256" | ||
"encoding" | ||
"encoding/hex" | ||
"hash" | ||
"hash/adler32" | ||
"testing" | ||
) | ||
|
||
func fromHex(s string) []byte { | ||
b, err := hex.DecodeString(s) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return b | ||
} | ||
|
||
var marshalTests = []struct { | ||
name string | ||
new func() hash.Hash | ||
golden []byte | ||
}{ | ||
{"adler32", func() hash.Hash { return adler32.New() }, fromHex("61646c01460a789d")}, | ||
} | ||
|
||
func TestMarshalHash(t *testing.T) { | ||
for _, tt := range marshalTests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
buf := make([]byte, 256) | ||
for i := range buf { | ||
buf[i] = byte(i) | ||
} | ||
|
||
h := tt.new() | ||
h.Write(buf[:256]) | ||
sum := h.Sum(nil) | ||
|
||
h2 := tt.new() | ||
h3 := tt.new() | ||
const split = 249 | ||
for i := 0; i < split; i++ { | ||
h2.Write(buf[i : i+1]) | ||
} | ||
h2m, ok := h2.(encoding.BinaryMarshaler) | ||
if !ok { | ||
t.Fatalf("Hash does not implement MarshalBinary") | ||
} | ||
enc, err := h2m.MarshalBinary() | ||
if err != nil { | ||
t.Fatalf("MarshalBinary: %v", err) | ||
} | ||
if !bytes.Equal(enc, tt.golden) { | ||
t.Errorf("MarshalBinary = %x, want %x", enc, tt.golden) | ||
} | ||
h3u, ok := h3.(encoding.BinaryUnmarshaler) | ||
if !ok { | ||
t.Fatalf("Hash does not implement UnmarshalBinary") | ||
} | ||
if err := h3u.UnmarshalBinary(enc); err != nil { | ||
t.Fatalf("UnmarshalBinary: %v", err) | ||
} | ||
h2.Write(buf[split:]) | ||
h3.Write(buf[split:]) | ||
sum2 := h2.Sum(nil) | ||
sum3 := h3.Sum(nil) | ||
if !bytes.Equal(sum2, sum) { | ||
t.Fatalf("Sum after MarshalBinary = %x, want %x", sum2, sum) | ||
} | ||
if !bytes.Equal(sum3, sum) { | ||
t.Fatalf("Sum after UnmarshalBinary = %x, want %x", sum3, sum) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not directly related to this particular pull request, but if I remember correctly, we had discussed completely prohibiting this import at some stage.
cc @jaekwon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's okay actualy.