| 320 | } |
| 321 | |
| 322 | func (s *Fast) encodeImpl(buf *bytes.Buffer, enc *base64.Encoder, hash *util.FNV64) error { |
| 323 | if s.large != nil && s.large.Min() < 0 { |
| 324 | return errors.AssertionFailedf("Encode used with negative elements") |
| 325 | } |
| 326 | |
| 327 | write := func(b []byte) { |
| 328 | if buf != nil { |
| 329 | buf.Write(b) |
| 330 | } else { |
| 331 | enc.Write(b) |
| 332 | for i := range b { |
| 333 | hash.Add(uint64(b[i])) |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | // This slice should stay on stack. We only need enough bytes to encode a 0 |
| 339 | // and then an arbitrary 64-bit integer. |
| 340 | //gcassert:noescape |
| 341 | tmp := make([]byte, binary.MaxVarintLen64+1) |
| 342 | |
| 343 | var n int |
| 344 | if s.small.hi == 0 && s.fitsInSmall() { |
| 345 | n = binary.PutUvarint(tmp, 0) |
| 346 | n += binary.PutUvarint(tmp[n:], s.small.lo) |
| 347 | write(tmp[:n]) |
| 348 | } else { |
| 349 | n = binary.PutUvarint(tmp, uint64(s.Len())) |
| 350 | write(tmp[:n]) |
| 351 | for i, ok := s.Next(0); ok; i, ok = s.Next(i + 1) { |
| 352 | n := binary.PutUvarint(tmp, uint64(i)) |
| 353 | write(tmp[:n]) |
| 354 | } |
| 355 | } |
| 356 | return nil |
| 357 | } |
| 358 | |
| 359 | // Decode does the opposite of Encode. The contents of the receiver are |
| 360 | // overwritten. |