Go provides Cast(buf []byte) (Multihash, error) for validating and casting raw bytes to a Multihash, and MHFromBytes(buf []byte) (int, Multihash, error) for reading a multihash from the beginning of a buffer with bytes-consumed tracking. Python has decode() but no direct equivalents.
Problem
Go's multihash.go:
// Cast casts a buffer onto a multihash, and returns an error if it does not work.
func Cast(buf []byte) (Multihash, error) {
_, err := Decode(buf)
if err != nil { return nil, err }
return Multihash(buf), nil
}
// MHFromBytes reads a multihash from the given byte buffer,
// returning the number of bytes read and the multihash.
func MHFromBytes(buf []byte) (int, Multihash, error) {
nr, _, _, err := readMultihashFromBuf(buf)
if err != nil { return 0, nil, err }
return nr, Multihash(buf[:nr]), nil
}
MHFromBytes is particularly useful when parsing a stream that contains a multihash followed by other data — it tells you exactly how many bytes the multihash consumed.
Python's decode() always consumes the entire input and doesn't return bytes consumed.
Proposed Solution
Add both functions:
def cast(buf: bytes) -> bytes:
"""Validate and return multihash bytes. Raises ValueError if invalid."""
decode(buf) # Validates
return buf
def from_bytes_with_length(buf: bytes) -> tuple[int, "Multihash"]:
"""Read a multihash from the beginning of buf.
Returns (bytes_consumed, Multihash).
Unlike decode(), this handles buffers with trailing data.
"""
buffer = BytesIO(buf)
code = varint.decode_stream(buffer)
if not is_valid_code(code):
raise ValueError(f"Unsupported hash code {code}")
length = varint.decode_stream(buffer)
digest = buffer.read(length)
if len(digest) != length:
raise ValueError(f"Insufficient data: expected {length} bytes, got {len(digest)}")
bytes_consumed = buffer.tell()
name = constants.CODE_HASHES.get(code, code)
return bytes_consumed, Multihash(code=code, name=name, length=length, digest=digest)
Export from __init__.py and add tests.
Related
Go provides
Cast(buf []byte) (Multihash, error)for validating and casting raw bytes to a Multihash, andMHFromBytes(buf []byte) (int, Multihash, error)for reading a multihash from the beginning of a buffer with bytes-consumed tracking. Python hasdecode()but no direct equivalents.Problem
Go's
multihash.go:MHFromBytesis particularly useful when parsing a stream that contains a multihash followed by other data — it tells you exactly how many bytes the multihash consumed.Python's
decode()always consumes the entire input and doesn't return bytes consumed.Proposed Solution
Add both functions:
Export from
__init__.pyand add tests.Related
multihash.go