You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.6 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. // Package modhex implements modhex encoding and decoding.
  2. package modhex
  3. import (
  4. "errors"
  5. "fmt"
  6. )
  7. const modhexTable = "cbdefghijklnrtuv"
  8. var modhexMap map[byte]byte
  9. func init() {
  10. modhexMap = make(map[byte]byte)
  11. for i, v := range []byte(modhexTable) {
  12. modhexMap[v] = byte(i)
  13. }
  14. }
  15. // EncodedLen returns the length of an encoding of n source bytes.
  16. // Specifically, it returns n * 2.
  17. func EncodedLen(n int) int {
  18. return n * 2
  19. }
  20. // Encode encodes src into EncodedLen(len(src)) bytes of dst.
  21. // It returns the number of bytes written to dst, but this is
  22. // always EncodedLen(len(src)).
  23. // Encode implements modhex encoding.
  24. func Encode(dst, src []byte) int {
  25. i := 0
  26. for _, v := range src {
  27. dst[i] = modhexTable[v>>4]
  28. dst[i+1] = modhexTable[v&0x0f]
  29. i += 2
  30. }
  31. return len(src) * 2
  32. }
  33. // EncodeToString returns the modhex encoding of src.
  34. func EncodeToString(src []byte) string {
  35. // make a new slice to hold the encoded bytes
  36. dst := make([]byte, EncodedLen(len(src)))
  37. // encode it!
  38. Encode(dst, src)
  39. // return the encoded bytes as a string
  40. return string(dst)
  41. }
  42. // DecodedLen returns the length of a decoding of n source bytes.
  43. // Specifically, it returns n / 2.
  44. func DecodedLen(n int) int {
  45. return n / 2
  46. }
  47. // Decode decodes src into DecodedLen(len(src)) bytes, returning
  48. // the actual number of bytes written to dst.
  49. //
  50. // Decode expects that src contains only modhex characters and that
  51. // src has an even length.
  52. // If the input is malformed, Decode returns the number
  53. // of bytes decoded before the error.
  54. func Decode(dst, src []byte) (int, error) {
  55. i, j := 0, 1
  56. for ; j < len(src); j += 2 {
  57. a, ok := modhexMap[src[j-1]]
  58. if !ok {
  59. return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j-1]))
  60. }
  61. b, ok := modhexMap[src[j]]
  62. if !ok {
  63. return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j]))
  64. }
  65. dst[i] = (a << 4) | b
  66. i++
  67. }
  68. if len(src)%2 == 1 {
  69. if _, ok := modhexMap[src[j-1]]; !ok {
  70. return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j-1]))
  71. }
  72. return i, errors.New("modhex: odd length modhex string")
  73. }
  74. return i, nil
  75. }
  76. // DecodeString returns the bytes represesented by the modhex string s.
  77. //
  78. // Decode expects that s contains only modhex characters and that s
  79. // has an even length.
  80. // If the input is malformed, Decode returns the number
  81. // of bytes decoded before the error.
  82. func DecodeString(s string) ([]byte, error) {
  83. // convert the input string to an array of bytes
  84. src := []byte(s)
  85. // make a new slice to hold the decoded bytes
  86. dst := make([]byte, DecodedLen(len(src)))
  87. // decode it!
  88. n, err := Decode(dst, src)
  89. // return the decoded bytes along with any errors that may have occured
  90. return dst[:n], err
  91. }