punycode.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
  2. // Copyright 2016 The Go Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package idna
  6. // This file implements the Punycode algorithm from RFC 3492.
  7. import (
  8. "math"
  9. "strings"
  10. "unicode/utf8"
  11. )
  12. // These parameter values are specified in section 5.
  13. //
  14. // All computation is done with int32s, so that overflow behavior is identical
  15. // regardless of whether int is 32-bit or 64-bit.
  16. const (
  17. base int32 = 36
  18. damp int32 = 700
  19. initialBias int32 = 72
  20. initialN int32 = 128
  21. skew int32 = 38
  22. tmax int32 = 26
  23. tmin int32 = 1
  24. )
  25. func punyError(s string) error { return &labelError{s, "A3"} }
  26. // decode decodes a string as specified in section 6.2.
  27. func decode(encoded string) (string, error) {
  28. if encoded == "" {
  29. return "", nil
  30. }
  31. pos := 1 + strings.LastIndex(encoded, "-")
  32. if pos == 1 {
  33. return "", punyError(encoded)
  34. }
  35. if pos == len(encoded) {
  36. return encoded[:len(encoded)-1], nil
  37. }
  38. output := make([]rune, 0, len(encoded))
  39. if pos != 0 {
  40. for _, r := range encoded[:pos-1] {
  41. output = append(output, r)
  42. }
  43. }
  44. i, n, bias := int32(0), initialN, initialBias
  45. overflow := false
  46. for pos < len(encoded) {
  47. oldI, w := i, int32(1)
  48. for k := base; ; k += base {
  49. if pos == len(encoded) {
  50. return "", punyError(encoded)
  51. }
  52. digit, ok := decodeDigit(encoded[pos])
  53. if !ok {
  54. return "", punyError(encoded)
  55. }
  56. pos++
  57. i, overflow = madd(i, digit, w)
  58. if overflow {
  59. return "", punyError(encoded)
  60. }
  61. t := k - bias
  62. if k <= bias {
  63. t = tmin
  64. } else if k >= bias+tmax {
  65. t = tmax
  66. }
  67. if digit < t {
  68. break
  69. }
  70. w, overflow = madd(0, w, base-t)
  71. if overflow {
  72. return "", punyError(encoded)
  73. }
  74. }
  75. if len(output) >= 1024 {
  76. return "", punyError(encoded)
  77. }
  78. x := int32(len(output) + 1)
  79. bias = adapt(i-oldI, x, oldI == 0)
  80. n += i / x
  81. i %= x
  82. if n < 0 || n > utf8.MaxRune {
  83. return "", punyError(encoded)
  84. }
  85. output = append(output, 0)
  86. copy(output[i+1:], output[i:])
  87. output[i] = n
  88. i++
  89. }
  90. return string(output), nil
  91. }
  92. // encode encodes a string as specified in section 6.3 and prepends prefix to
  93. // the result.
  94. //
  95. // The "while h < length(input)" line in the specification becomes "for
  96. // remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
  97. func encode(prefix, s string) (string, error) {
  98. output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
  99. copy(output, prefix)
  100. delta, n, bias := int32(0), initialN, initialBias
  101. b, remaining := int32(0), int32(0)
  102. for _, r := range s {
  103. if r < 0x80 {
  104. b++
  105. output = append(output, byte(r))
  106. } else {
  107. remaining++
  108. }
  109. }
  110. h := b
  111. if b > 0 {
  112. output = append(output, '-')
  113. }
  114. overflow := false
  115. for remaining != 0 {
  116. m := int32(0x7fffffff)
  117. for _, r := range s {
  118. if m > r && r >= n {
  119. m = r
  120. }
  121. }
  122. delta, overflow = madd(delta, m-n, h+1)
  123. if overflow {
  124. return "", punyError(s)
  125. }
  126. n = m
  127. for _, r := range s {
  128. if r < n {
  129. delta++
  130. if delta < 0 {
  131. return "", punyError(s)
  132. }
  133. continue
  134. }
  135. if r > n {
  136. continue
  137. }
  138. q := delta
  139. for k := base; ; k += base {
  140. t := k - bias
  141. if k <= bias {
  142. t = tmin
  143. } else if k >= bias+tmax {
  144. t = tmax
  145. }
  146. if q < t {
  147. break
  148. }
  149. output = append(output, encodeDigit(t+(q-t)%(base-t)))
  150. q = (q - t) / (base - t)
  151. }
  152. output = append(output, encodeDigit(q))
  153. bias = adapt(delta, h+1, h == b)
  154. delta = 0
  155. h++
  156. remaining--
  157. }
  158. delta++
  159. n++
  160. }
  161. return string(output), nil
  162. }
  163. // madd computes a + (b * c), detecting overflow.
  164. func madd(a, b, c int32) (next int32, overflow bool) {
  165. p := int64(b) * int64(c)
  166. if p > math.MaxInt32-int64(a) {
  167. return 0, true
  168. }
  169. return a + int32(p), false
  170. }
  171. func decodeDigit(x byte) (digit int32, ok bool) {
  172. switch {
  173. case '0' <= x && x <= '9':
  174. return int32(x - ('0' - 26)), true
  175. case 'A' <= x && x <= 'Z':
  176. return int32(x - 'A'), true
  177. case 'a' <= x && x <= 'z':
  178. return int32(x - 'a'), true
  179. }
  180. return 0, false
  181. }
  182. func encodeDigit(digit int32) byte {
  183. switch {
  184. case 0 <= digit && digit < 26:
  185. return byte(digit + 'a')
  186. case 26 <= digit && digit < 36:
  187. return byte(digit + ('0' - 26))
  188. }
  189. panic("idna: internal error in punycode encoding")
  190. }
  191. // adapt is the bias adaptation function specified in section 6.1.
  192. func adapt(delta, numPoints int32, firstTime bool) int32 {
  193. if firstTime {
  194. delta /= damp
  195. } else {
  196. delta /= 2
  197. }
  198. delta += delta / numPoints
  199. k := int32(0)
  200. for delta > ((base-tmin)*tmax)/2 {
  201. delta /= base - tmin
  202. k += base
  203. }
  204. return k + (base-tmin+1)*delta/(delta+skew)
  205. }