1// 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}
204