@@ -40,17 +40,16 @@ const maxUint16 = 1<<16 - 1
40
40
// Its memory representation is 24 bytes on 64-bit machines (the same
41
41
// size as a Go slice header) for both IPv4 and IPv6 address.
42
42
type IP struct {
43
- // addr are the hi (the first uint64) and lo bits (second
44
- // uint64) of an IPv6 address. If z==z4, hi and lo contain the
45
- // IPv4-mapped IPv6 address.
43
+ // addr are the hi and lo bits of an IPv6 address. If z==z4,
44
+ // hi and lo contain the IPv4-mapped IPv6 address.
46
45
//
47
46
// hi and lo are constructed by interpreting a 16-byte IPv6
48
47
// address as a big-endian 128-bit number. The most significant
49
48
// bits of that number go into hi, the rest into lo.
50
49
//
51
50
// For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as:
52
- // addr[0] (hi) = 0x0011223344556677
53
- // addr[1] (lo) = 0x8899aabbccddeeff
51
+ // addr.hi = 0x0011223344556677
52
+ // addr.lo = 0x8899aabbccddeeff
54
53
//
55
54
// We store IPs like this, rather than as [16]byte, because it
56
55
// turns most operations on IPs into arithmetic and bit-twiddling
@@ -68,9 +67,6 @@ type IP struct {
68
67
z * intern.Value
69
68
}
70
69
71
- func (ip IP ) hi () uint64 { return ip .addr [0 ] }
72
- func (ip IP ) lo () uint64 { return ip .addr [1 ] }
73
-
74
70
// z0, z4, and z6noz are sentinel IP.z values.
75
71
// See the IP type's field docs.
76
72
var (
@@ -379,17 +375,17 @@ func FromStdIPRaw(std net.IP) (ip IP, ok bool) {
379
375
// v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns
380
376
// unspecified garbage.
381
377
func (ip IP ) v4 (i uint8 ) uint8 {
382
- return uint8 (ip .lo () >> ((3 - i ) * 8 ))
378
+ return uint8 (ip .addr . lo >> ((3 - i ) * 8 ))
383
379
}
384
380
385
381
// v6 returns the i'th byte of ip. If ip is an IPv4 address, this
386
382
// accesses the IPv4-mapped IPv6 address form of the IP.
387
383
func (ip IP ) v6 (i uint8 ) uint8 {
388
- return uint8 (ip .addr [(i / 8 )% 2 ] >> ((7 - i % 8 ) * 8 ))
384
+ return uint8 (* ( ip .addr . halves () [(i / 8 )% 2 ]) >> ((7 - i % 8 ) * 8 ))
389
385
}
390
386
391
387
func (ip IP ) v6u16 (i uint8 ) uint16 {
392
- return uint16 (ip .addr [(i / 4 )% 2 ] >> ((3 - i % 4 ) * 16 ))
388
+ return uint16 (* ( ip .addr . halves () [(i / 4 )% 2 ]) >> ((3 - i % 4 ) * 16 ))
393
389
}
394
390
395
391
// IsZero reports whether ip is the zero value of the IP type.
@@ -436,12 +432,12 @@ func (ip IP) Compare(ip2 IP) int {
436
432
if f1 > f2 {
437
433
return 1
438
434
}
439
- if hi1 , hi2 := ip .hi () , ip2 .hi () ; hi1 < hi2 {
435
+ if hi1 , hi2 := ip .addr . hi , ip2 .addr . hi ; hi1 < hi2 {
440
436
return - 1
441
437
} else if hi1 > hi2 {
442
438
return 1
443
439
}
444
- if lo1 , lo2 := ip .lo () , ip2 .lo () ; lo1 < lo2 {
440
+ if lo1 , lo2 := ip .addr . lo , ip2 .addr . lo ; lo1 < lo2 {
445
441
return - 1
446
442
} else if lo1 > lo2 {
447
443
return 1
@@ -496,7 +492,7 @@ func (ip IP) Is4() bool {
496
492
497
493
// Is4in6 reports whether ip is an IPv4-mapped IPv6 address.
498
494
func (ip IP ) Is4in6 () bool {
499
- return ip .Is6 () && ip .hi () == 0 && ip .lo () >> 32 == 0xffff
495
+ return ip .Is6 () && ip .addr . hi == 0 && ip .addr . lo >> 32 == 0xffff
500
496
}
501
497
502
498
// Is6 reports whether ip is an IPv6 address, including IPv4-mapped
@@ -551,7 +547,7 @@ func (ip IP) IsLoopback() bool {
551
547
return ip .v4 (0 ) == 127
552
548
}
553
549
if ip .Is6 () {
554
- return ip .hi () == 0 && ip .lo () == 1
550
+ return ip .addr . hi == 0 && ip .addr . lo == 1
555
551
}
556
552
return false // zero value
557
553
}
@@ -563,7 +559,7 @@ func (ip IP) IsMulticast() bool {
563
559
return ip .v4 (0 )& 0xf0 == 0xe0
564
560
}
565
561
if ip .Is6 () {
566
- return ip .v6 (0 ) == 0xff
562
+ return ip .addr . hi >> ( 64 - 8 ) == 0xff // ip. v6(0) == 0xff
567
563
}
568
564
return false // zero value
569
565
}
@@ -598,8 +594,8 @@ func (ip IP) Prefix(bits uint8) (IPPrefix, error) {
598
594
// The ip zero value returns all zeroes.
599
595
func (ip IP ) As16 () [16 ]byte {
600
596
var ret [16 ]byte
601
- binary .BigEndian .PutUint64 (ret [:8 ], ip .hi () )
602
- binary .BigEndian .PutUint64 (ret [8 :], ip .lo () )
597
+ binary .BigEndian .PutUint64 (ret [:8 ], ip .addr . hi )
598
+ binary .BigEndian .PutUint64 (ret [8 :], ip .addr . lo )
603
599
return ret
604
600
}
605
601
@@ -609,7 +605,7 @@ func (ip IP) As16() [16]byte {
609
605
func (ip IP ) As4 () [4 ]byte {
610
606
if ip .z == z4 || ip .Is4in6 () {
611
607
var ret [4 ]byte
612
- binary .BigEndian .PutUint32 (ret [:], uint32 (ip .lo () ))
608
+ binary .BigEndian .PutUint32 (ret [:], uint32 (ip .addr . lo ))
613
609
return ret
614
610
}
615
611
if ip .z == z0 {
@@ -1074,12 +1070,12 @@ func (p IPPrefix) Contains(ip IP) bool {
1074
1070
}
1075
1071
if ip .Is4 () {
1076
1072
m := mask4 (p .Bits )
1077
- return uint32 (ip .lo ()) & m == uint32 (p .IP .lo () )& m
1073
+ return uint32 (ip .addr . lo ) & m == uint32 (p .IP .addr . lo )& m
1078
1074
} else {
1079
1075
m := mask6 (p .Bits )
1080
1076
// TODO: benchmark whether the short circuit below is faster or slower
1081
1077
// than the higher level alternative: 'ip.addr.and(m) == p.IP.addr.and(m)'.
1082
- return ip .hi () & m [ 0 ] == p .IP .hi () & m [ 0 ] && ip .lo () & m [ 1 ] == p .IP .lo () & m [ 1 ]
1078
+ return ip .addr . hi & m . hi == p .IP .addr . hi & m . hi && ip .addr . lo & m . lo == p .IP .addr . lo & m . lo
1083
1079
}
1084
1080
}
1085
1081
@@ -1273,22 +1269,24 @@ func (r IPRange) Overlaps(o IPRange) bool {
1273
1269
}
1274
1270
1275
1271
// uint128 represents a uint128 using two uint64s.
1276
- // Index 0 contains the high bits, index 1 contains the low.
1277
- type uint128 [2 ]uint64
1272
+ type uint128 struct {
1273
+ hi uint64
1274
+ lo uint64
1275
+ }
1278
1276
1279
1277
// and returns the bitwise AND of u and m (u&m).
1280
1278
func (u uint128 ) and (m uint128 ) uint128 {
1281
- return uint128 {u [ 0 ] & m [ 0 ] , u [ 1 ] & m [ 1 ] }
1279
+ return uint128 {u . hi & m . hi , u . lo & m . lo }
1282
1280
}
1283
1281
1284
1282
// xor returns the bitwise XOR of u and m (u^m).
1285
1283
func (u uint128 ) xor (m uint128 ) uint128 {
1286
- return uint128 {u [ 0 ] ^ m [ 0 ] , u [ 1 ] ^ m [ 1 ] }
1284
+ return uint128 {u . hi ^ m . hi , u . lo ^ m . lo }
1287
1285
}
1288
1286
1289
1287
// or returns the bitwise OR of u and m (u|m).
1290
1288
func (u uint128 ) or (m uint128 ) uint128 {
1291
- return uint128 {u [ 0 ] | m [ 0 ] , u [ 1 ] | m [ 1 ] }
1289
+ return uint128 {u . hi | m . hi , u . lo | m . lo }
1292
1290
}
1293
1291
1294
1292
func u64CommonPrefixLen (a , b uint64 ) uint8 {
@@ -1303,22 +1301,26 @@ func u64CommonPrefixLen(a, b uint64) uint8 {
1303
1301
}
1304
1302
1305
1303
func (a uint128 ) commonPrefixLen (b uint128 ) (n uint8 ) {
1306
- if n = u64CommonPrefixLen (a [ 0 ] , b [ 0 ] ); n == 64 {
1307
- n += u64CommonPrefixLen (a [ 1 ] , b [ 1 ] )
1304
+ if n = u64CommonPrefixLen (a . hi , b . hi ); n == 64 {
1305
+ n += u64CommonPrefixLen (a . lo , b . lo )
1308
1306
}
1309
1307
return
1310
1308
}
1311
1309
1310
+ func (u * uint128 ) halves () [2 ]* uint64 {
1311
+ return [2 ]* uint64 {& u .hi , & u .lo }
1312
+ }
1313
+
1312
1314
func (u * uint128 ) set (bit uint8 ) {
1313
1315
hli := (bit / 64 ) % 2 // hi/lo index: 0 or 1, respectively
1314
1316
s := 63 - (bit % 64 )
1315
- u [hli ] |= 1 << s
1317
+ * ( u . halves () [hli ]) |= 1 << s
1316
1318
}
1317
1319
1318
1320
func (u * uint128 ) clear (bit uint8 ) {
1319
1321
hli := (bit / 64 ) % 2 // hi/lo index: 0 or 1, respectively
1320
1322
s := 63 - (bit % 64 )
1321
- u [hli ] &^= 1 << s
1323
+ * ( u . halves () [hli ]) &^= 1 << s
1322
1324
}
1323
1325
1324
1326
// lastWithBitZero returns a copy of u with the given bit
0 commit comments