docs: public static PasswordSpec parse(String spec) {
          char[] ca = spec.toCharArray();
          int len = ca.length;
          illegalIf(0 == len, spec);
          Builder builder = new Builder();
          StringBuilder minBuf = new StringBuilder();
          StringBuilder maxBuf = new StringBuilder();
          boolean lenSpecStart = false;
          boolean minPart = false;
          for (int i = 0; i < len; ++i) {
              char c = ca[i];
              switch (c) {
                  case SPEC_LOWERCASE:
                      illegalIf(lenSpecStart, spec);
                      builder.requireLowercase();
                      break;
                  case SPEC_UPPERCASE:
                      illegalIf(lenSpecStart, spec);
                      builder.requireUppercase();
                      break;
                  case SPEC_SPECIAL_CHAR:
                      illegalIf(lenSpecStart, spec);
                      builder.requireSpecialChar();
                      break;
                  case SPEC_LENSPEC_START:
                      lenSpecStart = true;
                      minPart = true;
                      break;
                  case SPEC_LENSPEC_CLOSE:
                      illegalIf(minPart, spec);
                      lenSpecStart = false;
                      break;
                  case SPEC_LENSPEC_SEP:
                      minPart = false;
                      break;
                  case SPEC_DIGIT:
                      if (!lenSpecStart) {
                          builder.requireDigit();
                      } else {
                          if (minPart) {
                              minBuf.append(c);
                          } else {
                              maxBuf.append(c);
                          }
                      }
                      break;
                  default:
                      illegalIf(!lenSpecStart || !isDigit(c), spec);
                      if (minPart) {
                          minBuf.append(c);
                      } else {
                          maxBuf.append(c);
                      }
              }
          }
          illegalIf(lenSpecStart, spec);
          if (minBuf.length() != 0) {
              builder.minLength(Integer.parseInt(minBuf.toString()));
          }
          if (maxBuf.length() != 0) {
              builder.maxLength(Integer.parseInt(maxBuf.toString()));
          }
          return builder;
      }