code: func (s *asmState) Read(out []byte) (n int, err error) {
  	n = len(out)
  
  	// need to pad if we were absorbing
  	if s.state == spongeAbsorbing {
  		s.state = spongeSqueezing
  
  		// write hash directly into out if possible
  		if len(out)%s.rate == 0 {
  			klmd(s.function, &s.a, out, s.buf) // len(out) may be 0
  			s.buf = s.buf[:0]
  			return
  		}
  
  		// write hash into buffer
  		max := cap(s.buf)
  		if max > len(out) {
  			max = (len(out)/s.rate)*s.rate + s.rate
  		}
  		klmd(s.function, &s.a, s.buf[:max], s.buf)
  		s.buf = s.buf[:max]
  	}
  
  	for len(out) > 0 {
  		// flush the buffer
  		if len(s.buf) != 0 {
  			c := copy(out, s.buf)
  			out = out[c:]
  			s.buf = s.buf[c:]
  			continue
  		}
  
  		// write hash directly into out if possible
  		if len(out)%s.rate == 0 {
  			klmd(s.function|nopad, &s.a, out, nil)
  			return
  		}
  
  		// write hash into buffer
  		s.resetBuf()
  		if cap(s.buf) > len(out) {
  			s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate]
  		}
  		klmd(s.function|nopad, &s.a, s.buf, nil)
  	}
  	return
  }
docs: // Read squeezes an arbitrary number of bytes from the sponge.