|
|
@ -20,6 +20,9 @@ type ECC interface { |
|
|
|
CheckECC([]byte) ([]byte, error) |
|
|
|
} |
|
|
|
|
|
|
|
var errInputTooShort = errors.New("input too short, no checksum present") |
|
|
|
var errChecksumDoesntMatch = errors.New("checksum does not match") |
|
|
|
|
|
|
|
// NoECC is a no-op placeholder, kind of useless... except for tests
|
|
|
|
type NoECC struct{} |
|
|
|
|
|
|
@ -34,9 +37,9 @@ type CRC16 struct { |
|
|
|
table *crc16.Table |
|
|
|
} |
|
|
|
|
|
|
|
var _ ECC = &CRC16{} |
|
|
|
var _ ECC = (*CRC16)(nil) |
|
|
|
|
|
|
|
const crc16Size = 2 |
|
|
|
const crc16ByteCount = 2 |
|
|
|
|
|
|
|
func NewIBMCRC16() *CRC16 { |
|
|
|
return &CRC16{Poly: crc16.IBM} |
|
|
@ -55,7 +58,7 @@ func (c *CRC16) AddECC(input []byte) []byte { |
|
|
|
|
|
|
|
// get crc and convert to some bytes...
|
|
|
|
crc := crc16.Checksum(input, table) |
|
|
|
check := make([]byte, crc16Size) |
|
|
|
check := make([]byte, crc16ByteCount) |
|
|
|
binary.BigEndian.PutUint16(check, crc) |
|
|
|
|
|
|
|
// append it to the input
|
|
|
@ -66,26 +69,27 @@ func (c *CRC16) AddECC(input []byte) []byte { |
|
|
|
func (c *CRC16) CheckECC(input []byte) ([]byte, error) { |
|
|
|
table := c.getTable() |
|
|
|
|
|
|
|
if len(input) <= crc16Size { |
|
|
|
return nil, errors.New("input too short, no checksum present") |
|
|
|
if len(input) <= crc16ByteCount { |
|
|
|
return nil, errInputTooShort |
|
|
|
} |
|
|
|
cut := len(input) - crc16Size |
|
|
|
cut := len(input) - crc16ByteCount |
|
|
|
data, check := input[:cut], input[cut:] |
|
|
|
crc := binary.BigEndian.Uint16(check) |
|
|
|
calc := crc16.Checksum(data, table) |
|
|
|
if crc != calc { |
|
|
|
return nil, errors.New("Checksum does not match") |
|
|
|
return nil, errChecksumDoesntMatch |
|
|
|
} |
|
|
|
return data, nil |
|
|
|
} |
|
|
|
|
|
|
|
func (c *CRC16) getTable() *crc16.Table { |
|
|
|
if c.table == nil { |
|
|
|
if c.Poly == 0 { |
|
|
|
c.Poly = crc16.IBM |
|
|
|
} |
|
|
|
c.table = crc16.MakeTable(c.Poly) |
|
|
|
if c.table != nil { |
|
|
|
return c.table |
|
|
|
} |
|
|
|
if c.Poly == 0 { |
|
|
|
c.Poly = crc16.IBM |
|
|
|
} |
|
|
|
c.table = crc16.MakeTable(c.Poly) |
|
|
|
return c.table |
|
|
|
} |
|
|
|
|
|
|
@ -95,7 +99,7 @@ type CRC32 struct { |
|
|
|
table *crc32.Table |
|
|
|
} |
|
|
|
|
|
|
|
var _ ECC = &CRC32{} |
|
|
|
var _ ECC = (*CRC32)(nil) |
|
|
|
|
|
|
|
func NewIEEECRC32() *CRC32 { |
|
|
|
return &CRC32{Poly: crc32.IEEE} |
|
|
@ -126,14 +130,14 @@ func (c *CRC32) CheckECC(input []byte) ([]byte, error) { |
|
|
|
table := c.getTable() |
|
|
|
|
|
|
|
if len(input) <= crc32.Size { |
|
|
|
return nil, errors.New("input too short, no checksum present") |
|
|
|
return nil, errInputTooShort |
|
|
|
} |
|
|
|
cut := len(input) - crc32.Size |
|
|
|
data, check := input[:cut], input[cut:] |
|
|
|
crc := binary.BigEndian.Uint32(check) |
|
|
|
calc := crc32.Checksum(data, table) |
|
|
|
if crc != calc { |
|
|
|
return nil, errors.New("Checksum does not match") |
|
|
|
return nil, errChecksumDoesntMatch |
|
|
|
} |
|
|
|
return data, nil |
|
|
|
} |
|
|
@ -154,7 +158,7 @@ type CRC64 struct { |
|
|
|
table *crc64.Table |
|
|
|
} |
|
|
|
|
|
|
|
var _ ECC = &CRC64{} |
|
|
|
var _ ECC = (*CRC64)(nil) |
|
|
|
|
|
|
|
func NewISOCRC64() *CRC64 { |
|
|
|
return &CRC64{Poly: crc64.ISO} |
|
|
@ -181,14 +185,14 @@ func (c *CRC64) CheckECC(input []byte) ([]byte, error) { |
|
|
|
table := c.getTable() |
|
|
|
|
|
|
|
if len(input) <= crc64.Size { |
|
|
|
return nil, errors.New("input too short, no checksum present") |
|
|
|
return nil, errInputTooShort |
|
|
|
} |
|
|
|
cut := len(input) - crc64.Size |
|
|
|
data, check := input[:cut], input[cut:] |
|
|
|
crc := binary.BigEndian.Uint64(check) |
|
|
|
calc := crc64.Checksum(data, table) |
|
|
|
if crc != calc { |
|
|
|
return nil, errors.New("Checksum does not match") |
|
|
|
return nil, errChecksumDoesntMatch |
|
|
|
} |
|
|
|
return data, nil |
|
|
|
} |
|
|
|