github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/idna/punycode.go (about) 1 // Code generated by running "go generate" in github.com/Andyfoo/golang/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 7 package idna 8 9 // This file implements the Punycode algorithm from RFC 3492. 10 11 import ( 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. 21 const ( 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 31 func punyError(s string) error { return &labelError{s, "A3"} } 32 33 // decode decodes a string as specified in section 6.2. 34 func 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. 101 func 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 167 func 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 179 func 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. 190 func 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 }