github.com/cristalhq/base64@v0.1.2/decoder.go (about)

     1  package base64
     2  
     3  import "unsafe"
     4  
     5  //go:nosplit
     6  func (e *Encoding) decode(dst []byte, src []byte) int {
     7  	dstlen := uintptr(len(dst))
     8  	srclen := uintptr(len(src))
     9  	if srclen == 0 || (e.pad && (srclen&3) != 0) {
    10  		return 0
    11  	}
    12  	ip := (*sliceHeader)(unsafe.Pointer(&src)).data
    13  	ipstart := ip
    14  	op := (*sliceHeader)(unsafe.Pointer(&dst)).data
    15  	opstart := op
    16  	var cu uint32
    17  	if srclen >= 8+4 {
    18  		ux := ctou32(ip)
    19  		vx := ctou32(ip + 4)
    20  		for ip < (ipstart+srclen)-(128+4) {
    21  			{
    22  				_u := ux
    23  				ux = ctou32(ip + 8 + 0*8)
    24  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    25  				cu |= _u
    26  				stou32(op+0*6, _u)
    27  				_v := vx
    28  				vx = ctou32(ip + 8 + 0*8 + 4)
    29  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    30  				cu |= _v
    31  				stou32(op+0*6+3, _v)
    32  			}
    33  			{
    34  				_u := ux
    35  				ux = ctou32(ip + 8 + 1*8)
    36  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    37  				cu |= _u
    38  				stou32(op+1*6, _u)
    39  				_v := vx
    40  				vx = ctou32(ip + 8 + 1*8 + 4)
    41  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    42  				cu |= _v
    43  				stou32(op+1*6+3, _v)
    44  			}
    45  			{
    46  				_u := ux
    47  				ux = ctou32(ip + 8 + 2*8)
    48  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    49  				cu |= _u
    50  				stou32(op+2*6, _u)
    51  				_v := vx
    52  				vx = ctou32(ip + 8 + 2*8 + 4)
    53  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    54  				cu |= _v
    55  				stou32(op+2*6+3, _v)
    56  			}
    57  			{
    58  				_u := ux
    59  				ux = ctou32(ip + 8 + 3*8)
    60  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    61  				cu |= _u
    62  				stou32(op+3*6, _u)
    63  				_v := vx
    64  				vx = ctou32(ip + 8 + 3*8 + 4)
    65  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    66  				cu |= _v
    67  				stou32(op+3*6+3, _v)
    68  			}
    69  			{
    70  				_u := ux
    71  				ux = ctou32(ip + 8 + 4*8)
    72  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    73  				cu |= _u
    74  				stou32(op+4*6, _u)
    75  				_v := vx
    76  				vx = ctou32(ip + 8 + 4*8 + 4)
    77  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    78  				cu |= _v
    79  				stou32(op+4*6+3, _v)
    80  			}
    81  			{
    82  				_u := ux
    83  				ux = ctou32(ip + 8 + 5*8)
    84  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    85  				cu |= _u
    86  				stou32(op+5*6, _u)
    87  				_v := vx
    88  				vx = ctou32(ip + 8 + 5*8 + 4)
    89  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
    90  				cu |= _v
    91  				stou32(op+5*6+3, _v)
    92  			}
    93  			{
    94  				_u := ux
    95  				ux = ctou32(ip + 8 + 6*8)
    96  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
    97  				cu |= _u
    98  				stou32(op+6*6, _u)
    99  				_v := vx
   100  				vx = ctou32(ip + 8 + 6*8 + 4)
   101  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   102  				cu |= _v
   103  				stou32(op+6*6+3, _v)
   104  			}
   105  			{
   106  				_u := ux
   107  				ux = ctou32(ip + 8 + 7*8)
   108  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   109  				cu |= _u
   110  				stou32(op+7*6, _u)
   111  				_v := vx
   112  				vx = ctou32(ip + 8 + 7*8 + 4)
   113  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   114  				cu |= _v
   115  				stou32(op+7*6+3, _v)
   116  			}
   117  
   118  			{
   119  				_u := ux
   120  				ux = ctou32(ip + 8 + 8*8)
   121  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   122  				cu |= _u
   123  				stou32(op+8*6, _u)
   124  				_v := vx
   125  				vx = ctou32(ip + 8 + 8*8 + 4)
   126  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   127  				cu |= _v
   128  				stou32(op+8*6+3, _v)
   129  			}
   130  			{
   131  				_u := ux
   132  				ux = ctou32(ip + 8 + 9*8)
   133  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   134  				cu |= _u
   135  				stou32(op+9*6, _u)
   136  				_v := vx
   137  				vx = ctou32(ip + 8 + 9*8 + 4)
   138  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   139  				cu |= _v
   140  				stou32(op+9*6+3, _v)
   141  			}
   142  			{
   143  				_u := ux
   144  				ux = ctou32(ip + 8 + 10*8)
   145  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   146  				cu |= _u
   147  				stou32(op+10*6, _u)
   148  				_v := vx
   149  				vx = ctou32(ip + 8 + 10*8 + 4)
   150  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   151  				cu |= _v
   152  				stou32(op+10*6+3, _v)
   153  			}
   154  			{
   155  				_u := ux
   156  				ux = ctou32(ip + 8 + 11*8)
   157  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   158  				cu |= _u
   159  				stou32(op+11*6, _u)
   160  				_v := vx
   161  				vx = ctou32(ip + 8 + 11*8 + 4)
   162  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   163  				cu |= _v
   164  				stou32(op+11*6+3, _v)
   165  			}
   166  			{
   167  				_u := ux
   168  				ux = ctou32(ip + 8 + 12*8)
   169  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   170  				cu |= _u
   171  				stou32(op+12*6, _u)
   172  				_v := vx
   173  				vx = ctou32(ip + 8 + 12*8 + 4)
   174  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   175  				cu |= _v
   176  				stou32(op+12*6+3, _v)
   177  			}
   178  			{
   179  				_u := ux
   180  				ux = ctou32(ip + 8 + 13*8)
   181  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   182  				cu |= _u
   183  				stou32(op+13*6, _u)
   184  				_v := vx
   185  				vx = ctou32(ip + 8 + 13*8 + 4)
   186  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   187  				cu |= _v
   188  				stou32(op+13*6+3, _v)
   189  			}
   190  			{
   191  				_u := ux
   192  				ux = ctou32(ip + 8 + 14*8)
   193  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   194  				cu |= _u
   195  				stou32(op+14*6, _u)
   196  				_v := vx
   197  				vx = ctou32(ip + 8 + 14*8 + 4)
   198  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   199  				cu |= _v
   200  				stou32(op+14*6+3, _v)
   201  			}
   202  			{
   203  				_u := ux
   204  				ux = ctou32(ip + 8 + 15*8)
   205  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   206  				cu |= _u
   207  				stou32(op+15*6, _u)
   208  				_v := vx
   209  				vx = ctou32(ip + 8 + 15*8 + 4)
   210  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   211  				cu |= _v
   212  				stou32(op+15*6+3, _v)
   213  			}
   214  			ip += 128
   215  			op += (128 / 4) * 3
   216  		}
   217  		for ip < (ipstart+srclen)-(16+4) {
   218  			{
   219  				_u := ux
   220  				ux = ctou32(ip + 8 + 0*8)
   221  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   222  				cu |= _u
   223  				stou32(op+0*6, _u)
   224  				_v := vx
   225  				vx = ctou32(ip + 8 + 0*8 + 4)
   226  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   227  				cu |= _v
   228  				stou32(op+0*6+3, _v)
   229  			}
   230  			{
   231  				_u := ux
   232  				ux = ctou32(ip + 8 + 1*8)
   233  				_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   234  				cu |= _u
   235  				stou32(op+1*6, _u)
   236  				_v := vx
   237  				vx = ctou32(ip + 8 + 1*8 + 4)
   238  				_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   239  				cu |= _v
   240  				stou32(op+1*6+3, _v)
   241  			}
   242  			ip += 16
   243  			op += (16 / 4) * 3
   244  		}
   245  		if ip < (ipstart+srclen)-(8+4) {
   246  			_u := ux
   247  			_u = (e.lutXd0[byte(_u)] | e.lutXd1[byte(_u>>8)] | e.lutXd2[byte(_u>>16)] | e.lutXd3[_u>>24])
   248  			cu |= _u
   249  			stou32(op+0*6, _u)
   250  			_v := vx
   251  			_v = (e.lutXd0[byte(_v)] | e.lutXd1[byte(_v>>8)] | e.lutXd2[byte(_v>>16)] | e.lutXd3[_v>>24])
   252  			cu |= _v
   253  			stou32(op+0*6+3, _v)
   254  			ip += 8
   255  			op += (8 / 4) * 3
   256  		}
   257  	}
   258  	for ip < (ipstart+srclen)-4 {
   259  		u := ctou32(ip)
   260  		u = (e.lutXd0[byte(u)] | e.lutXd1[byte(u>>8)] | e.lutXd2[byte(u>>16)] | e.lutXd3[u>>24])
   261  		stou32(op, u)
   262  		cu |= u
   263  		ip += 4
   264  		op += 3
   265  	}
   266  	var u uint32
   267  	l := (ipstart + srclen) - ip
   268  	if e.pad && l == 4 {
   269  		if *(*byte)(unsafe.Pointer(ip + 3)) == '=' {
   270  			l = 3
   271  			if *(*byte)(unsafe.Pointer(ip + 2)) == '=' {
   272  				l = 2
   273  			}
   274  		}
   275  	}
   276  	up := (*[4]byte)(unsafe.Pointer(&u))
   277  	switch l {
   278  	case 4:
   279  		if !e.pad && op-opstart+3 > dstlen {
   280  			return 0
   281  		}
   282  		u = ctou32(ip)
   283  		u = (e.lutXd0[byte(u)] | e.lutXd1[byte(u>>8)] | e.lutXd2[byte(u>>16)] | e.lutXd3[u>>24])
   284  		putTail(op, up, 3)
   285  		op += 3
   286  		cu |= u
   287  		break
   288  	case 3:
   289  		if !e.pad && op-opstart+2 > dstlen {
   290  			return 0
   291  		}
   292  		u = e.lutXd0[*(*byte)(unsafe.Pointer(ip + 0))] | e.lutXd1[*(*byte)(unsafe.Pointer(ip + 1))] | e.lutXd2[*(*byte)(unsafe.Pointer(ip + 2))]
   293  		putTail(op, up, 2)
   294  		op += 2
   295  		cu |= u
   296  		break
   297  	case 2:
   298  		if !e.pad && op-opstart >= dstlen {
   299  			return 0
   300  		}
   301  		u = e.lutXd0[*(*byte)(unsafe.Pointer(ip + 0))] | e.lutXd1[*(*byte)(unsafe.Pointer(ip + 1))]
   302  		putTail(op, up, 1)
   303  		op++
   304  		cu |= u
   305  		break
   306  	case 1:
   307  		return 0
   308  	}
   309  	if cu == 0xffffffff {
   310  		return 0
   311  	}
   312  	return int(op - opstart)
   313  }