code: static IpFamily detectFamily(String ipString) {
      boolean hasColon = false;
      boolean hasDot = false;
      for (int i = 0, length = ipString.length(); i < length; i++) {
        char c = ipString.charAt(i);
        if (c == '.') {
          hasDot = true;
        } else if (c == ':') {
          if (hasDot) return IpFamily.Unknown; // Colons must not appear after dots.
          hasColon = true;
        } else if (notHex(c)) {
          return IpFamily.Unknown; // Everything else must be a decimal or hex digit.
        }
      }
  
      // Now decide which address family to parse.
      if (hasColon) {
        if (hasDot) {
          int lastColonIndex = ipString.lastIndexOf(':');
          if (!isValidIpV4Address(ipString, lastColonIndex + 1, ipString.length())) {
            return IpFamily.Unknown;
          }
          if (lastColonIndex == 1 && ipString.charAt(0) == ':') {// compressed like ::1.2.3.4
            return IpFamily.IPv4Embedded;
          }
          if (lastColonIndex != 6 || ipString.charAt(0) != ':' || ipString.charAt(1) != ':') {
            return IpFamily.Unknown;
          }
          for (int i = 2; i < 6; i++) {
            char c = ipString.charAt(i);
            if (c != 'f' && c != 'F' && c != '0') return IpFamily.Unknown;
          }
          return IpFamily.IPv4Embedded;
        }
        return IpFamily.IPv6;
      } else if (hasDot && isValidIpV4Address(ipString, 0, ipString.length())) {
        return IpFamily.IPv4;
      }
      return IpFamily.Unknown;
    }
docs: Adapted from code in {@code com.google.common.net.InetAddresses.ipStringToBytes}. This version
  separates detection from parsing and checks more carefully about embedded addresses.