1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package netip defines an IP address type that's a small value type.
6// Building on that [Addr] type, the package also defines [AddrPort] (an
7// IP address and a port) and [Prefix] (an IP address and a bit length
8// prefix).
9//
10// Compared to the [net.IP] type, [Addr] type takes less memory, is immutable,
11// and is comparable (supports == and being a map key).
12package netip
13
14import (
15	"cmp"
16	"errors"
17	"internal/bytealg"
18	"internal/byteorder"
19	"internal/itoa"
20	"math"
21	"strconv"
22	"unique"
23)
24
25// Sizes: (64-bit)
26//   net.IP:     24 byte slice header + {4, 16} = 28 to 40 bytes
27//   net.IPAddr: 40 byte slice header + {4, 16} = 44 to 56 bytes + zone length
28//   netip.Addr: 24 bytes (zone is per-name singleton, shared across all users)
29
30// Addr represents an IPv4 or IPv6 address (with or without a scoped
31// addressing zone), similar to [net.IP] or [net.IPAddr].
32//
33// Unlike [net.IP] or [net.IPAddr], Addr is a comparable value
34// type (it supports == and can be a map key) and is immutable.
35//
36// The zero Addr is not a valid IP address.
37// Addr{} is distinct from both 0.0.0.0 and ::.
38type Addr struct {
39	// addr is the hi and lo bits of an IPv6 address. If z==z4,
40	// hi and lo contain the IPv4-mapped IPv6 address.
41	//
42	// hi and lo are constructed by interpreting a 16-byte IPv6
43	// address as a big-endian 128-bit number. The most significant
44	// bits of that number go into hi, the rest into lo.
45	//
46	// For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as:
47	//  addr.hi = 0x0011223344556677
48	//  addr.lo = 0x8899aabbccddeeff
49	//
50	// We store IPs like this, rather than as [16]byte, because it
51	// turns most operations on IPs into arithmetic and bit-twiddling
52	// operations on 64-bit registers, which is much faster than
53	// bytewise processing.
54	addr uint128
55
56	// Details about the address, wrapped up together and canonicalized.
57	z unique.Handle[addrDetail]
58}
59
60// addrDetail represents the details of an Addr, like address family and IPv6 zone.
61type addrDetail struct {
62	isV6   bool   // IPv4 is false, IPv6 is true.
63	zoneV6 string // != "" only if IsV6 is true.
64}
65
66// z0, z4, and z6noz are sentinel Addr.z values.
67// See the Addr type's field docs.
68var (
69	z0    unique.Handle[addrDetail]
70	z4    = unique.Make(addrDetail{})
71	z6noz = unique.Make(addrDetail{isV6: true})
72)
73
74// IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast
75// address ff02::1.
76func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) }
77
78// IPv6LinkLocalAllRouters returns the IPv6 link-local all routers multicast
79// address ff02::2.
80func IPv6LinkLocalAllRouters() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x02}) }
81
82// IPv6Loopback returns the IPv6 loopback address ::1.
83func IPv6Loopback() Addr { return AddrFrom16([16]byte{15: 0x01}) }
84
85// IPv6Unspecified returns the IPv6 unspecified address "::".
86func IPv6Unspecified() Addr { return Addr{z: z6noz} }
87
88// IPv4Unspecified returns the IPv4 unspecified address "0.0.0.0".
89func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) }
90
91// AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.
92func AddrFrom4(addr [4]byte) Addr {
93	return Addr{
94		addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])},
95		z:    z4,
96	}
97}
98
99// AddrFrom16 returns the IPv6 address given by the bytes in addr.
100// An IPv4-mapped IPv6 address is left as an IPv6 address.
101// (Use Unmap to convert them if needed.)
102func AddrFrom16(addr [16]byte) Addr {
103	return Addr{
104		addr: uint128{
105			byteorder.BeUint64(addr[:8]),
106			byteorder.BeUint64(addr[8:]),
107		},
108		z: z6noz,
109	}
110}
111
112// ParseAddr parses s as an IP address, returning the result. The string
113// s can be in dotted decimal ("192.0.2.1"), IPv6 ("2001:db8::68"),
114// or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18").
115func ParseAddr(s string) (Addr, error) {
116	for i := 0; i < len(s); i++ {
117		switch s[i] {
118		case '.':
119			return parseIPv4(s)
120		case ':':
121			return parseIPv6(s)
122		case '%':
123			// Assume that this was trying to be an IPv6 address with
124			// a zone specifier, but the address is missing.
125			return Addr{}, parseAddrError{in: s, msg: "missing IPv6 address"}
126		}
127	}
128	return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"}
129}
130
131// MustParseAddr calls [ParseAddr](s) and panics on error.
132// It is intended for use in tests with hard-coded strings.
133func MustParseAddr(s string) Addr {
134	ip, err := ParseAddr(s)
135	if err != nil {
136		panic(err)
137	}
138	return ip
139}
140
141type parseAddrError struct {
142	in  string // the string given to ParseAddr
143	msg string // an explanation of the parse failure
144	at  string // optionally, the unparsed portion of in at which the error occurred.
145}
146
147func (err parseAddrError) Error() string {
148	q := strconv.Quote
149	if err.at != "" {
150		return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")"
151	}
152	return "ParseAddr(" + q(err.in) + "): " + err.msg
153}
154
155func parseIPv4Fields(in string, off, end int, fields []uint8) error {
156	var val, pos int
157	var digLen int // number of digits in current octet
158	s := in[off:end]
159	for i := 0; i < len(s); i++ {
160		if s[i] >= '0' && s[i] <= '9' {
161			if digLen == 1 && val == 0 {
162				return parseAddrError{in: in, msg: "IPv4 field has octet with leading zero"}
163			}
164			val = val*10 + int(s[i]) - '0'
165			digLen++
166			if val > 255 {
167				return parseAddrError{in: in, msg: "IPv4 field has value >255"}
168			}
169		} else if s[i] == '.' {
170			// .1.2.3
171			// 1.2.3.
172			// 1..2.3
173			if i == 0 || i == len(s)-1 || s[i-1] == '.' {
174				return parseAddrError{in: in, msg: "IPv4 field must have at least one digit", at: s[i:]}
175			}
176			// 1.2.3.4.5
177			if pos == 3 {
178				return parseAddrError{in: in, msg: "IPv4 address too long"}
179			}
180			fields[pos] = uint8(val)
181			pos++
182			val = 0
183			digLen = 0
184		} else {
185			return parseAddrError{in: in, msg: "unexpected character", at: s[i:]}
186		}
187	}
188	if pos < 3 {
189		return parseAddrError{in: in, msg: "IPv4 address too short"}
190	}
191	fields[3] = uint8(val)
192	return nil
193}
194
195// parseIPv4 parses s as an IPv4 address (in form "192.168.0.1").
196func parseIPv4(s string) (ip Addr, err error) {
197	var fields [4]uint8
198	err = parseIPv4Fields(s, 0, len(s), fields[:])
199	if err != nil {
200		return Addr{}, err
201	}
202	return AddrFrom4(fields), nil
203}
204
205// parseIPv6 parses s as an IPv6 address (in form "2001:db8::68").
206func parseIPv6(in string) (Addr, error) {
207	s := in
208
209	// Split off the zone right from the start. Yes it's a second scan
210	// of the string, but trying to handle it inline makes a bunch of
211	// other inner loop conditionals more expensive, and it ends up
212	// being slower.
213	zone := ""
214	i := bytealg.IndexByteString(s, '%')
215	if i != -1 {
216		s, zone = s[:i], s[i+1:]
217		if zone == "" {
218			// Not allowed to have an empty zone if explicitly specified.
219			return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"}
220		}
221	}
222
223	var ip [16]byte
224	ellipsis := -1 // position of ellipsis in ip
225
226	// Might have leading ellipsis
227	if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
228		ellipsis = 0
229		s = s[2:]
230		// Might be only ellipsis
231		if len(s) == 0 {
232			return IPv6Unspecified().WithZone(zone), nil
233		}
234	}
235
236	// Loop, parsing hex numbers followed by colon.
237	i = 0
238	for i < 16 {
239		// Hex number. Similar to parseIPv4, inlining the hex number
240		// parsing yields a significant performance increase.
241		off := 0
242		acc := uint32(0)
243		for ; off < len(s); off++ {
244			c := s[off]
245			if c >= '0' && c <= '9' {
246				acc = (acc << 4) + uint32(c-'0')
247			} else if c >= 'a' && c <= 'f' {
248				acc = (acc << 4) + uint32(c-'a'+10)
249			} else if c >= 'A' && c <= 'F' {
250				acc = (acc << 4) + uint32(c-'A'+10)
251			} else {
252				break
253			}
254			if off > 3 {
255				//more than 4 digits in group, fail.
256				return Addr{}, parseAddrError{in: in, msg: "each group must have 4 or less digits", at: s}
257			}
258			if acc > math.MaxUint16 {
259				// Overflow, fail.
260				return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s}
261			}
262		}
263		if off == 0 {
264			// No digits found, fail.
265			return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s}
266		}
267
268		// If followed by dot, might be in trailing IPv4.
269		if off < len(s) && s[off] == '.' {
270			if ellipsis < 0 && i != 12 {
271				// Not the right place.
272				return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s}
273			}
274			if i+4 > 16 {
275				// Not enough room.
276				return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s}
277			}
278
279			end := len(in)
280			if len(zone) > 0 {
281				end -= len(zone) + 1
282			}
283			err := parseIPv4Fields(in, end-len(s), end, ip[i:i+4])
284			if err != nil {
285				return Addr{}, err
286			}
287			s = ""
288			i += 4
289			break
290		}
291
292		// Save this 16-bit chunk.
293		ip[i] = byte(acc >> 8)
294		ip[i+1] = byte(acc)
295		i += 2
296
297		// Stop at end of string.
298		s = s[off:]
299		if len(s) == 0 {
300			break
301		}
302
303		// Otherwise must be followed by colon and more.
304		if s[0] != ':' {
305			return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s}
306		} else if len(s) == 1 {
307			return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s}
308		}
309		s = s[1:]
310
311		// Look for ellipsis.
312		if s[0] == ':' {
313			if ellipsis >= 0 { // already have one
314				return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s}
315			}
316			ellipsis = i
317			s = s[1:]
318			if len(s) == 0 { // can be at end
319				break
320			}
321		}
322	}
323
324	// Must have used entire string.
325	if len(s) != 0 {
326		return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s}
327	}
328
329	// If didn't parse enough, expand ellipsis.
330	if i < 16 {
331		if ellipsis < 0 {
332			return Addr{}, parseAddrError{in: in, msg: "address string too short"}
333		}
334		n := 16 - i
335		for j := i - 1; j >= ellipsis; j-- {
336			ip[j+n] = ip[j]
337		}
338		clear(ip[ellipsis : ellipsis+n])
339	} else if ellipsis >= 0 {
340		// Ellipsis must represent at least one 0 group.
341		return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"}
342	}
343	return AddrFrom16(ip).WithZone(zone), nil
344}
345
346// AddrFromSlice parses the 4- or 16-byte byte slice as an IPv4 or IPv6 address.
347// Note that a [net.IP] can be passed directly as the []byte argument.
348// If slice's length is not 4 or 16, AddrFromSlice returns [Addr]{}, false.
349func AddrFromSlice(slice []byte) (ip Addr, ok bool) {
350	switch len(slice) {
351	case 4:
352		return AddrFrom4([4]byte(slice)), true
353	case 16:
354		return AddrFrom16([16]byte(slice)), true
355	}
356	return Addr{}, false
357}
358
359// v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns
360// unspecified garbage.
361func (ip Addr) v4(i uint8) uint8 {
362	return uint8(ip.addr.lo >> ((3 - i) * 8))
363}
364
365// v6 returns the i'th byte of ip. If ip is an IPv4 address, this
366// accesses the IPv4-mapped IPv6 address form of the IP.
367func (ip Addr) v6(i uint8) uint8 {
368	return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8))
369}
370
371// v6u16 returns the i'th 16-bit word of ip. If ip is an IPv4 address,
372// this accesses the IPv4-mapped IPv6 address form of the IP.
373func (ip Addr) v6u16(i uint8) uint16 {
374	return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16))
375}
376
377// isZero reports whether ip is the zero value of the IP type.
378// The zero value is not a valid IP address of any type.
379//
380// Note that "0.0.0.0" and "::" are not the zero value. Use IsUnspecified to
381// check for these values instead.
382func (ip Addr) isZero() bool {
383	// Faster than comparing ip == Addr{}, but effectively equivalent,
384	// as there's no way to make an IP with a nil z from this package.
385	return ip.z == z0
386}
387
388// IsValid reports whether the [Addr] is an initialized address (not the zero Addr).
389//
390// Note that "0.0.0.0" and "::" are both valid values.
391func (ip Addr) IsValid() bool { return ip.z != z0 }
392
393// BitLen returns the number of bits in the IP address:
394// 128 for IPv6, 32 for IPv4, and 0 for the zero [Addr].
395//
396// Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses
397// and therefore have bit length 128.
398func (ip Addr) BitLen() int {
399	switch ip.z {
400	case z0:
401		return 0
402	case z4:
403		return 32
404	}
405	return 128
406}
407
408// Zone returns ip's IPv6 scoped addressing zone, if any.
409func (ip Addr) Zone() string {
410	if ip.z == z0 {
411		return ""
412	}
413	return ip.z.Value().zoneV6
414}
415
416// Compare returns an integer comparing two IPs.
417// The result will be 0 if ip == ip2, -1 if ip < ip2, and +1 if ip > ip2.
418// The definition of "less than" is the same as the [Addr.Less] method.
419func (ip Addr) Compare(ip2 Addr) int {
420	f1, f2 := ip.BitLen(), ip2.BitLen()
421	if f1 < f2 {
422		return -1
423	}
424	if f1 > f2 {
425		return 1
426	}
427	hi1, hi2 := ip.addr.hi, ip2.addr.hi
428	if hi1 < hi2 {
429		return -1
430	}
431	if hi1 > hi2 {
432		return 1
433	}
434	lo1, lo2 := ip.addr.lo, ip2.addr.lo
435	if lo1 < lo2 {
436		return -1
437	}
438	if lo1 > lo2 {
439		return 1
440	}
441	if ip.Is6() {
442		za, zb := ip.Zone(), ip2.Zone()
443		if za < zb {
444			return -1
445		}
446		if za > zb {
447			return 1
448		}
449	}
450	return 0
451}
452
453// Less reports whether ip sorts before ip2.
454// IP addresses sort first by length, then their address.
455// IPv6 addresses with zones sort just after the same address without a zone.
456func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 }
457
458// Is4 reports whether ip is an IPv4 address.
459//
460// It returns false for IPv4-mapped IPv6 addresses. See [Addr.Unmap].
461func (ip Addr) Is4() bool {
462	return ip.z == z4
463}
464
465// Is4In6 reports whether ip is an IPv4-mapped IPv6 address.
466func (ip Addr) Is4In6() bool {
467	return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff
468}
469
470// Is6 reports whether ip is an IPv6 address, including IPv4-mapped
471// IPv6 addresses.
472func (ip Addr) Is6() bool {
473	return ip.z != z0 && ip.z != z4
474}
475
476// Unmap returns ip with any IPv4-mapped IPv6 address prefix removed.
477//
478// That is, if ip is an IPv6 address wrapping an IPv4 address, it
479// returns the wrapped IPv4 address. Otherwise it returns ip unmodified.
480func (ip Addr) Unmap() Addr {
481	if ip.Is4In6() {
482		ip.z = z4
483	}
484	return ip
485}
486
487// WithZone returns an IP that's the same as ip but with the provided
488// zone. If zone is empty, the zone is removed. If ip is an IPv4
489// address, WithZone is a no-op and returns ip unchanged.
490func (ip Addr) WithZone(zone string) Addr {
491	if !ip.Is6() {
492		return ip
493	}
494	if zone == "" {
495		ip.z = z6noz
496		return ip
497	}
498	ip.z = unique.Make(addrDetail{isV6: true, zoneV6: zone})
499	return ip
500}
501
502// withoutZone unconditionally strips the zone from ip.
503// It's similar to WithZone, but small enough to be inlinable.
504func (ip Addr) withoutZone() Addr {
505	if !ip.Is6() {
506		return ip
507	}
508	ip.z = z6noz
509	return ip
510}
511
512// hasZone reports whether ip has an IPv6 zone.
513func (ip Addr) hasZone() bool {
514	return ip.z != z0 && ip.z != z4 && ip.z != z6noz
515}
516
517// IsLinkLocalUnicast reports whether ip is a link-local unicast address.
518func (ip Addr) IsLinkLocalUnicast() bool {
519	if ip.Is4In6() {
520		ip = ip.Unmap()
521	}
522
523	// Dynamic Configuration of IPv4 Link-Local Addresses
524	// https://datatracker.ietf.org/doc/html/rfc3927#section-2.1
525	if ip.Is4() {
526		return ip.v4(0) == 169 && ip.v4(1) == 254
527	}
528	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
529	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
530	if ip.Is6() {
531		return ip.v6u16(0)&0xffc0 == 0xfe80
532	}
533	return false // zero value
534}
535
536// IsLoopback reports whether ip is a loopback address.
537func (ip Addr) IsLoopback() bool {
538	if ip.Is4In6() {
539		ip = ip.Unmap()
540	}
541
542	// Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing)
543	// https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3
544	if ip.Is4() {
545		return ip.v4(0) == 127
546	}
547	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
548	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
549	if ip.Is6() {
550		return ip.addr.hi == 0 && ip.addr.lo == 1
551	}
552	return false // zero value
553}
554
555// IsMulticast reports whether ip is a multicast address.
556func (ip Addr) IsMulticast() bool {
557	if ip.Is4In6() {
558		ip = ip.Unmap()
559	}
560
561	// Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES)
562	// https://datatracker.ietf.org/doc/html/rfc1112#section-4
563	if ip.Is4() {
564		return ip.v4(0)&0xf0 == 0xe0
565	}
566	// IP Version 6 Addressing Architecture (2.4 Address Type Identification)
567	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.4
568	if ip.Is6() {
569		return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff
570	}
571	return false // zero value
572}
573
574// IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local
575// multicast address.
576func (ip Addr) IsInterfaceLocalMulticast() bool {
577	// IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
578	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
579	if ip.Is6() && !ip.Is4In6() {
580		return ip.v6u16(0)&0xff0f == 0xff01
581	}
582	return false // zero value
583}
584
585// IsLinkLocalMulticast reports whether ip is a link-local multicast address.
586func (ip Addr) IsLinkLocalMulticast() bool {
587	if ip.Is4In6() {
588		ip = ip.Unmap()
589	}
590
591	// IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24))
592	// https://datatracker.ietf.org/doc/html/rfc5771#section-4
593	if ip.Is4() {
594		return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0
595	}
596	// IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses)
597	// https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
598	if ip.Is6() {
599		return ip.v6u16(0)&0xff0f == 0xff02
600	}
601	return false // zero value
602}
603
604// IsGlobalUnicast reports whether ip is a global unicast address.
605//
606// It returns true for IPv6 addresses which fall outside of the current
607// IANA-allocated 2000::/3 global unicast space, with the exception of the
608// link-local address space. It also returns true even if ip is in the IPv4
609// private address space or IPv6 unique local address space.
610// It returns false for the zero [Addr].
611//
612// For reference, see RFC 1122, RFC 4291, and RFC 4632.
613func (ip Addr) IsGlobalUnicast() bool {
614	if ip.z == z0 {
615		// Invalid or zero-value.
616		return false
617	}
618
619	if ip.Is4In6() {
620		ip = ip.Unmap()
621	}
622
623	// Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses
624	// and ULA IPv6 addresses are still considered "global unicast".
625	if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) {
626		return false
627	}
628
629	return ip != IPv6Unspecified() &&
630		!ip.IsLoopback() &&
631		!ip.IsMulticast() &&
632		!ip.IsLinkLocalUnicast()
633}
634
635// IsPrivate reports whether ip is a private address, according to RFC 1918
636// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
637// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
638// same as [net.IP.IsPrivate].
639func (ip Addr) IsPrivate() bool {
640	if ip.Is4In6() {
641		ip = ip.Unmap()
642	}
643
644	// Match the stdlib's IsPrivate logic.
645	if ip.Is4() {
646		// RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as
647		// private IPv4 address subnets.
648		return ip.v4(0) == 10 ||
649			(ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) ||
650			(ip.v4(0) == 192 && ip.v4(1) == 168)
651	}
652
653	if ip.Is6() {
654		// RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address
655		// subnet.
656		return ip.v6(0)&0xfe == 0xfc
657	}
658
659	return false // zero value
660}
661
662// IsUnspecified reports whether ip is an unspecified address, either the IPv4
663// address "0.0.0.0" or the IPv6 address "::".
664//
665// Note that the zero [Addr] is not an unspecified address.
666func (ip Addr) IsUnspecified() bool {
667	return ip == IPv4Unspecified() || ip == IPv6Unspecified()
668}
669
670// Prefix keeps only the top b bits of IP, producing a Prefix
671// of the specified length.
672// If ip is a zero [Addr], Prefix always returns a zero Prefix and a nil error.
673// Otherwise, if bits is less than zero or greater than ip.BitLen(),
674// Prefix returns an error.
675func (ip Addr) Prefix(b int) (Prefix, error) {
676	if b < 0 {
677		return Prefix{}, errors.New("negative Prefix bits")
678	}
679	effectiveBits := b
680	switch ip.z {
681	case z0:
682		return Prefix{}, nil
683	case z4:
684		if b > 32 {
685			return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4")
686		}
687		effectiveBits += 96
688	default:
689		if b > 128 {
690			return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6")
691		}
692	}
693	ip.addr = ip.addr.and(mask6(effectiveBits))
694	return PrefixFrom(ip, b), nil
695}
696
697// As16 returns the IP address in its 16-byte representation.
698// IPv4 addresses are returned as IPv4-mapped IPv6 addresses.
699// IPv6 addresses with zones are returned without their zone (use the
700// [Addr.Zone] method to get it).
701// The ip zero value returns all zeroes.
702func (ip Addr) As16() (a16 [16]byte) {
703	byteorder.BePutUint64(a16[:8], ip.addr.hi)
704	byteorder.BePutUint64(a16[8:], ip.addr.lo)
705	return a16
706}
707
708// As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation.
709// If ip is the zero [Addr] or an IPv6 address, As4 panics.
710// Note that 0.0.0.0 is not the zero Addr.
711func (ip Addr) As4() (a4 [4]byte) {
712	if ip.z == z4 || ip.Is4In6() {
713		byteorder.BePutUint32(a4[:], uint32(ip.addr.lo))
714		return a4
715	}
716	if ip.z == z0 {
717		panic("As4 called on IP zero value")
718	}
719	panic("As4 called on IPv6 address")
720}
721
722// AsSlice returns an IPv4 or IPv6 address in its respective 4-byte or 16-byte representation.
723func (ip Addr) AsSlice() []byte {
724	switch ip.z {
725	case z0:
726		return nil
727	case z4:
728		var ret [4]byte
729		byteorder.BePutUint32(ret[:], uint32(ip.addr.lo))
730		return ret[:]
731	default:
732		var ret [16]byte
733		byteorder.BePutUint64(ret[:8], ip.addr.hi)
734		byteorder.BePutUint64(ret[8:], ip.addr.lo)
735		return ret[:]
736	}
737}
738
739// Next returns the address following ip.
740// If there is none, it returns the zero [Addr].
741func (ip Addr) Next() Addr {
742	ip.addr = ip.addr.addOne()
743	if ip.Is4() {
744		if uint32(ip.addr.lo) == 0 {
745			// Overflowed.
746			return Addr{}
747		}
748	} else {
749		if ip.addr.isZero() {
750			// Overflowed
751			return Addr{}
752		}
753	}
754	return ip
755}
756
757// Prev returns the IP before ip.
758// If there is none, it returns the IP zero value.
759func (ip Addr) Prev() Addr {
760	if ip.Is4() {
761		if uint32(ip.addr.lo) == 0 {
762			return Addr{}
763		}
764	} else if ip.addr.isZero() {
765		return Addr{}
766	}
767	ip.addr = ip.addr.subOne()
768	return ip
769}
770
771// String returns the string form of the IP address ip.
772// It returns one of 5 forms:
773//
774//   - "invalid IP", if ip is the zero [Addr]
775//   - IPv4 dotted decimal ("192.0.2.1")
776//   - IPv6 ("2001:db8::1")
777//   - "::ffff:1.2.3.4" (if [Addr.Is4In6])
778//   - IPv6 with zone ("fe80:db8::1%eth0")
779//
780// Note that unlike package net's IP.String method,
781// IPv4-mapped IPv6 addresses format with a "::ffff:"
782// prefix before the dotted quad.
783func (ip Addr) String() string {
784	switch ip.z {
785	case z0:
786		return "invalid IP"
787	case z4:
788		return ip.string4()
789	default:
790		if ip.Is4In6() {
791			return ip.string4In6()
792		}
793		return ip.string6()
794	}
795}
796
797// AppendTo appends a text encoding of ip,
798// as generated by [Addr.MarshalText],
799// to b and returns the extended buffer.
800func (ip Addr) AppendTo(b []byte) []byte {
801	switch ip.z {
802	case z0:
803		return b
804	case z4:
805		return ip.appendTo4(b)
806	default:
807		if ip.Is4In6() {
808			return ip.appendTo4In6(b)
809		}
810		return ip.appendTo6(b)
811	}
812}
813
814// digits is a string of the hex digits from 0 to f. It's used in
815// appendDecimal and appendHex to format IP addresses.
816const digits = "0123456789abcdef"
817
818// appendDecimal appends the decimal string representation of x to b.
819func appendDecimal(b []byte, x uint8) []byte {
820	// Using this function rather than strconv.AppendUint makes IPv4
821	// string building 2x faster.
822
823	if x >= 100 {
824		b = append(b, digits[x/100])
825	}
826	if x >= 10 {
827		b = append(b, digits[x/10%10])
828	}
829	return append(b, digits[x%10])
830}
831
832// appendHex appends the hex string representation of x to b.
833func appendHex(b []byte, x uint16) []byte {
834	// Using this function rather than strconv.AppendUint makes IPv6
835	// string building 2x faster.
836
837	if x >= 0x1000 {
838		b = append(b, digits[x>>12])
839	}
840	if x >= 0x100 {
841		b = append(b, digits[x>>8&0xf])
842	}
843	if x >= 0x10 {
844		b = append(b, digits[x>>4&0xf])
845	}
846	return append(b, digits[x&0xf])
847}
848
849// appendHexPad appends the fully padded hex string representation of x to b.
850func appendHexPad(b []byte, x uint16) []byte {
851	return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf])
852}
853
854func (ip Addr) string4() string {
855	const max = len("255.255.255.255")
856	ret := make([]byte, 0, max)
857	ret = ip.appendTo4(ret)
858	return string(ret)
859}
860
861func (ip Addr) appendTo4(ret []byte) []byte {
862	ret = appendDecimal(ret, ip.v4(0))
863	ret = append(ret, '.')
864	ret = appendDecimal(ret, ip.v4(1))
865	ret = append(ret, '.')
866	ret = appendDecimal(ret, ip.v4(2))
867	ret = append(ret, '.')
868	ret = appendDecimal(ret, ip.v4(3))
869	return ret
870}
871
872func (ip Addr) string4In6() string {
873	const max = len("::ffff:255.255.255.255%enp5s0")
874	ret := make([]byte, 0, max)
875	ret = ip.appendTo4In6(ret)
876	return string(ret)
877}
878
879func (ip Addr) appendTo4In6(ret []byte) []byte {
880	ret = append(ret, "::ffff:"...)
881	ret = ip.Unmap().appendTo4(ret)
882	if ip.z != z6noz {
883		ret = append(ret, '%')
884		ret = append(ret, ip.Zone()...)
885	}
886	return ret
887}
888
889// string6 formats ip in IPv6 textual representation. It follows the
890// guidelines in section 4 of RFC 5952
891// (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary
892// zeros, use :: to elide the longest run of zeros, and don't use ::
893// to compact a single zero field.
894func (ip Addr) string6() string {
895	// Use a zone with a "plausibly long" name, so that most zone-ful
896	// IP addresses won't require additional allocation.
897	//
898	// The compiler does a cool optimization here, where ret ends up
899	// stack-allocated and so the only allocation this function does
900	// is to construct the returned string. As such, it's okay to be a
901	// bit greedy here, size-wise.
902	const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
903	ret := make([]byte, 0, max)
904	ret = ip.appendTo6(ret)
905	return string(ret)
906}
907
908func (ip Addr) appendTo6(ret []byte) []byte {
909	zeroStart, zeroEnd := uint8(255), uint8(255)
910	for i := uint8(0); i < 8; i++ {
911		j := i
912		for j < 8 && ip.v6u16(j) == 0 {
913			j++
914		}
915		if l := j - i; l >= 2 && l > zeroEnd-zeroStart {
916			zeroStart, zeroEnd = i, j
917		}
918	}
919
920	for i := uint8(0); i < 8; i++ {
921		if i == zeroStart {
922			ret = append(ret, ':', ':')
923			i = zeroEnd
924			if i >= 8 {
925				break
926			}
927		} else if i > 0 {
928			ret = append(ret, ':')
929		}
930
931		ret = appendHex(ret, ip.v6u16(i))
932	}
933
934	if ip.z != z6noz {
935		ret = append(ret, '%')
936		ret = append(ret, ip.Zone()...)
937	}
938	return ret
939}
940
941// StringExpanded is like [Addr.String] but IPv6 addresses are expanded with leading
942// zeroes and no "::" compression. For example, "2001:db8::1" becomes
943// "2001:0db8:0000:0000:0000:0000:0000:0001".
944func (ip Addr) StringExpanded() string {
945	switch ip.z {
946	case z0, z4:
947		return ip.String()
948	}
949
950	const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
951	ret := make([]byte, 0, size)
952	for i := uint8(0); i < 8; i++ {
953		if i > 0 {
954			ret = append(ret, ':')
955		}
956
957		ret = appendHexPad(ret, ip.v6u16(i))
958	}
959
960	if ip.z != z6noz {
961		// The addition of a zone will cause a second allocation, but when there
962		// is no zone the ret slice will be stack allocated.
963		ret = append(ret, '%')
964		ret = append(ret, ip.Zone()...)
965	}
966	return string(ret)
967}
968
969// MarshalText implements the [encoding.TextMarshaler] interface,
970// The encoding is the same as returned by [Addr.String], with one exception:
971// If ip is the zero [Addr], the encoding is the empty string.
972func (ip Addr) MarshalText() ([]byte, error) {
973	switch ip.z {
974	case z0:
975		return []byte(""), nil
976	case z4:
977		max := len("255.255.255.255")
978		b := make([]byte, 0, max)
979		return ip.appendTo4(b), nil
980	default:
981		if ip.Is4In6() {
982			max := len("::ffff:255.255.255.255%enp5s0")
983			b := make([]byte, 0, max)
984			return ip.appendTo4In6(b), nil
985		}
986		max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0")
987		b := make([]byte, 0, max)
988		return ip.appendTo6(b), nil
989	}
990}
991
992// UnmarshalText implements the encoding.TextUnmarshaler interface.
993// The IP address is expected in a form accepted by [ParseAddr].
994//
995// If text is empty, UnmarshalText sets *ip to the zero [Addr] and
996// returns no error.
997func (ip *Addr) UnmarshalText(text []byte) error {
998	if len(text) == 0 {
999		*ip = Addr{}
1000		return nil
1001	}
1002	var err error
1003	*ip, err = ParseAddr(string(text))
1004	return err
1005}
1006
1007func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte {
1008	var b []byte
1009	switch ip.z {
1010	case z0:
1011		b = make([]byte, trailingBytes)
1012	case z4:
1013		b = make([]byte, 4+trailingBytes)
1014		byteorder.BePutUint32(b, uint32(ip.addr.lo))
1015	default:
1016		z := ip.Zone()
1017		b = make([]byte, 16+len(z)+trailingBytes)
1018		byteorder.BePutUint64(b[:8], ip.addr.hi)
1019		byteorder.BePutUint64(b[8:], ip.addr.lo)
1020		copy(b[16:], z)
1021	}
1022	return b
1023}
1024
1025// MarshalBinary implements the [encoding.BinaryMarshaler] interface.
1026// It returns a zero-length slice for the zero [Addr],
1027// the 4-byte form for an IPv4 address,
1028// and the 16-byte form with zone appended for an IPv6 address.
1029func (ip Addr) MarshalBinary() ([]byte, error) {
1030	return ip.marshalBinaryWithTrailingBytes(0), nil
1031}
1032
1033// UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
1034// It expects data in the form generated by MarshalBinary.
1035func (ip *Addr) UnmarshalBinary(b []byte) error {
1036	n := len(b)
1037	switch {
1038	case n == 0:
1039		*ip = Addr{}
1040		return nil
1041	case n == 4:
1042		*ip = AddrFrom4([4]byte(b))
1043		return nil
1044	case n == 16:
1045		*ip = AddrFrom16([16]byte(b))
1046		return nil
1047	case n > 16:
1048		*ip = AddrFrom16([16]byte(b[:16])).WithZone(string(b[16:]))
1049		return nil
1050	}
1051	return errors.New("unexpected slice size")
1052}
1053
1054// AddrPort is an IP and a port number.
1055type AddrPort struct {
1056	ip   Addr
1057	port uint16
1058}
1059
1060// AddrPortFrom returns an [AddrPort] with the provided IP and port.
1061// It does not allocate.
1062func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} }
1063
1064// Addr returns p's IP address.
1065func (p AddrPort) Addr() Addr { return p.ip }
1066
1067// Port returns p's port.
1068func (p AddrPort) Port() uint16 { return p.port }
1069
1070// splitAddrPort splits s into an IP address string and a port
1071// string. It splits strings shaped like "foo:bar" or "[foo]:bar",
1072// without further validating the substrings. v6 indicates whether the
1073// ip string should parse as an IPv6 address or an IPv4 address, in
1074// order for s to be a valid ip:port string.
1075func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
1076	i := bytealg.LastIndexByteString(s, ':')
1077	if i == -1 {
1078		return "", "", false, errors.New("not an ip:port")
1079	}
1080
1081	ip, port = s[:i], s[i+1:]
1082	if len(ip) == 0 {
1083		return "", "", false, errors.New("no IP")
1084	}
1085	if len(port) == 0 {
1086		return "", "", false, errors.New("no port")
1087	}
1088	if ip[0] == '[' {
1089		if len(ip) < 2 || ip[len(ip)-1] != ']' {
1090			return "", "", false, errors.New("missing ]")
1091		}
1092		ip = ip[1 : len(ip)-1]
1093		v6 = true
1094	}
1095
1096	return ip, port, v6, nil
1097}
1098
1099// ParseAddrPort parses s as an [AddrPort].
1100//
1101// It doesn't do any name resolution: both the address and the port
1102// must be numeric.
1103func ParseAddrPort(s string) (AddrPort, error) {
1104	var ipp AddrPort
1105	ip, port, v6, err := splitAddrPort(s)
1106	if err != nil {
1107		return ipp, err
1108	}
1109	port16, err := strconv.ParseUint(port, 10, 16)
1110	if err != nil {
1111		return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s))
1112	}
1113	ipp.port = uint16(port16)
1114	ipp.ip, err = ParseAddr(ip)
1115	if err != nil {
1116		return AddrPort{}, err
1117	}
1118	if v6 && ipp.ip.Is4() {
1119		return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses")
1120	} else if !v6 && ipp.ip.Is6() {
1121		return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets")
1122	}
1123	return ipp, nil
1124}
1125
1126// MustParseAddrPort calls [ParseAddrPort](s) and panics on error.
1127// It is intended for use in tests with hard-coded strings.
1128func MustParseAddrPort(s string) AddrPort {
1129	ip, err := ParseAddrPort(s)
1130	if err != nil {
1131		panic(err)
1132	}
1133	return ip
1134}
1135
1136// IsValid reports whether p.Addr() is valid.
1137// All ports are valid, including zero.
1138func (p AddrPort) IsValid() bool { return p.ip.IsValid() }
1139
1140// Compare returns an integer comparing two AddrPorts.
1141// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
1142// AddrPorts sort first by IP address, then port.
1143func (p AddrPort) Compare(p2 AddrPort) int {
1144	if c := p.Addr().Compare(p2.Addr()); c != 0 {
1145		return c
1146	}
1147	return cmp.Compare(p.Port(), p2.Port())
1148}
1149
1150func (p AddrPort) String() string {
1151	var b []byte
1152	switch p.ip.z {
1153	case z0:
1154		return "invalid AddrPort"
1155	case z4:
1156		const max = len("255.255.255.255:65535")
1157		b = make([]byte, 0, max)
1158		b = p.ip.appendTo4(b)
1159	default:
1160		if p.ip.Is4In6() {
1161			const max = len("[::ffff:255.255.255.255%enp5s0]:65535")
1162			b = make([]byte, 0, max)
1163			b = append(b, '[')
1164			b = p.ip.appendTo4In6(b)
1165		} else {
1166			const max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1167			b = make([]byte, 0, max)
1168			b = append(b, '[')
1169			b = p.ip.appendTo6(b)
1170		}
1171		b = append(b, ']')
1172	}
1173	b = append(b, ':')
1174	b = strconv.AppendUint(b, uint64(p.port), 10)
1175	return string(b)
1176}
1177
1178// AppendTo appends a text encoding of p,
1179// as generated by [AddrPort.MarshalText],
1180// to b and returns the extended buffer.
1181func (p AddrPort) AppendTo(b []byte) []byte {
1182	switch p.ip.z {
1183	case z0:
1184		return b
1185	case z4:
1186		b = p.ip.appendTo4(b)
1187	default:
1188		b = append(b, '[')
1189		if p.ip.Is4In6() {
1190			b = p.ip.appendTo4In6(b)
1191		} else {
1192			b = p.ip.appendTo6(b)
1193		}
1194		b = append(b, ']')
1195	}
1196	b = append(b, ':')
1197	b = strconv.AppendUint(b, uint64(p.port), 10)
1198	return b
1199}
1200
1201// MarshalText implements the [encoding.TextMarshaler] interface. The
1202// encoding is the same as returned by [AddrPort.String], with one exception: if
1203// p.Addr() is the zero [Addr], the encoding is the empty string.
1204func (p AddrPort) MarshalText() ([]byte, error) {
1205	var max int
1206	switch p.ip.z {
1207	case z0:
1208	case z4:
1209		max = len("255.255.255.255:65535")
1210	default:
1211		max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535")
1212	}
1213	b := make([]byte, 0, max)
1214	b = p.AppendTo(b)
1215	return b, nil
1216}
1217
1218// UnmarshalText implements the encoding.TextUnmarshaler
1219// interface. The [AddrPort] is expected in a form
1220// generated by [AddrPort.MarshalText] or accepted by [ParseAddrPort].
1221func (p *AddrPort) UnmarshalText(text []byte) error {
1222	if len(text) == 0 {
1223		*p = AddrPort{}
1224		return nil
1225	}
1226	var err error
1227	*p, err = ParseAddrPort(string(text))
1228	return err
1229}
1230
1231// MarshalBinary implements the [encoding.BinaryMarshaler] interface.
1232// It returns [Addr.MarshalBinary] with an additional two bytes appended
1233// containing the port in little-endian.
1234func (p AddrPort) MarshalBinary() ([]byte, error) {
1235	b := p.Addr().marshalBinaryWithTrailingBytes(2)
1236	byteorder.LePutUint16(b[len(b)-2:], p.Port())
1237	return b, nil
1238}
1239
1240// UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
1241// It expects data in the form generated by [AddrPort.MarshalBinary].
1242func (p *AddrPort) UnmarshalBinary(b []byte) error {
1243	if len(b) < 2 {
1244		return errors.New("unexpected slice size")
1245	}
1246	var addr Addr
1247	err := addr.UnmarshalBinary(b[:len(b)-2])
1248	if err != nil {
1249		return err
1250	}
1251	*p = AddrPortFrom(addr, byteorder.LeUint16(b[len(b)-2:]))
1252	return nil
1253}
1254
1255// Prefix is an IP address prefix (CIDR) representing an IP network.
1256//
1257// The first [Prefix.Bits]() of [Addr]() are specified. The remaining bits match any address.
1258// The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6.
1259type Prefix struct {
1260	ip Addr
1261
1262	// bitsPlusOne stores the prefix bit length plus one.
1263	// A Prefix is valid if and only if bitsPlusOne is non-zero.
1264	bitsPlusOne uint8
1265}
1266
1267// PrefixFrom returns a [Prefix] with the provided IP address and bit
1268// prefix length.
1269//
1270// It does not allocate. Unlike [Addr.Prefix], [PrefixFrom] does not mask
1271// off the host bits of ip.
1272//
1273// If bits is less than zero or greater than ip.BitLen, [Prefix.Bits]
1274// will return an invalid value -1.
1275func PrefixFrom(ip Addr, bits int) Prefix {
1276	var bitsPlusOne uint8
1277	if !ip.isZero() && bits >= 0 && bits <= ip.BitLen() {
1278		bitsPlusOne = uint8(bits) + 1
1279	}
1280	return Prefix{
1281		ip:          ip.withoutZone(),
1282		bitsPlusOne: bitsPlusOne,
1283	}
1284}
1285
1286// Addr returns p's IP address.
1287func (p Prefix) Addr() Addr { return p.ip }
1288
1289// Bits returns p's prefix length.
1290//
1291// It reports -1 if invalid.
1292func (p Prefix) Bits() int { return int(p.bitsPlusOne) - 1 }
1293
1294// IsValid reports whether p.Bits() has a valid range for p.Addr().
1295// If p.Addr() is the zero [Addr], IsValid returns false.
1296// Note that if p is the zero [Prefix], then p.IsValid() == false.
1297func (p Prefix) IsValid() bool { return p.bitsPlusOne > 0 }
1298
1299func (p Prefix) isZero() bool { return p == Prefix{} }
1300
1301// IsSingleIP reports whether p contains exactly one IP.
1302func (p Prefix) IsSingleIP() bool { return p.IsValid() && p.Bits() == p.ip.BitLen() }
1303
1304// compare returns an integer comparing two prefixes.
1305// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
1306// Prefixes sort first by validity (invalid before valid), then
1307// address family (IPv4 before IPv6), then prefix length, then
1308// address.
1309//
1310// Unexported for Go 1.22 because we may want to compare by p.Addr first.
1311// See post-acceptance discussion on go.dev/issue/61642.
1312func (p Prefix) compare(p2 Prefix) int {
1313	if c := cmp.Compare(p.Addr().BitLen(), p2.Addr().BitLen()); c != 0 {
1314		return c
1315	}
1316	if c := cmp.Compare(p.Bits(), p2.Bits()); c != 0 {
1317		return c
1318	}
1319	return p.Addr().Compare(p2.Addr())
1320}
1321
1322type parsePrefixError struct {
1323	in  string // the string given to ParsePrefix
1324	msg string // an explanation of the parse failure
1325}
1326
1327func (err parsePrefixError) Error() string {
1328	return "netip.ParsePrefix(" + strconv.Quote(err.in) + "): " + err.msg
1329}
1330
1331// ParsePrefix parses s as an IP address prefix.
1332// The string can be in the form "192.168.1.0/24" or "2001:db8::/32",
1333// the CIDR notation defined in RFC 4632 and RFC 4291.
1334// IPv6 zones are not permitted in prefixes, and an error will be returned if a
1335// zone is present.
1336//
1337// Note that masked address bits are not zeroed. Use Masked for that.
1338func ParsePrefix(s string) (Prefix, error) {
1339	i := bytealg.LastIndexByteString(s, '/')
1340	if i < 0 {
1341		return Prefix{}, parsePrefixError{in: s, msg: "no '/'"}
1342	}
1343	ip, err := ParseAddr(s[:i])
1344	if err != nil {
1345		return Prefix{}, parsePrefixError{in: s, msg: err.Error()}
1346	}
1347	// IPv6 zones are not allowed: https://go.dev/issue/51899
1348	if ip.Is6() && ip.z != z6noz {
1349		return Prefix{}, parsePrefixError{in: s, msg: "IPv6 zones cannot be present in a prefix"}
1350	}
1351
1352	bitsStr := s[i+1:]
1353
1354	// strconv.Atoi accepts a leading sign and leading zeroes, but we don't want that.
1355	if len(bitsStr) > 1 && (bitsStr[0] < '1' || bitsStr[0] > '9') {
1356		return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)}
1357	}
1358
1359	bits, err := strconv.Atoi(bitsStr)
1360	if err != nil {
1361		return Prefix{}, parsePrefixError{in: s, msg: "bad bits after slash: " + strconv.Quote(bitsStr)}
1362	}
1363	maxBits := 32
1364	if ip.Is6() {
1365		maxBits = 128
1366	}
1367	if bits < 0 || bits > maxBits {
1368		return Prefix{}, parsePrefixError{in: s, msg: "prefix length out of range"}
1369	}
1370	return PrefixFrom(ip, bits), nil
1371}
1372
1373// MustParsePrefix calls [ParsePrefix](s) and panics on error.
1374// It is intended for use in tests with hard-coded strings.
1375func MustParsePrefix(s string) Prefix {
1376	ip, err := ParsePrefix(s)
1377	if err != nil {
1378		panic(err)
1379	}
1380	return ip
1381}
1382
1383// Masked returns p in its canonical form, with all but the high
1384// p.Bits() bits of p.Addr() masked off.
1385//
1386// If p is zero or otherwise invalid, Masked returns the zero [Prefix].
1387func (p Prefix) Masked() Prefix {
1388	m, _ := p.ip.Prefix(p.Bits())
1389	return m
1390}
1391
1392// Contains reports whether the network p includes ip.
1393//
1394// An IPv4 address will not match an IPv6 prefix.
1395// An IPv4-mapped IPv6 address will not match an IPv4 prefix.
1396// A zero-value IP will not match any prefix.
1397// If ip has an IPv6 zone, Contains returns false,
1398// because Prefixes strip zones.
1399func (p Prefix) Contains(ip Addr) bool {
1400	if !p.IsValid() || ip.hasZone() {
1401		return false
1402	}
1403	if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 {
1404		return false
1405	}
1406	if ip.Is4() {
1407		// xor the IP addresses together; mismatched bits are now ones.
1408		// Shift away the number of bits we don't care about.
1409		// Shifts in Go are more efficient if the compiler can prove
1410		// that the shift amount is smaller than the width of the shifted type (64 here).
1411		// We know that p.bits is in the range 0..32 because p is Valid;
1412		// the compiler doesn't know that, so mask with 63 to help it.
1413		// Now truncate to 32 bits, because this is IPv4.
1414		// If all the bits we care about are equal, the result will be zero.
1415		return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.Bits())&63)) == 0
1416	} else {
1417		// xor the IP addresses together.
1418		// Mask away the bits we don't care about.
1419		// If all the bits we care about are equal, the result will be zero.
1420		return ip.addr.xor(p.ip.addr).and(mask6(p.Bits())).isZero()
1421	}
1422}
1423
1424// Overlaps reports whether p and o contain any IP addresses in common.
1425//
1426// If p and o are of different address families or either have a zero
1427// IP, it reports false. Like the Contains method, a prefix with an
1428// IPv4-mapped IPv6 address is still treated as an IPv6 mask.
1429func (p Prefix) Overlaps(o Prefix) bool {
1430	if !p.IsValid() || !o.IsValid() {
1431		return false
1432	}
1433	if p == o {
1434		return true
1435	}
1436	if p.ip.Is4() != o.ip.Is4() {
1437		return false
1438	}
1439	var minBits int
1440	if pb, ob := p.Bits(), o.Bits(); pb < ob {
1441		minBits = pb
1442	} else {
1443		minBits = ob
1444	}
1445	if minBits == 0 {
1446		return true
1447	}
1448	// One of these Prefix calls might look redundant, but we don't require
1449	// that p and o values are normalized (via Prefix.Masked) first,
1450	// so the Prefix call on the one that's already minBits serves to zero
1451	// out any remaining bits in IP.
1452	var err error
1453	if p, err = p.ip.Prefix(minBits); err != nil {
1454		return false
1455	}
1456	if o, err = o.ip.Prefix(minBits); err != nil {
1457		return false
1458	}
1459	return p.ip == o.ip
1460}
1461
1462// AppendTo appends a text encoding of p,
1463// as generated by [Prefix.MarshalText],
1464// to b and returns the extended buffer.
1465func (p Prefix) AppendTo(b []byte) []byte {
1466	if p.isZero() {
1467		return b
1468	}
1469	if !p.IsValid() {
1470		return append(b, "invalid Prefix"...)
1471	}
1472
1473	// p.ip is non-nil, because p is valid.
1474	if p.ip.z == z4 {
1475		b = p.ip.appendTo4(b)
1476	} else {
1477		if p.ip.Is4In6() {
1478			b = append(b, "::ffff:"...)
1479			b = p.ip.Unmap().appendTo4(b)
1480		} else {
1481			b = p.ip.appendTo6(b)
1482		}
1483	}
1484
1485	b = append(b, '/')
1486	b = appendDecimal(b, uint8(p.Bits()))
1487	return b
1488}
1489
1490// MarshalText implements the [encoding.TextMarshaler] interface,
1491// The encoding is the same as returned by [Prefix.String], with one exception:
1492// If p is the zero value, the encoding is the empty string.
1493func (p Prefix) MarshalText() ([]byte, error) {
1494	var max int
1495	switch p.ip.z {
1496	case z0:
1497	case z4:
1498		max = len("255.255.255.255/32")
1499	default:
1500		max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128")
1501	}
1502	b := make([]byte, 0, max)
1503	b = p.AppendTo(b)
1504	return b, nil
1505}
1506
1507// UnmarshalText implements the encoding.TextUnmarshaler interface.
1508// The IP address is expected in a form accepted by [ParsePrefix]
1509// or generated by [Prefix.MarshalText].
1510func (p *Prefix) UnmarshalText(text []byte) error {
1511	if len(text) == 0 {
1512		*p = Prefix{}
1513		return nil
1514	}
1515	var err error
1516	*p, err = ParsePrefix(string(text))
1517	return err
1518}
1519
1520// MarshalBinary implements the [encoding.BinaryMarshaler] interface.
1521// It returns [Addr.MarshalBinary] with an additional byte appended
1522// containing the prefix bits.
1523func (p Prefix) MarshalBinary() ([]byte, error) {
1524	b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1)
1525	b[len(b)-1] = uint8(p.Bits())
1526	return b, nil
1527}
1528
1529// UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
1530// It expects data in the form generated by [Prefix.MarshalBinary].
1531func (p *Prefix) UnmarshalBinary(b []byte) error {
1532	if len(b) < 1 {
1533		return errors.New("unexpected slice size")
1534	}
1535	var addr Addr
1536	err := addr.UnmarshalBinary(b[:len(b)-1])
1537	if err != nil {
1538		return err
1539	}
1540	*p = PrefixFrom(addr, int(b[len(b)-1]))
1541	return nil
1542}
1543
1544// String returns the CIDR notation of p: "<ip>/<bits>".
1545func (p Prefix) String() string {
1546	if !p.IsValid() {
1547		return "invalid Prefix"
1548	}
1549	return p.ip.String() + "/" + itoa.Itoa(p.Bits())
1550}
1551