punycode.mx raw

   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  
   7  package idna
   8  
   9  // This file implements the Punycode algorithm from RFC 3492.
  10  
  11  import (
  12  	"math"
  13  	"bytes"
  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 + bytes.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 := []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  	overflow := false
  53  	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++
  64  			i, overflow = madd(i, digit, w)
  65  			if overflow {
  66  				return "", punyError(encoded)
  67  			}
  68  			t := k - bias
  69  			if k <= bias {
  70  				t = tmin
  71  			} else if k >= bias+tmax {
  72  				t = tmax
  73  			}
  74  			if digit < t {
  75  				break
  76  			}
  77  			w, overflow = madd(0, w, base-t)
  78  			if overflow {
  79  				return "", punyError(encoded)
  80  			}
  81  		}
  82  		if len(output) >= 1024 {
  83  			return "", punyError(encoded)
  84  		}
  85  		x := int32(len(output) + 1)
  86  		bias = adapt(i-oldI, x, oldI == 0)
  87  		n += i / x
  88  		i %= x
  89  		if n < 0 || n > utf8.MaxRune {
  90  			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.
 105  func encode(prefix, s string) (string, error) {
 106  	output := []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  	}
 122  	overflow := false
 123  	for remaining != 0 {
 124  		m := int32(0x7fffffff)
 125  		for _, r := range s {
 126  			if m > r && r >= n {
 127  				m = r
 128  			}
 129  		}
 130  		delta, overflow = madd(delta, m-n, h+1)
 131  		if overflow {
 132  			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
 149  				if k <= bias {
 150  					t = tmin
 151  				} else if k >= bias+tmax {
 152  					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  
 172  // madd computes a + (b * c), detecting overflow.
 173  func 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  
 181  func 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  
 193  func 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.
 204  func 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  }
 218