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