punycode.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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, code16("A3", "P4")} }
  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 unicode16 && r == 0xfffd {
  104. return s, &labelError{s, "A3"}
  105. }
  106. if r < 0x80 {
  107. b++
  108. output = append(output, byte(r))
  109. } else {
  110. remaining++
  111. }
  112. }
  113. h := b
  114. if b > 0 {
  115. output = append(output, '-')
  116. }
  117. overflow := false
  118. for remaining != 0 {
  119. m := int32(0x7fffffff)
  120. for _, r := range s {
  121. if m > r && r >= n {
  122. m = r
  123. }
  124. }
  125. delta, overflow = madd(delta, m-n, h+1)
  126. if overflow {
  127. return "", punyError(s)
  128. }
  129. n = m
  130. for _, r := range s {
  131. if r < n {
  132. delta++
  133. if delta < 0 {
  134. return "", punyError(s)
  135. }
  136. continue
  137. }
  138. if r > n {
  139. continue
  140. }
  141. q := delta
  142. for k := base; ; k += base {
  143. t := k - bias
  144. if k <= bias {
  145. t = tmin
  146. } else if k >= bias+tmax {
  147. t = tmax
  148. }
  149. if q < t {
  150. break
  151. }
  152. output = append(output, encodeDigit(t+(q-t)%(base-t)))
  153. q = (q - t) / (base - t)
  154. }
  155. output = append(output, encodeDigit(q))
  156. bias = adapt(delta, h+1, h == b)
  157. delta = 0
  158. h++
  159. remaining--
  160. }
  161. delta++
  162. n++
  163. }
  164. return string(output), nil
  165. }
  166. // madd computes a + (b * c), detecting overflow.
  167. func madd(a, b, c int32) (next int32, overflow bool) {
  168. p := int64(b) * int64(c)
  169. if p > math.MaxInt32-int64(a) {
  170. return 0, true
  171. }
  172. return a + int32(p), false
  173. }
  174. func decodeDigit(x byte) (digit int32, ok bool) {
  175. switch {
  176. case '0' <= x && x <= '9':
  177. return int32(x - ('0' - 26)), true
  178. case 'A' <= x && x <= 'Z':
  179. return int32(x - 'A'), true
  180. case 'a' <= x && x <= 'z':
  181. return int32(x - 'a'), true
  182. }
  183. return 0, false
  184. }
  185. func encodeDigit(digit int32) byte {
  186. switch {
  187. case 0 <= digit && digit < 26:
  188. return byte(digit + 'a')
  189. case 26 <= digit && digit < 36:
  190. return byte(digit + ('0' - 26))
  191. }
  192. panic("idna: internal error in punycode encoding")
  193. }
  194. // adapt is the bias adaptation function specified in section 6.1.
  195. func adapt(delta, numPoints int32, firstTime bool) int32 {
  196. if firstTime {
  197. delta /= damp
  198. } else {
  199. delta /= 2
  200. }
  201. delta += delta / numPoints
  202. k := int32(0)
  203. for delta > ((base-tmin)*tmax)/2 {
  204. delta /= base - tmin
  205. k += base
  206. }
  207. return k + (base-tmin+1)*delta/(delta+skew)
  208. }