blob: e8e3ac11a94b1920987183390d9dd09658311bcd [file] [log] [blame]
kesavand2cde6582020-06-22 04:56:23 -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
kesavandc71914f2022-03-25 11:19:03 +053052 overflow := false
kesavand2cde6582020-06-22 04:56:23 -040053 for pos < len(encoded) {
54 oldI, w := i, int32(1)
55 for k := base; ; k += base {
56 if pos == len(encoded) {
57 return "", punyError(encoded)
58 }
59 digit, ok := decodeDigit(encoded[pos])
60 if !ok {
61 return "", punyError(encoded)
62 }
63 pos++
kesavandc71914f2022-03-25 11:19:03 +053064 i, overflow = madd(i, digit, w)
65 if overflow {
kesavand2cde6582020-06-22 04:56:23 -040066 return "", punyError(encoded)
67 }
68 t := k - bias
kesavandc71914f2022-03-25 11:19:03 +053069 if k <= bias {
kesavand2cde6582020-06-22 04:56:23 -040070 t = tmin
kesavandc71914f2022-03-25 11:19:03 +053071 } else if k >= bias+tmax {
kesavand2cde6582020-06-22 04:56:23 -040072 t = tmax
73 }
74 if digit < t {
75 break
76 }
kesavandc71914f2022-03-25 11:19:03 +053077 w, overflow = madd(0, w, base-t)
78 if overflow {
kesavand2cde6582020-06-22 04:56:23 -040079 return "", punyError(encoded)
80 }
81 }
kesavandc71914f2022-03-25 11:19:03 +053082 if len(output) >= 1024 {
83 return "", punyError(encoded)
84 }
kesavand2cde6582020-06-22 04:56:23 -040085 x := int32(len(output) + 1)
86 bias = adapt(i-oldI, x, oldI == 0)
87 n += i / x
88 i %= x
kesavandc71914f2022-03-25 11:19:03 +053089 if n < 0 || n > utf8.MaxRune {
kesavand2cde6582020-06-22 04:56:23 -040090 return "", punyError(encoded)
91 }
92 output = append(output, 0)
93 copy(output[i+1:], output[i:])
94 output[i] = n
95 i++
96 }
97 return string(output), nil
98}
99
100// encode encodes a string as specified in section 6.3 and prepends prefix to
101// the result.
102//
103// The "while h < length(input)" line in the specification becomes "for
104// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
105func encode(prefix, s string) (string, error) {
106 output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
107 copy(output, prefix)
108 delta, n, bias := int32(0), initialN, initialBias
109 b, remaining := int32(0), int32(0)
110 for _, r := range s {
111 if r < 0x80 {
112 b++
113 output = append(output, byte(r))
114 } else {
115 remaining++
116 }
117 }
118 h := b
119 if b > 0 {
120 output = append(output, '-')
121 }
kesavandc71914f2022-03-25 11:19:03 +0530122 overflow := false
kesavand2cde6582020-06-22 04:56:23 -0400123 for remaining != 0 {
124 m := int32(0x7fffffff)
125 for _, r := range s {
126 if m > r && r >= n {
127 m = r
128 }
129 }
kesavandc71914f2022-03-25 11:19:03 +0530130 delta, overflow = madd(delta, m-n, h+1)
131 if overflow {
kesavand2cde6582020-06-22 04:56:23 -0400132 return "", punyError(s)
133 }
134 n = m
135 for _, r := range s {
136 if r < n {
137 delta++
138 if delta < 0 {
139 return "", punyError(s)
140 }
141 continue
142 }
143 if r > n {
144 continue
145 }
146 q := delta
147 for k := base; ; k += base {
148 t := k - bias
kesavandc71914f2022-03-25 11:19:03 +0530149 if k <= bias {
kesavand2cde6582020-06-22 04:56:23 -0400150 t = tmin
kesavandc71914f2022-03-25 11:19:03 +0530151 } else if k >= bias+tmax {
kesavand2cde6582020-06-22 04:56:23 -0400152 t = tmax
153 }
154 if q < t {
155 break
156 }
157 output = append(output, encodeDigit(t+(q-t)%(base-t)))
158 q = (q - t) / (base - t)
159 }
160 output = append(output, encodeDigit(q))
161 bias = adapt(delta, h+1, h == b)
162 delta = 0
163 h++
164 remaining--
165 }
166 delta++
167 n++
168 }
169 return string(output), nil
170}
171
kesavandc71914f2022-03-25 11:19:03 +0530172// madd computes a + (b * c), detecting overflow.
173func madd(a, b, c int32) (next int32, overflow bool) {
174 p := int64(b) * int64(c)
175 if p > math.MaxInt32-int64(a) {
176 return 0, true
177 }
178 return a + int32(p), false
179}
180
kesavand2cde6582020-06-22 04:56:23 -0400181func decodeDigit(x byte) (digit int32, ok bool) {
182 switch {
183 case '0' <= x && x <= '9':
184 return int32(x - ('0' - 26)), true
185 case 'A' <= x && x <= 'Z':
186 return int32(x - 'A'), true
187 case 'a' <= x && x <= 'z':
188 return int32(x - 'a'), true
189 }
190 return 0, false
191}
192
193func encodeDigit(digit int32) byte {
194 switch {
195 case 0 <= digit && digit < 26:
196 return byte(digit + 'a')
197 case 26 <= digit && digit < 36:
198 return byte(digit + ('0' - 26))
199 }
200 panic("idna: internal error in punycode encoding")
201}
202
203// adapt is the bias adaptation function specified in section 6.1.
204func adapt(delta, numPoints int32, firstTime bool) int32 {
205 if firstTime {
206 delta /= damp
207 } else {
208 delta /= 2
209 }
210 delta += delta / numPoints
211 k := int32(0)
212 for delta > ((base-tmin)*tmax)/2 {
213 delta /= base - tmin
214 k += base
215 }
216 return k + (base-tmin+1)*delta/(delta+skew)
217}