Source file src/vendor/golang.org/x/net/idna/punycode.go

     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  	"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, code16("A3", "P4")} }
    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  	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 := 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 unicode16 && r == 0xfffd {
   112  			return s, &labelError{s, "A3"}
   113  		}
   114  		if r < 0x80 {
   115  			b++
   116  			output = append(output, byte(r))
   117  		} else {
   118  			remaining++
   119  		}
   120  	}
   121  	h := b
   122  	if b > 0 {
   123  		output = append(output, '-')
   124  	}
   125  	overflow := false
   126  	for remaining != 0 {
   127  		m := int32(0x7fffffff)
   128  		for _, r := range s {
   129  			if m > r && r >= n {
   130  				m = r
   131  			}
   132  		}
   133  		delta, overflow = madd(delta, m-n, h+1)
   134  		if overflow {
   135  			return "", punyError(s)
   136  		}
   137  		n = m
   138  		for _, r := range s {
   139  			if r < n {
   140  				delta++
   141  				if delta < 0 {
   142  					return "", punyError(s)
   143  				}
   144  				continue
   145  			}
   146  			if r > n {
   147  				continue
   148  			}
   149  			q := delta
   150  			for k := base; ; k += base {
   151  				t := k - bias
   152  				if k <= bias {
   153  					t = tmin
   154  				} else if k >= bias+tmax {
   155  					t = tmax
   156  				}
   157  				if q < t {
   158  					break
   159  				}
   160  				output = append(output, encodeDigit(t+(q-t)%(base-t)))
   161  				q = (q - t) / (base - t)
   162  			}
   163  			output = append(output, encodeDigit(q))
   164  			bias = adapt(delta, h+1, h == b)
   165  			delta = 0
   166  			h++
   167  			remaining--
   168  		}
   169  		delta++
   170  		n++
   171  	}
   172  	return string(output), nil
   173  }
   174  
   175  // madd computes a + (b * c), detecting overflow.
   176  func madd(a, b, c int32) (next int32, overflow bool) {
   177  	p := int64(b) * int64(c)
   178  	if p > math.MaxInt32-int64(a) {
   179  		return 0, true
   180  	}
   181  	return a + int32(p), false
   182  }
   183  
   184  func decodeDigit(x byte) (digit int32, ok bool) {
   185  	switch {
   186  	case '0' <= x && x <= '9':
   187  		return int32(x - ('0' - 26)), true
   188  	case 'A' <= x && x <= 'Z':
   189  		return int32(x - 'A'), true
   190  	case 'a' <= x && x <= 'z':
   191  		return int32(x - 'a'), true
   192  	}
   193  	return 0, false
   194  }
   195  
   196  func encodeDigit(digit int32) byte {
   197  	switch {
   198  	case 0 <= digit && digit < 26:
   199  		return byte(digit + 'a')
   200  	case 26 <= digit && digit < 36:
   201  		return byte(digit + ('0' - 26))
   202  	}
   203  	panic("idna: internal error in punycode encoding")
   204  }
   205  
   206  // adapt is the bias adaptation function specified in section 6.1.
   207  func adapt(delta, numPoints int32, firstTime bool) int32 {
   208  	if firstTime {
   209  		delta /= damp
   210  	} else {
   211  		delta /= 2
   212  	}
   213  	delta += delta / numPoints
   214  	k := int32(0)
   215  	for delta > ((base-tmin)*tmax)/2 {
   216  		delta /= base - tmin
   217  		k += base
   218  	}
   219  	return k + (base-tmin+1)*delta/(delta+skew)
   220  }
   221  

View as plain text