2 * Copyright (c) 2016 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.annotations.Beta;
14 import com.google.common.net.InetAddresses;
15 import java.net.Inet4Address;
16 import java.net.Inet6Address;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.util.AbstractMap.SimpleImmutableEntry;
20 import java.util.Map.Entry;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.mdsal.binding.spec.reflect.StringValueObjectFactory;
24 import org.opendaylight.mdsal.model.ietf.util.Ipv4Utils;
25 import org.opendaylight.mdsal.model.ietf.util.Ipv6Utils;
28 * A set of utility methods to efficiently instantiate various ietf-inet-types DTOs.
31 @SuppressWarnings("checkstyle:classTypeParameterName")
32 public abstract class AbstractIetfInetUtil {
33 private final StringValueObjectFactory<Ipv4AddressNoZone> address4NoZoneFactory =
34 StringValueObjectFactory.create(Ipv4AddressNoZone.class, "0.0.0.0");
35 private final StringValueObjectFactory<Ipv4Prefix> prefix4Factory =
36 StringValueObjectFactory.create(Ipv4Prefix.class, "0.0.0.0/0");
37 private final StringValueObjectFactory<Ipv6AddressNoZone> address6NoZoneFactory =
38 StringValueObjectFactory.create(Ipv6AddressNoZone.class, "::0");
39 private final StringValueObjectFactory<Ipv6Prefix> prefix6Factory =
40 StringValueObjectFactory.create(Ipv6Prefix.class, "::0/0");
42 protected abstract @NonNull IpAddress ipv4Address(@NonNull Ipv4AddressNoZone addr);
44 protected abstract @NonNull IpAddressNoZone ipv4AddressNoZone(@NonNull Ipv4AddressNoZone addr);
46 protected abstract @NonNull IpAddress ipv6Address(@NonNull Ipv6AddressNoZone addr);
48 protected abstract @NonNull IpAddressNoZone ipv6AddressNoZone(@NonNull Ipv6AddressNoZone addr);
50 protected abstract @Nullable Ipv4Address maybeIpv4Address(@NonNull IpAddress addr);
52 protected abstract @Nullable Ipv4AddressNoZone maybeIpv4AddressNoZone(@NonNull IpAddressNoZone addr);
54 protected abstract @Nullable Ipv6Address maybeIpv6Address(@NonNull IpAddress addr);
56 protected abstract @Nullable Ipv6AddressNoZone maybeIpv6AddressNoZone(@NonNull IpAddressNoZone addr);
58 protected abstract @NonNull IpPrefix ipv4Prefix(@NonNull Ipv4Prefix addr);
60 protected abstract @NonNull IpPrefix ipv6Prefix(@NonNull Ipv6Prefix addr);
62 protected abstract @NonNull String ipv4AddressString(@NonNull Ipv4Address addr);
64 protected abstract @NonNull String ipv6AddressString(@NonNull Ipv6Address addr);
66 protected abstract @NonNull String ipv4PrefixString(@NonNull Ipv4Prefix prefix);
68 protected abstract @NonNull String ipv6PrefixString(@NonNull Ipv6Prefix prefix);
71 * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
73 * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
74 * @return An IpAddress object
75 * @throws IllegalArgumentException if bytes has length different from 4 or 6
76 * @throws NullPointerException if bytes is null
78 public final @NonNull IpAddress ipAddressFor(final byte @NonNull[] bytes) {
79 return switch (bytes.length) {
80 case Ipv4Utils.INET4_LENGTH -> ipv4Address(ipv4AddressFor(bytes));
81 case Ipv6Utils.INET6_LENGTH -> ipv6Address(ipv6AddressFor(bytes));
82 default -> throwInvalidArray(bytes);
86 public final @NonNull IpAddress ipAddressFor(final @NonNull InetAddress addr) {
88 if (addr instanceof Inet4Address) {
89 return ipv4Address(ipv4AddressFor(addr));
90 } else if (addr instanceof Inet6Address) {
91 return ipv6Address(ipv6AddressFor(addr));
93 throw unhandledAddress(addr);
97 private static <T> @NonNull T requireAddress(final T addr) {
98 return requireNonNull(addr, "Address must not be null");
102 * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
104 * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
105 * @return A no-zone IpAddress object
106 * @throws IllegalArgumentException if bytes has length different from 4 or 6
107 * @throws NullPointerException if bytes is null
109 public final @NonNull IpAddressNoZone ipAddressNoZoneFor(final byte @NonNull[] bytes) {
110 return switch (bytes.length) {
111 case Ipv4Utils.INET4_LENGTH -> ipv4AddressNoZone(ipv4AddressFor(bytes));
112 case Ipv6Utils.INET6_LENGTH -> ipv6AddressNoZone(ipv6AddressFor(bytes));
113 default -> throwInvalidArray(bytes);
117 public final @NonNull IpAddressNoZone ipAddressNoZoneFor(final @NonNull InetAddress addr) {
118 requireAddress(addr);
119 if (addr instanceof Inet4Address) {
120 return ipv4AddressNoZone(ipv4AddressFor(addr));
121 } else if (addr instanceof Inet6Address) {
122 return ipv6AddressNoZone(ipv6AddressFor(addr));
124 throw unhandledAddress(addr);
128 private static <T> T throwInvalidArray(final byte[] bytes) {
129 throw new IllegalArgumentException("Invalid array length " + bytes.length);
132 private static IllegalArgumentException unhandledAddress(final InetAddress addr) {
133 return new IllegalArgumentException("Unhandled address " + addr);
137 * Create an IpPrefix by combining the address with a mask. The address
138 * bytes are interpreted as an address and the specified mask is concatenated to
139 * it. The address bytes are not masked.
141 * @param bytes Input address as a 4-byte (IPv4) or 16-byte (IPv6) array
142 * @param mask Prefix mask
143 * @return An IpPrefix object
144 * @throws IllegalArgumentException if bytes has length different from 4 or 16 or if mask is not
145 * in range 0-32 or 0-128 respectively
146 * @throws NullPointerException if bytes is null
148 public final @NonNull IpPrefix ipPrefixFor(final byte @NonNull[] bytes, final int mask) {
149 return switch (bytes.length) {
150 case Ipv4Utils.INET4_LENGTH -> ipv4Prefix(ipv4PrefixFor(bytes, mask));
151 case Ipv6Utils.INET6_LENGTH -> ipv6Prefix(ipv6PrefixFor(bytes, mask));
152 default -> throwInvalidArray(bytes);
156 public final @NonNull IpPrefix ipPrefixFor(final @NonNull InetAddress addr, final int mask) {
157 requireAddress(addr);
158 if (addr instanceof Inet4Address) {
159 return ipv4Prefix(ipv4PrefixFor(addr, mask));
160 } else if (addr instanceof Inet6Address) {
161 return ipv6Prefix(ipv6PrefixFor(addr, mask));
163 throw unhandledAddress(addr);
167 public final @NonNull IpPrefix ipPrefixFor(final @NonNull IpAddress addr) {
168 final var v4 = maybeIpv4Address(addr);
169 return v4 != null ? ipv4Prefix(ipv4PrefixFor(v4)) : ipv6Prefix(ipv6PrefixFor(coerceIpv6Address(addr)));
172 public final @NonNull IpPrefix ipPrefixForNoZone(final @NonNull IpAddressNoZone addr) {
173 final var v4 = maybeIpv4AddressNoZone(addr);
174 return v4 != null ? ipv4Prefix(ipv4PrefixFor(inet4AddressForNoZone(v4)))
175 : ipv6Prefix(ipv6PrefixFor(coerceIpv6AddressNoZone(addr)));
178 public final @NonNull InetAddress inetAddressFor(final @NonNull IpAddress addr) {
179 final var v4 = maybeIpv4Address(addr);
180 return v4 != null ? inet4AddressFor(v4) : inet6AddressFor(coerceIpv6Address(addr));
183 public final @NonNull InetAddress inetAddressForNoZone(final @NonNull IpAddressNoZone addr) {
184 final var v4 = maybeIpv4AddressNoZone(addr);
185 return v4 != null ? inet4AddressForNoZone(v4) : inet6AddressForNoZone(coerceIpv6AddressNoZone(addr));
188 public final @NonNull Inet4Address inet4AddressFor(final @NonNull Ipv4Address addr) {
190 return (Inet4Address) InetAddress.getByAddress(ipv4AddressBytes(addr));
191 } catch (UnknownHostException e) {
192 throw new IllegalArgumentException("Invalid address " + addr, e);
196 public final @NonNull Inet4Address inet4AddressForNoZone(final @NonNull Ipv4AddressNoZone addr) {
198 return (Inet4Address) InetAddress.getByAddress(ipv4AddressNoZoneBytes(addr));
199 } catch (UnknownHostException e) {
200 throw new IllegalArgumentException("Invalid address " + addr, e);
204 public final @NonNull Inet6Address inet6AddressFor(final @NonNull Ipv6Address addr) {
206 return (Inet6Address) InetAddress.getByAddress(ipv6AddressBytes(addr));
207 } catch (UnknownHostException e) {
208 throw new IllegalArgumentException("Invalid address " + addr, e);
212 public final @NonNull Inet6Address inet6AddressForNoZone(final @NonNull Ipv6AddressNoZone addr) {
214 return (Inet6Address) InetAddress.getByAddress(ipv6AddressNoZoneBytes(addr));
215 } catch (UnknownHostException e) {
216 throw new IllegalArgumentException("Invalid address " + addr, e);
221 * Create an Ipv4AddressNoZone by interpreting input bytes as an IPv4 address.
223 * @param bytes 4-byte array
224 * @return An Ipv4AddressNoZone object
225 * @throws IllegalArgumentException if bytes has length different from 4
226 * @throws NullPointerException if bytes is null
228 public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final byte @NonNull[] bytes) {
229 return address4NoZoneFactory.newInstance(Ipv4Utils.addressString(bytes));
233 * Create an Ipv4AddressNoZone by interpreting an {@link Inet4Address}.
235 * @param addr An {@link Inet4Address}
236 * @return An Ipv4AddressNoZone object
237 * @throws IllegalArgumentException if addr is not an {@link Inet4Address}
238 * @throws NullPointerException if addr is null
240 public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final @NonNull InetAddress addr) {
241 return address4NoZoneFactory.newInstance(addressStringV4(addr));
245 * Create an Ipv4AddressNoZone by interpreting input 32 bits as an IPv4 address in big-endian format.
247 * @param bits 32 bits, big endian
248 * @return An Ipv4AddressNoZone object
250 public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final int bits) {
251 return address4NoZoneFactory.newInstance(Ipv4Utils.addressString(bits));
255 * Create an Ipv4AddressNoZone by interpreting an Ipv4Address.
257 * @param addr An Ipv4Address
258 * @return An Ipv4AddressNoZone object
259 * @throws NullPointerException if addr is null
261 public final @NonNull Ipv4AddressNoZone ipv4AddressNoZoneFor(final @NonNull Ipv4Address addr) {
262 requireAddress(addr);
263 return addr instanceof Ipv4AddressNoZone noZone ? noZone
264 : address4NoZoneFactory.newInstance(stripZone(ipv4AddressString(addr)));
267 public final @NonNull Ipv4AddressNoZone ipv4AddressFrom(final @NonNull Ipv4Prefix prefix) {
268 return prefixToAddress(address4NoZoneFactory, ipv4PrefixString(prefix));
271 public final byte @NonNull[] ipv4AddressBytes(final @NonNull Ipv4Address addr) {
273 * This implementation relies heavily on the input string having been validated to comply with
274 * the Ipv4Address pattern, which may include a zone index.
276 final String str = ipv4AddressString(addr);
277 final int percent = str.indexOf('%');
278 return Ipv4Utils.addressBytes(str, percent == -1 ? str.length() : percent);
281 public final int ipv4AddressBits(final @NonNull Ipv4Address addr) {
282 final String str = ipv4AddressString(addr);
283 final int percent = str.indexOf('%');
284 return Ipv4Utils.addressBits(str, percent == -1 ? str.length() : percent);
287 public final byte @NonNull[] ipv4AddressNoZoneBytes(final @NonNull Ipv4AddressNoZone addr) {
289 * This implementation relies heavily on the input string having been validated to comply with
290 * the Ipv4AddressNoZone pattern, which must not include a zone index.
292 final String str = ipv4AddressString(addr);
293 return Ipv4Utils.addressBytes(str, str.length());
296 public final int ipv4AddressNoZoneBits(final @NonNull Ipv4AddressNoZone addr) {
297 final String str = ipv4AddressString(addr);
298 return Ipv4Utils.addressBits(str, str.length());
302 * Create a /32 Ipv4Prefix by interpreting input bytes as an IPv4 address.
304 * @param bytes four-byte array
305 * @return An Ipv4Prefix object
306 * @throws IllegalArgumentException if bytes has length different from 4
307 * @throws NullPointerException if bytes is null
309 public final @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] bytes) {
310 return prefix4Factory.newInstance(prefixStringV4(bytes));
314 * Create a Ipv4Prefix by combining the address with a mask. The address
315 * bytes are interpreted as an address and the specified mask is concatenated to
316 * it. The address bytes are not masked, hence input <code>address = { 1, 2, 3, 4 }</code>
317 * and <code>mask=24</code> will result in <code>1.2.3.4/24</code>.
319 * @param address Input address as a 4-byte array
320 * @param mask Prefix mask
321 * @return An Ipv4Prefix object
322 * @throws IllegalArgumentException if bytes has length different from 4 or if mask is not in range 0-32
323 * @throws NullPointerException if bytes is null
325 public final @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] address, final int mask) {
326 return prefix4Factory.newInstance(prefixStringV4(address, mask));
330 * Create a /32 Ipv4Prefix for an {@link Inet4Address}.
332 * @param addr An {@link Inet4Address}
333 * @return An Ipv4Prefix object
334 * @throws IllegalArgumentException if addr is not an Inet4Address
335 * @throws NullPointerException if addr is null
337 public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr) {
338 return prefix4Factory.newInstance(addressStringV4(addr) + "/32");
342 * Create a Ipv4Prefix by combining the address with a mask. The address bytes are not masked.
344 * @param addr An {@link Inet4Address}
345 * @param mask Prefix mask
346 * @return An Ipv4Prefix object
347 * @throws IllegalArgumentException if addr is not an Inet4Address or if mask is not in range 0-32
348 * @throws NullPointerException if addr is null
350 public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr, final int mask) {
351 return newIpv4Prefix(addressStringV4(addr), mask);
354 public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr) {
355 return prefix4Factory.newInstance(stripZone(ipv4AddressString(requireAddress(addr))) + "/32");
358 public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr, final int mask) {
359 return newIpv4Prefix(stripZone(ipv4AddressString(requireAddress(addr))), mask);
362 public final @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr) {
363 return prefix4Factory.newInstance(ipv4AddressString(requireAddress(addr)) + "/32");
366 public final @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr, final int mask) {
367 return newIpv4Prefix(ipv4AddressString(requireAddress(addr)), mask);
370 public final @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] address, final int mask) {
372 // Easy case, reuse the template
373 return prefix4Factory.getTemplate();
376 return v4PrefixForShort(address, 0, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
379 public final @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] array, final int startOffset,
382 // Easy case, reuse the template
383 return prefix4Factory.getTemplate();
386 return v4PrefixForShort(array, startOffset, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
389 private static String stripZone(final String str) {
390 final int percent = str.indexOf('%');
391 return percent == -1 ? str : str.substring(0, percent);
394 private @NonNull Ipv4Prefix newIpv4Prefix(final String addr, final int mask) {
395 checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
396 return prefix4Factory.newInstance(addr + '/' + mask);
399 public final @NonNull Entry<Ipv4AddressNoZone, Integer> splitIpv4Prefix(final @NonNull Ipv4Prefix prefix) {
400 return splitPrefix(address4NoZoneFactory, ipv4PrefixString(prefix));
403 public final byte @NonNull[] ipv4PrefixToBytes(final @NonNull Ipv4Prefix prefix) {
404 final String str = ipv4PrefixString(prefix);
405 final int slash = str.lastIndexOf('/');
407 final byte[] bytes = new byte[Ipv4Utils.INET4_LENGTH + 1];
408 Ipv4Utils.fillIpv4Bytes(bytes, 0, str, 0, slash);
409 bytes[Ipv4Utils.INET4_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
414 * Create an Ipv6Address by interpreting input bytes as an IPv6 address.
416 * @param bytes 16-byte array
417 * @return An Ipv6Address object
418 * @throws IllegalArgumentException if bytes has length different from 16
419 * @throws NullPointerException if bytes is null
421 public final @NonNull Ipv6AddressNoZone ipv6AddressFor(final byte @NonNull[] bytes) {
422 return address6NoZoneFactory.newInstance(addressStringV6(bytes));
426 * Create an Ipv6Address by interpreting an {@link Inet6Address}.
428 * @param addr An {@link Inet6Address}
429 * @return An Ipv6Address object
430 * @throws IllegalArgumentException if addr is not an {@link Inet6Address}
431 * @throws NullPointerException if addr is null
433 public final @NonNull Ipv6AddressNoZone ipv6AddressFor(final @NonNull InetAddress addr) {
434 return address6NoZoneFactory.newInstance(addressStringV6(addr));
438 * Create an Ipv6AddressNoZone by interpreting an Ipv6Address.
440 * @param addr An Ipv6Address
441 * @return An Ipv6AddressNoZone object
442 * @throws NullPointerException if addr is null
444 public final @NonNull Ipv6AddressNoZone ipv6AddressNoZoneFor(final @NonNull Ipv6Address addr) {
445 requireAddress(addr);
446 return addr instanceof Ipv6AddressNoZone noZone ? noZone
447 : address6NoZoneFactory.newInstance(stripZone(ipv6AddressString(addr)));
450 public final @NonNull Ipv6AddressNoZone ipv6AddressFrom(final @NonNull Ipv6Prefix prefix) {
451 return prefixToAddress(address6NoZoneFactory, ipv6PrefixString(prefix));
454 public final byte @NonNull[] ipv6AddressBytes(final @NonNull Ipv6Address addr) {
455 final String str = ipv6AddressString(addr);
456 final int percent = str.indexOf('%');
457 return ipv6StringBytes(str, percent == -1 ? str.length() : percent);
460 public final byte @NonNull[] ipv6AddressNoZoneBytes(final @NonNull Ipv6Address addr) {
461 final String str = ipv6AddressString(addr);
462 return ipv6StringBytes(str, str.length());
465 private static byte @NonNull[] ipv6StringBytes(final @NonNull String str, final int limit) {
466 final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH];
467 Ipv6Utils.fillIpv6Bytes(bytes, str, limit);
472 * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
474 * @param bytes four-byte array
475 * @return An Ipv6Prefix object
476 * @throws IllegalArgumentException if bytes has length different from 16
477 * @throws NullPointerException if bytes is null
479 public final @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] bytes) {
480 return prefix6Factory.newInstance(addressStringV6(bytes) + "/128");
484 * Create a Ipv6Prefix by combining the address with a mask. The address
485 * bytes are interpreted as an address and the specified mask is concatenated to
486 * it. The address bytes are not masked.
488 * @param address Input address as a 16-byte array
489 * @param mask Prefix mask
490 * @return An Ipv6Prefix object
491 * @throws IllegalArgumentException if bytes has length different from 16 or if mask is not in range 0-128
492 * @throws NullPointerException if bytes is null
494 public final @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] address, final int mask) {
495 checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
496 return prefix6Factory.newInstance(addressStringV6(address) + '/' + mask);
500 * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
502 * @param addr an {@link Inet6Address}
503 * @return An Ipv6Prefix object
504 * @throws IllegalArgumentException if addr is not an Inet6Address
505 * @throws NullPointerException if addr is null
507 public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr) {
508 return prefix6Factory.newInstance(addressStringV6(addr) + "/128");
512 * Create a Ipv6Prefix by combining the address with a mask. The address
513 * bytes are interpreted as an address and the specified mask is concatenated to
514 * it. The address bytes are not masked.
516 * @param addr Input address
517 * @param mask Prefix mask
518 * @return An Ipv6Prefix object
519 * @throws IllegalArgumentException if addr is not an Inet6Address or if mask is not in range 0-128
520 * @throws NullPointerException if addr is null
522 public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr, final int mask) {
523 checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
524 return prefix6Factory.newInstance(addressStringV6(addr) + '/' + mask);
527 public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr) {
528 return prefix6Factory.newInstance(stripZone(ipv6AddressString(requireAddress(addr))) + "/128");
531 public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr, final int mask) {
532 return newIpv6Prefix(stripZone(ipv6AddressString(requireAddress(addr))), mask);
535 public final @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr) {
536 return prefix6Factory.newInstance(ipv6AddressString(requireAddress(addr)) + "/128");
539 public final @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr, final int mask) {
540 return newIpv6Prefix(ipv6AddressString(requireAddress(addr)), mask);
543 public final @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] address, final int mask) {
544 return ipv6PrefixForShort(address, 0, mask);
547 public final @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] array, final int startOffset,
550 // Easy case, reuse the template
551 return prefix6Factory.getTemplate();
554 checkArgument(mask > 0 && mask <= 128, "Invalid mask %s", mask);
555 final int size = mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1);
557 // Until we can instantiate an IPv6 address for a partial array, use a temporary buffer
558 byte[] tmp = new byte[Ipv6Utils.INET6_LENGTH];
559 System.arraycopy(array, startOffset, tmp, 0, size);
560 return ipv6PrefixFor(tmp, mask);
563 private Ipv6Prefix newIpv6Prefix(final String addr, final int mask) {
564 checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
565 return prefix6Factory.newInstance(addr + '/' + mask);
568 public final @NonNull Entry<Ipv6AddressNoZone, Integer> splitIpv6Prefix(final @NonNull Ipv6Prefix prefix) {
569 return splitPrefix(address6NoZoneFactory, ipv6PrefixString(prefix));
572 private static <T> @NonNull T prefixToAddress(final StringValueObjectFactory<T> factory, final String str) {
573 return factory.newInstance(str.substring(0, str.lastIndexOf('/')));
576 private static <T> @NonNull Entry<T, Integer> splitPrefix(final StringValueObjectFactory<T> factory,
578 final int slash = str.lastIndexOf('/');
579 return new SimpleImmutableEntry<>(factory.newInstance(str.substring(0, slash)),
580 Integer.valueOf(str.substring(slash + 1)));
583 public final byte @NonNull[] ipv6PrefixToBytes(final @NonNull Ipv6Prefix prefix) {
584 final String str = ipv6PrefixString(prefix);
585 final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH + 1];
586 final int slash = str.lastIndexOf('/');
587 Ipv6Utils.fillIpv6Bytes(bytes, str, slash);
588 bytes[Ipv6Utils.INET6_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
592 private static @NonNull String addressStringV4(final InetAddress addr) {
593 requireAddress(addr);
594 checkArgument(addr instanceof Inet4Address, "Address has to be an Inet4Address");
595 return addr.getHostAddress();
598 private static String addressStringV6(final byte @NonNull[] bytes) {
599 checkArgument(bytes.length == Ipv6Utils.INET6_LENGTH, "IPv6 address length is 16 bytes");
602 return addressStringV6(Inet6Address.getByAddress(null, bytes, null));
603 } catch (UnknownHostException e) {
604 throw new IllegalArgumentException(String.format("Invalid input %s", bytes), e);
608 private static String addressStringV6(final InetAddress addr) {
609 requireAddress(addr);
610 checkArgument(addr instanceof Inet6Address, "Address has to be an Inet6Address");
611 return addressStringV6((Inet6Address) addr);
614 private static String addressStringV6(final Inet6Address addr) {
615 return InetAddresses.toAddrString(addr);
618 private static String prefixStringV4(final byte @NonNull[] bytes) {
619 final StringBuilder sb = new StringBuilder(18);
620 Ipv4Utils.appendIpv4String(sb, bytes);
621 return sb.append("/32").toString();
624 private static String prefixStringV4(final byte @NonNull[] bytes, final int mask) {
625 checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
627 final StringBuilder sb = new StringBuilder(18);
628 Ipv4Utils.appendIpv4String(sb, bytes);
629 return sb.append('/').append(mask).toString();
632 private @NonNull Ipv4Prefix v4PrefixForShort(final byte @NonNull[] array, final int startOffset, final int size,
634 if (startOffset == 0 && size == Ipv4Utils.INET4_LENGTH && array.length == Ipv4Utils.INET4_LENGTH) {
635 // Easy case, fall back to non-short
636 return ipv4PrefixFor(array, mask);
639 final StringBuilder sb = new StringBuilder(18);
642 sb.append(Byte.toUnsignedInt(array[startOffset]));
643 for (int i = 1; i < size; i++) {
644 sb.append('.').append(Byte.toUnsignedInt(array[startOffset + i]));
648 for (int i = size; i < Ipv4Utils.INET4_LENGTH; i++) {
653 checkArgument(mask > 0 && mask <= 32, "Invalid mask %s", mask);
654 sb.append('/').append(mask);
656 return prefix4Factory.newInstance(sb.toString());
659 private @NonNull Ipv6Address coerceIpv6Address(final @NonNull IpAddress addr) {
660 final var ret = maybeIpv6Address(addr);
661 checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);
665 private @NonNull Ipv6AddressNoZone coerceIpv6AddressNoZone(final @NonNull IpAddressNoZone addr) {
666 final var ret = maybeIpv6AddressNoZone(addr);
667 checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);