With per-chunk validation in hand, you can vet a whole file. Today you extend the chunk walk to check every CRC and fail fast on the first corrupt chunk, so nothing downstream ever sees bad data.
Walk a PNG and confirm every chunk's CRC, returning an error that names the first chunk whose CRC does not match.
This closes the integrity chapter with a single guarantee: run Verify and either every chunk is sound or you learn exactly which one is not. It reuses the chunk walk from chapter one and the per-chunk Valid check, and the naming matters - “bad CRC in IDAT chunk” tells a caller precisely where the damage is, which is far more useful than a bare failure. A corrupt byte in the compressed image data is caught here, before the inflater ever tries to make sense of it.
You now have a container you can fully trust: recognized by signature, split into chunks, and every chunk proven intact. That trust is the foundation the hard part stands on. The next chapter opens the IDAT payload and begins the real work - turning that compressed zlib stream back into raw bytes.
func Verify(b []byte) error {chunks, err := Chunks(b)if err != nil { return err }for _, c := range chunks {if !c.Valid() { return fmt.Errorf("bad CRC in %s chunk", c.Type) }}return nil}