leb128.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Package obu implements tools for working with the "Open Bitstream Unit"
  2. package obu
  3. import "errors"
  4. const (
  5. sevenLsbBitmask = uint(0b01111111)
  6. msbBitmask = uint(0b10000000)
  7. )
  8. // ErrFailedToReadLEB128 indicates that a buffer ended before a LEB128 value could be successfully read
  9. var ErrFailedToReadLEB128 = errors.New("payload ended before LEB128 was finished")
  10. // EncodeLEB128 encodes a uint as LEB128
  11. func EncodeLEB128(in uint) (out uint) {
  12. for {
  13. // Copy seven bits from in and discard
  14. // what we have copied from in
  15. out |= (in & sevenLsbBitmask)
  16. in >>= 7
  17. // If we have more bits to encode set MSB
  18. // otherwise we are done
  19. if in != 0 {
  20. out |= msbBitmask
  21. out <<= 8
  22. } else {
  23. return out
  24. }
  25. }
  26. }
  27. func decodeLEB128(in uint) (out uint) {
  28. for {
  29. // Take 7 LSB from in
  30. out |= (in & sevenLsbBitmask)
  31. // Discard the MSB
  32. in >>= 8
  33. if in == 0 {
  34. return out
  35. }
  36. out <<= 7
  37. }
  38. }
  39. // ReadLeb128 scans an buffer and decodes a Leb128 value.
  40. // If the end of the buffer is reached and all MSB are set
  41. // an error is returned
  42. func ReadLeb128(in []byte) (uint, uint, error) {
  43. var encodedLength uint
  44. for i := range in {
  45. encodedLength |= uint(in[i])
  46. if in[i]&byte(msbBitmask) == 0 {
  47. return decodeLEB128(encodedLength), uint(i + 1), nil
  48. }
  49. // Make more room for next read
  50. encodedLength <<= 8
  51. }
  52. return 0, 0, ErrFailedToReadLEB128
  53. }