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.

203 lines
4.3 KiB

  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. for pos < len(encoded) {
  46. oldI, w := i, int32(1)
  47. for k := base; ; k += base {
  48. if pos == len(encoded) {
  49. return "", punyError(encoded)
  50. }
  51. digit, ok := decodeDigit(encoded[pos])
  52. if !ok {
  53. return "", punyError(encoded)
  54. }
  55. pos++
  56. i += digit * w
  57. if i < 0 {
  58. return "", punyError(encoded)
  59. }
  60. t := k - bias
  61. if t < tmin {
  62. t = tmin
  63. } else if t > tmax {
  64. t = tmax
  65. }
  66. if digit < t {
  67. break
  68. }
  69. w *= base - t
  70. if w >= math.MaxInt32/base {
  71. return "", punyError(encoded)
  72. }
  73. }
  74. x := int32(len(output) + 1)
  75. bias = adapt(i-oldI, x, oldI == 0)
  76. n += i / x
  77. i %= x
  78. if n > utf8.MaxRune || len(output) >= 1024 {
  79. return "", punyError(encoded)
  80. }
  81. output = append(output, 0)
  82. copy(output[i+1:], output[i:])
  83. output[i] = n
  84. i++
  85. }
  86. return string(output), nil
  87. }
  88. // encode encodes a string as specified in section 6.3 and prepends prefix to
  89. // the result.
  90. //
  91. // The "while h < length(input)" line in the specification becomes "for
  92. // remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
  93. func encode(prefix, s string) (string, error) {
  94. output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
  95. copy(output, prefix)
  96. delta, n, bias := int32(0), initialN, initialBias
  97. b, remaining := int32(0), int32(0)
  98. for _, r := range s {
  99. if r < 0x80 {
  100. b++
  101. output = append(output, byte(r))
  102. } else {
  103. remaining++
  104. }
  105. }
  106. h := b
  107. if b > 0 {
  108. output = append(output, '-')
  109. }
  110. for remaining != 0 {
  111. m := int32(0x7fffffff)
  112. for _, r := range s {
  113. if m > r && r >= n {
  114. m = r
  115. }
  116. }
  117. delta += (m - n) * (h + 1)
  118. if delta < 0 {
  119. return "", punyError(s)
  120. }
  121. n = m
  122. for _, r := range s {
  123. if r < n {
  124. delta++
  125. if delta < 0 {
  126. return "", punyError(s)
  127. }
  128. continue
  129. }
  130. if r > n {
  131. continue
  132. }
  133. q := delta
  134. for k := base; ; k += base {
  135. t := k - bias
  136. if t < tmin {
  137. t = tmin
  138. } else if t > tmax {
  139. t = tmax
  140. }
  141. if q < t {
  142. break
  143. }
  144. output = append(output, encodeDigit(t+(q-t)%(base-t)))
  145. q = (q - t) / (base - t)
  146. }
  147. output = append(output, encodeDigit(q))
  148. bias = adapt(delta, h+1, h == b)
  149. delta = 0
  150. h++
  151. remaining--
  152. }
  153. delta++
  154. n++
  155. }
  156. return string(output), nil
  157. }
  158. func decodeDigit(x byte) (digit int32, ok bool) {
  159. switch {
  160. case '0' <= x && x <= '9':
  161. return int32(x - ('0' - 26)), true
  162. case 'A' <= x && x <= 'Z':
  163. return int32(x - 'A'), true
  164. case 'a' <= x && x <= 'z':
  165. return int32(x - 'a'), true
  166. }
  167. return 0, false
  168. }
  169. func encodeDigit(digit int32) byte {
  170. switch {
  171. case 0 <= digit && digit < 26:
  172. return byte(digit + 'a')
  173. case 26 <= digit && digit < 36:
  174. return byte(digit + ('0' - 26))
  175. }
  176. panic("idna: internal error in punycode encoding")
  177. }
  178. // adapt is the bias adaptation function specified in section 6.1.
  179. func adapt(delta, numPoints int32, firstTime bool) int32 {
  180. if firstTime {
  181. delta /= damp
  182. } else {
  183. delta /= 2
  184. }
  185. delta += delta / numPoints
  186. k := int32(0)
  187. for delta > ((base-tmin)*tmax)/2 {
  188. delta /= base - tmin
  189. k += base
  190. }
  191. return k + (base-tmin+1)*delta/(delta+skew)
  192. }