io_nats_client_support - RichardHightower/jnats GitHub Wiki
ServerVersion
The ServerVersion class is a public class that implements the Comparable interface. It represents a server version and allows for comparisons between different server versions.
public int compareTo(ServerVersion o)
@Override
public int compareTo(ServerVersion o) {
int c = major.compareTo(o.major);
if (c == 0) {
c = minor.compareTo(o.minor);
if (c == 0) {
c = patch.compareTo(o.patch);
if (c == 0) {
if (extra == null) {
c = o.extra == null ? 0 : 1;
} else if (o.extra == null) {
c = -1;
} else {
c = extra.compareTo(o.extra);
}
}
}
}
return c;
}The compareTo method in the ServerVersion class is used to compare two ServerVersion objects based on their properties such as major version, minor version, patch version, and extra information.
Here is a step-by-step description of what the compareTo method does:
- Compares the
majorproperty of the currentServerVersionobject to themajorproperty of theoobject (passed as an argument to the method) using thecompareTomethod. The result is stored in the variablec. - If
cis equal to 0 (indicating that the major versions are equal), the method proceeds to compare theminorproperty of both objects using thecompareTomethod. The result is again stored in the variablec. - If
cis equal to 0 (indicating that the minor versions are equal), the method compares thepatchproperty of both objects using thecompareTomethod. The result is again stored in the variablec. - If
cis equal to 0 (indicating that the patch versions are equal), the method checks if theextraproperty of the current object isnull. If it isnull, the method checks if theextraproperty of theoobject is alsonull. If both arenull, the method setscto 0. Otherwise, it setscto 1. - If
cis not equal to 0 (indicating that the extra strings are different), the method checks if theo.extraproperty isnull. If it isnull, the method setscto -1. Otherwise, it proceeds to compare theextraproperty of both objects using thecompareTomethod. - Finally, the method returns the value of
c, which represents the result of the comparison.
In summary, the compareTo method compares two ServerVersion objects based on their major, minor, patch versions, and extra information. It returns 0 if the objects are equal, a positive integer if the current object is greater than the argument object, and a negative integer if the current object is less than the argument object.
The compareTo method in the ServerVersion class is used to compare two ServerVersion objects. It compares the major, minor, and patch versions of the two objects sequentially.
The method first compares the major versions of the two objects using the compareTo method of the major version. If the major versions are equal, it moves on to compare the minor versions. If the minor versions are also equal, it compares the patch versions.
If the patch versions are equal as well, it checks if the extra field of one object is null. If the extra field is null, it considers the other object as greater (returns 1). If the extra field of the other object is null, it considers the current object as greater (returns -1). If both extra fields are not null, it compares them using the compareTo method of the extra field.
Finally, the method returns the value of c, which represents the comparison result. A negative value indicates that the current object is less than the given object, a positive value indicates it is greater, and a zero value indicates they are equal.

Status
The Status class is a public class that represents the status of a certain process or entity. Its primary purpose is to provide information about the current state or condition of the process or entity it represents. With its various methods and attributes, the Status class allows software engineers to easily track and manage the status of different processes within their applications.
private static int extractCode(Token codeToken) {
try {
return Integer.parseInt(codeToken.getValue());
} catch (Exception e) {
throw new IllegalArgumentException(NatsConstants.INVALID_HEADER_STATUS_CODE);
}
}The extractCode method is used to extract an integer value from a Token object. The method takes a single parameter codeToken, which represents the token containing the code value.
Here is a step-by-step description of what the extractCode method is doing based on its body:
-
The method is declared as
privateandstatic, indicating that it can only be accessed within theio.nats.client.support.Statusclass and does not require an instance of the class to be called. -
The method signature specifies that the return type of the method is
int, indicating that the method will return an integer value. -
Within a
tryblock, the method attempts to parse the value of thecodeTokenby calling thegetValuemethod on it, and then converting the returned value to an integer using theInteger.parseIntmethod. -
If the parsing succeeds, the parsed integer value is returned as the result of the method.
-
If an exception occurs during parsing, for example, if the value of the
codeTokenis not a valid integer, the method catches the exception. -
In the catch block, an
IllegalArgumentExceptionis thrown with the messageNatsConstants.INVALID_HEADER_STATUS_CODE. This indicates that the code value could not be extracted due to an invalid format.
That's a step-by-step description of the extractCode method in the io.nats.client.support.Status class.
The method extractCode is a private static method defined in the class io.nats.client.support.Status.
It takes a parameter codeToken of type Token and returns an integer.
The purpose of this method is to extract the code value from the codeToken and convert it into an integer.
If an exception occurs during the conversion process, it throws an IllegalArgumentException with the message "Invalid header status code defined in NatsConstants class".

JwtUtils
The JwtUtils class is an abstract class that implements ADR-14.
public static String issueUserJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, UserClaim nats) throws GeneralSecurityException, IOException
public static String issueUserJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, UserClaim nats) throws GeneralSecurityException, IOException {
// Validate the signingKey:
if (signingKey.getType() != NKey.Type.ACCOUNT) {
throw new IllegalArgumentException("issueUserJWT requires an account key for the signingKey parameter, but got " + signingKey.getType());
}
// Validate the accountId:
NKey accountKey = NKey.fromPublicKey(nats.issuerAccount.toCharArray());
if (accountKey.getType() != NKey.Type.ACCOUNT) {
throw new IllegalArgumentException("issueUserJWT requires an account key for the accountId parameter, but got " + accountKey.getType());
}
// Validate the publicUserKey:
NKey userKey = NKey.fromPublicKey(publicUserKey.toCharArray());
if (userKey.getType() != NKey.Type.USER) {
throw new IllegalArgumentException("issueUserJWT requires a user key for the publicUserKey, but got " + userKey.getType());
}
String accSigningKeyPub = new String(signingKey.getPublicKey());
String claimName = Validator.nullOrEmpty(name) ? publicUserKey : name;
return issueJWT(signingKey, publicUserKey, claimName, expiration, issuedAt, accSigningKeyPub, nats);
}The issueUserJWT method is defined as follows:
public static String issueUserJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, UserClaim nats) throws GeneralSecurityException, IOException {
// Validate the signingKey:
if (signingKey.getType() != NKey.Type.ACCOUNT) {
throw new IllegalArgumentException("issueUserJWT requires an account key for the signingKey parameter, but got " + signingKey.getType());
}
// Validate the accountId:
NKey accountKey = NKey.fromPublicKey(nats.issuerAccount.toCharArray());
if (accountKey.getType() != NKey.Type.ACCOUNT) {
throw new IllegalArgumentException("issueUserJWT requires an account key for the accountId parameter, but got " + accountKey.getType());
}
// Validate the publicUserKey:
NKey userKey = NKey.fromPublicKey(publicUserKey.toCharArray());
if (userKey.getType() != NKey.Type.USER) {
throw new IllegalArgumentException("issueUserJWT requires a user key for the publicUserKey, but got " + userKey.getType());
}
String accSigningKeyPub = new String(signingKey.getPublicKey());
String claimName = Validator.nullOrEmpty(name) ? publicUserKey : name;
return issueJWT(signingKey, publicUserKey, claimName, expiration, issuedAt, accSigningKeyPub, nats);
}The steps carried out by this method, based on its body, are as follows:
-
Validate the
signingKeyparameter to ensure that it is of typeNKey.Type.ACCOUNT. If it is not, throw anIllegalArgumentExceptionwith a message indicating the incorrect type. -
Validate the
accountIdparameter by converting it to anNKeyobject usingNKey.fromPublicKey. Ensure that the resulting key has a type ofNKey.Type.ACCOUNT. If it does not, throw anIllegalArgumentExceptionwith a message indicating the incorrect type. -
Validate the
publicUserKeyparameter by converting it to anNKeyobject usingNKey.fromPublicKey. Ensure that the resulting key has a type ofNKey.Type.USER. If it does not, throw anIllegalArgumentExceptionwith a message indicating the incorrect type. -
Convert the
signingKey's public key to aStringusingnew String(signingKey.getPublicKey()). -
Set the
claimNamevariable based on the value of thenameparameter. If thenameparameter is null or empty, use the value ofpublicUserKeyas theclaimName. -
Call the
issueJWTmethod, passing in thesigningKey,publicUserKey,claimName,expiration,issuedAt,accSigningKeyPub, andnatsparameters. -
Return the result of the
issueJWTmethod as the output of theissueUserJWTmethod.
Note: The issueJWT method is not included in the provided code snippet.
The issueUserJWT method in the JwtUtils class is responsible for generating a JSON Web Token (JWT) for a user.
Here's a breakdown of what the method does:
-
It first validates the
signingKeyparameter to ensure that it is of typeNKey.Type.ACCOUNT. If not, it throws anIllegalArgumentException. -
It then validates the
accountIdparameter by converting it to anNKeyobject and checking if it is of typeNKey.Type.ACCOUNT. If not, it throws anIllegalArgumentException. -
Next, it validates the
publicUserKeyparameter by converting it to anNKeyobject and checking if it is of typeNKey.Type.USER. If not, it throws anIllegalArgumentException. -
The method then generates the public key of the signing key as a string.
-
It determines the
claimNamefor the JWT by checking if thenameparameter is null or empty. If so, it uses thepublicUserKeyas the claim name, otherwise it uses thenameparameter. -
Finally, it calls the
issueJWTmethod, passing in the necessary parameters, to issue the JWT and returns the generated token.
Note: The method may throw GeneralSecurityException or IOException if there are any issues during the JWT generation process.

public static String issueJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, String accSigningKeyPub, JsonSerializable nats) throws GeneralSecurityException, IOException
public static String issueJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, String accSigningKeyPub, JsonSerializable nats) throws GeneralSecurityException, IOException {
Claim claim = new Claim();
claim.exp = expiration;
claim.iat = issuedAt;
claim.iss = accSigningKeyPub;
claim.name = name;
claim.sub = publicUserKey;
claim.nats = nats;
// Issue At time is stored in unix seconds
String claimJson = claim.toJson();
// Compute jti, a base32 encoded sha256 hash
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] encoded = sha256.digest(claimJson.getBytes(StandardCharsets.UTF_8));
claim.jti = new String(base32Encode(encoded));
claimJson = claim.toJson();
// all three components (header/body/signature) are base64url encoded
String encBody = toBase64Url(claimJson);
// compute the signature off of header + body (. included on purpose)
byte[] sig = (ENCODED_CLAIM_HEADER + "." + encBody).getBytes(StandardCharsets.UTF_8);
String encSig = toBase64Url(signingKey.sign(sig));
// append signature to header and body and return it
return ENCODED_CLAIM_HEADER + "." + encBody + "." + encSig;
}The issueJWT method, defined in the io.nats.client.support.JwtUtils class, is responsible for issuing a JSON Web Token (JWT) based on the provided parameters.
public static String issueJWT(NKey signingKey, String publicUserKey, String name, Duration expiration, long issuedAt, String accSigningKeyPub, JsonSerializable nats) throws GeneralSecurityException, IOException-
signingKey: NKey object representing the private key used for signing the JWT. -
publicUserKey: String representing the public key of the user. -
name: String representing the name associated with the JWT. -
expiration: Duration object representing the time duration for which the JWT is valid. -
issuedAt: long representing the timestamp when the JWT was issued. -
accSigningKeyPub: String representing the public key of the account signing key. -
nats: JsonSerializable object representing additional data associated with the JWT.
The method returns a String representing the issued JWT.
The issueJWT method follows the following steps to issue the JWT:
- Create a new
Claimobject. - Set the
expiration,issuedAt,accSigningKeyPub,name,publicUserKey, andnatsfields of theClaimobject based on the provided parameters. - Convert the
Claimobject to a JSON string using thetoJsonmethod and store it in theclaimJsonvariable. - Compute the SHA-256 hash of the
claimJsonstring and encode it using base32 encoding. Set the result as thejtifield of theClaimobject. - Convert the
Claimobject to JSON string again and update theclaimJsonvariable with the updated JSON string. - Encode the
claimJsonstring using base64url encoding and store it in theencBodyvariable. - Concatenate the
ENCODED_CLAIM_HEADER,".", andencBodyand convert it to bytes using UTF-8 encoding. Store the result in thesigvariable. - Sign the
sigbytes using thesigningKeyand encode the resulting signature using base64url encoding. Store the result in theencSigvariable. - Concatenate the
ENCODED_CLAIM_HEADER,".",encBody,".", andencSigto form the final JWT. - Return the final JWT.
Note: The values of ENCODED_CLAIM_HEADER and base32Encode methods are not provided in the given code snippet.
The issueJWT method in the JwtUtils class is responsible for generating a JSON Web Token (JWT) using the provided input parameters.
Here's a breakdown of what the method does:
-
The method takes in a
signingKey,publicUserKey,name,expiration,issuedAt,accSigningKeyPub, andnatsparameter. These parameters are used to create the claims for the JWT. -
A new
Claimobject is created and the input parameters are assigned to the respective claim fields. -
The
claimJsonis generated by converting theClaimobject to JSON. -
The
jticlaim field is computed by creating a SHA-256 hash of theclaimJsonand encoding it in base32. -
The
claimJsonis converted to base64url encoding. -
The signature (
encSig) is computed by signing the concatenation of the encoded claim header, encoded claim body, and a dot delimiter using thesigningKey. -
The JWT is constructed by concatenating the encoded claim header, encoded claim body, and encoded signature with dot delimiters.
-
Finally, the generated JWT is returned.
This method is used to issue a JWT with the provided claims and is typically used for authentication and authorization purposes in a distributed system.

NatsJetStreamClientError
The NatsJetStreamClientError class is a public class that represents an error that can occur when using the NATS JetStream client. This class is used to handle and manage error conditions specific to the JetStream functionality of the NATS messaging system.
private RuntimeException _instance(String msg) {
if (kind == KIND_ILLEGAL_ARGUMENT) {
return new IllegalArgumentException(msg);
}
return new IllegalStateException(msg);
}The _instance method defined in the NatsJetStreamClientError class in the io.nats.client.support package is responsible for creating and returning a RuntimeException based on the provided message.
Here is a step-by-step description of what the _instance method does:
-
The method takes a single parameter
msg, which represents the error message that will be included in the created exception object. -
The method first checks the value of the
kindvariable. -
If the value of
kindisKIND_ILLEGAL_ARGUMENT, the method creates a newIllegalArgumentExceptioninstance with the providedmsgas the error message. -
If the value of
kindis notKIND_ILLEGAL_ARGUMENT, the method creates a newIllegalStateExceptioninstance with the providedmsgas the error message. -
The created exception object is then returned by the method.
Note: The exact implementation of KIND_ILLEGAL_ARGUMENT and the declaration of kind are not shown in the provided code snippet, so the behavior of the method may vary depending on the actual values and logic in the code.
The _instance method, defined in the NatsJetStreamClientError class of the io.nats.client.support package, is a private method that returns a RuntimeException based on the given message parameter.
If the kind variable is equal to KIND_ILLEGAL_ARGUMENT, it creates and returns an IllegalArgumentException with the given message. Otherwise, it creates and returns an IllegalStateException with the given message.

JsonValue
The JsonValue class is a public class in Java that implements the JsonSerializable interface. It represents a value in JSON format and provides methods to serialize and deserialize JSON objects. This class is commonly used in software engineering for handling JSON data in applications.
public String toJson()
@Override
public String toJson() {
switch(type) {
case STRING:
return valueString(string);
case BOOL:
return valueString(bool);
case MAP:
return valueString(map);
case ARRAY:
return valueString(array);
case INTEGER:
return i.toString();
case LONG:
return l.toString();
case DOUBLE:
return d.toString();
case FLOAT:
return f.toString();
case BIG_DECIMAL:
return bd.toString();
case BIG_INTEGER:
return bi.toString();
default:
return NULL_STR;
}
}The toJson() method in the JsonValue class, defined in the io.nats.client.support package, converts the value of an object to its respective JSON representation. It does this by switching on the type of the object, and returning the JSON representation based on the type.
Here is a step-by-step breakdown of what the toJson() method does:
- Start of the method
toJson(). - Switch on the
typeof the object. - If the
typeisSTRING, return the JSON representation of thestringvalue using the helper methodvalueString(string). - If the
typeisBOOL, return the JSON representation of theboolvalue using the helper methodvalueString(bool). - If the
typeisMAP, return the JSON representation of themapvalue using the helper methodvalueString(map). - If the
typeisARRAY, return the JSON representation of thearrayvalue using the helper methodvalueString(array). - If the
typeisINTEGER, return thetoString()representation of theivalue. - If the
typeisLONG, return thetoString()representation of thelvalue. - If the
typeisDOUBLE, return thetoString()representation of thedvalue. - If the
typeisFLOAT, return thetoString()representation of thefvalue. - If the
typeisBIG_DECIMAL, return thetoString()representation of thebdvalue. - If the
typeisBIG_INTEGER, return thetoString()representation of thebivalue. - If none of the above cases match, return the string representation of
NULL_STR. - End of the
toJson()method.
Note that the valueString() helper method is used for converting certain types such as string, bool, map, and array to their respective JSON representations.
This is a high-level overview of what the toJson() method in the JsonValue class does based on its body. The exact functionality and behavior may depend on the implementation and usage of the JsonValue class and its dependencies.
The toJson method in the JsonValue class is used to convert the current instance of JsonValue into a JSON string representation.
Based on the implementation, the method performs a switch statement on the type of the JsonValue. Depending on the type, it returns the JSON representation of the corresponding value.
If the type is STRING, it returns the JSON representation of the string value. If the type is BOOL, it returns the JSON representation of the bool value. If the type is MAP, it returns the JSON representation of the map value. If the type is ARRAY, it returns the JSON representation of the array value.
If the type is INTEGER, LONG, DOUBLE, FLOAT, BIG_DECIMAL, or BIG_INTEGER, it returns the string representation of the respective value.
If none of the above cases match, it returns the JSON representation of null.

private String valueString(Map<String, JsonValue> map) {
StringBuilder sbo = beginJson();
for (String key : map.keySet()) {
addField(sbo, key, map.get(key));
}
return endJson(sbo).toString();
}The valueString method in the JsonValue class is used to convert a given map of key-value pairs into a JSON string. Here is a step-by-step description of what this method does:
-
Declare a
StringBuilderobject namedsboand initialize it by calling thebeginJsonmethod. This method is not defined in the given code snippet, so its implementation details are not known. -
Iterate over the keys of the
mapusing a for-each loop. For each key, do the following:a. Call the
addFieldmethod, passing in thesbostring builder, the current key, and the corresponding value from themap. TheaddFieldmethod is not defined in the given code snippet, so its implementation details are not known. -
After the iteration is complete, call the
endJsonmethod, passing in thesbostring builder. This method is not defined in the given code snippet, so its implementation details are not known. The method should finalize the creation of the JSON string. -
Convert the
sbostring builder to a string by calling thetoStringmethod. -
Return the JSON string.
Please note that without the implementation details of the beginJson, addField, and endJson methods, it is not possible to fully determine the behavior of the valueString method.
The valueString method is a private method defined in the JsonValue class within the io.nats.client.support package. It takes in a Map of type String and JsonValue as input.
The method loops through the keys of the map and for each key, it calls the addField method and passes the sbo (a StringBuilder) and the corresponding value associated with the key in the map. The addField method is responsible for appending the formatted JSON field to the sbo builder.
After iterating through all the keys in the map, the method calls the endJson method and passes the sbo builder to generate the closing part of the JSON string. The endJson method returns a StringBuilder with the complete JSON string.
Finally, the method converts the StringBuilder to a String by calling the toString method and returns the result.

private String valueString(List<JsonValue> list) {
StringBuilder sba = beginArray();
for (JsonValue v : list) {
sba.append(v.toJson());
sba.append(COMMA);
}
return endArray(sba).toString();
}The valueString method, defined in the JsonValue class in the io.nats.client.support package, takes a list of JsonValue objects as its parameter.
Here is a step-by-step description of what the valueString method does based on its body:
-
The method starts by creating a
StringBuilderobject namedsbaby calling thebeginArraymethod. ThebeginArraymethod is not shown in the provided code snippet, but it is assumed to initialize theStringBuilderwith an opening array bracket "[". -
The method then enters a loop that iterates over each
JsonValueobject in thelistparameter. -
Inside the loop, the
toJsonmethod is called on eachJsonValueobjectv. ThetoJsonmethod converts theJsonValueobject into its string representation. -
The resulting string is appended to the
sbaStringBuilderobject by calling theappendmethod. -
After appending the string representation of the
JsonValueobject, a comma (,) is also appended to thesbaStringBuilderobject by calling theappendmethod with theCOMMAconstant. -
Steps 4 and 5 are repeated for each
JsonValueobject in thelistparameter. -
Once the loop iteration is complete, the
sbaStringBuilderobject is passed to theendArraymethod. TheendArraymethod is not shown in the provided code snippet, but it is assumed to append the closing array bracket "]" to theStringBuilderand perform any necessary post-processing. -
The
endArraymethod returns thesbaStringBuilderobject as aStringby calling thetoStringmethod. -
Finally, the
valueStringmethod returns theStringrepresentation of theStringBuilderobject.
In summary, the valueString method takes a list of JsonValue objects, converts each object into its string representation, and combines them with commas to form a JSON array. The resulting JSON array string is returned as the output of the method.
The valueString method in the io.nats.client.support.JsonValue class is used to convert a list of JsonValue objects into a string representation.
It takes a List<JsonValue> as input and iterates through the elements of the list. For each JsonValue element, it appends the result of calling its toJson() method to a StringBuilder, followed by a comma.
Finally, it calls the endArray method, passing the StringBuilder as a parameter, and converts the result to a string by calling toString().
The purpose of this method is to generate a string representation of the given list of JsonValue objects, suitable for JSON serialization or other similar purposes.

Validator
The Validator class is an abstract class that provides a framework for implementing various validation logic in a software application. It serves as a base class for creating specific validator classes that can be used to validate different types of data or entities.
public static String validateSubject(String subject, String label, boolean required, boolean cantEndWithGt)
public static String validateSubject(String subject, String label, boolean required, boolean cantEndWithGt) {
if (emptyAsNull(subject) == null) {
if (required) {
throw new IllegalArgumentException(label + " cannot be null or empty.");
}
return null;
}
String[] segments = subject.split("\\.");
for (int x = 0; x < segments.length; x++) {
String segment = segments[x];
if (segment.equals(">")) {
if (cantEndWithGt || x != segments.length - 1) {
// if it can end with gt, gt must be last segment
throw new IllegalArgumentException(label + " cannot contain '>'");
}
} else if (!segment.equals("*") && notPrintable(segment)) {
throw new IllegalArgumentException(label + " must be printable characters only.");
}
}
return subject;
}The validateSubject method in class io.nats.client.support.Validator is used to validate a subject string based on certain criteria. Here is a step-by-step description of what the method does:
-
The method takes four parameters:
subject(the subject string to validate),label(a label used in error messages),required(a boolean flag indicating if the subject is required), andcantEndWithGt(a boolean flag indicating if the subject cannot end with '>'). -
The method first checks if the
subjectisnullor empty by calling theemptyAsNullhelper method. If the subject isnullor empty and is marked as required, anIllegalArgumentExceptionis thrown with an error message stating that thelabelcannot be null or empty. If the subject is not required and isnullor empty, the method returnsnull. -
If the subject is not
nullor empty, the method splits the subject into segments using the dot ('.') as the delimiter. Each segment represents a part of the subject string. -
The method then iterates over each segment in the
segmentsarray. -
For each segment, the method checks if it is equal to '>'. If it is, two conditions are checked: (a) if
cantEndWithGtistrueor if the segment is not the last segment in the subject. If either of these conditions is true, anIllegalArgumentExceptionis thrown with an error message stating that thelabelcannot contain '>'. This check is to ensure that if the subject is not allowed to end with '>', it must be the last segment. -
If the segment is not equal to '>', the method checks if it is equal to '' or if it contains any non-printable characters. The
notPrintablehelper method is used to determine if a segment contains any non-printable characters. If the segment is neither '' nor consists of only printable characters, anIllegalArgumentExceptionis thrown with an error message stating that thelabelmust be printable characters only. -
If all segments pass the validation checks, the method returns the original
subjectstring.
Overall, the validateSubject method ensures that the provided subject string meets the specified criteria, such as not being null or empty, not containing '>', and consisting of only printable characters. If any of the validation conditions fail, an IllegalArgumentException is thrown.
The validateSubject method in the Validator class is used to validate a subject string. It takes four parameters: subject, label, required, and cantEndWithGt.
The method first checks if the subject string is null or empty. If it is and the required parameter is true, it throws an IllegalArgumentException with a message indicating that the subject cannot be null or empty. If the subject is null or empty and the required parameter is false, it returns null.
Next, the method splits the subject string into segments using the dot (".") as the separator. It then iterates over each segment and performs validation checks.
If a segment equals ">", the method checks if cantEndWithGt is true or if it is the last segment in the subject. If either condition is true, it throws an IllegalArgumentException with a message indicating that the subject cannot contain ">", as it violates the validation rule.
If a segment is neither "*" nor printable, the method throws an IllegalArgumentException with a message indicating that the subject must consist of printable characters only.
Finally, if all validation checks pass, the method returns the subject string.

public static String validatePrefixOrDomain(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (s.startsWith(DOT)) {
throw new IllegalArgumentException(label + " cannot start with `.` [" + s + "]");
}
if (notPrintableOrHasWildGt(s)) {
throw new IllegalArgumentException(label + " must be in the printable ASCII range and cannot include `*`, `>` [" + s + "]");
}
return s;
});
}The validatePrefixOrDomain method, defined in the io.nats.client.support.Validator class, is used to validate a given string s as either a prefix or domain. It takes three parameters: s (the string to be validated), label (the label used in error messages), and required (a boolean indicating whether the string is required or not).
Here is the step-by-step description of what the validatePrefixOrDomain method does based on its body:
-
Call the private method
_validatewith the parameterss,required,label, and a lambda expression. This lambda expression contains the validation logic for the string. -
In the lambda expression:
- Check if the string
sstarts with a dot (.). If it does, throw anIllegalArgumentExceptionwith an error message indicating that the label cannot start with a dot. - Check if the string
sis not printable ASCII or if it contains the characters*or>. If it does, throw anIllegalArgumentExceptionwith an error message indicating that the label must be in the printable ASCII range and cannot include*or>. - If the string passes the above checks, return the string
s.
- Check if the string
-
Return the string
sfrom thevalidatePrefixOrDomainmethod.
Note: The _validate method is not described in the provided code snippet, but it can be inferred that it performs common validation logic and error handling.
The validatePrefixOrDomain method is used to validate a prefix or domain string.
The method takes three parameters: s which is the string to be validated, label which is a label to describe the string being validated, and required which is a boolean value indicating if the string is required or not.
Inside the method, the _validate function is called with the string, required flag, and label as arguments. This function performs the actual validation.
The validation checks for two conditions. First, it checks if the string starts with a dot (.). If it does, it throws an IllegalArgumentException with a message indicating that the string cannot start with a dot.
Second, it checks if the string is not printable ASCII or contains wildcard characters (* or >). If either of these conditions is true, it throws an IllegalArgumentException with a message indicating that the string must be in the printable ASCII range and cannot contain wildcard characters.
If both checks pass, the method returns the validated string.
In summary, the validatePrefixOrDomain method ensures that a given prefix or domain string meets certain criteria: it does not start with a dot and it is printable ASCII without wildcard characters.

public static String validateMustMatchIfBothSupplied(String s1, String s2, NatsJetStreamClientError err)
public static String validateMustMatchIfBothSupplied(String s1, String s2, NatsJetStreamClientError err) {
// s1 | s2 || result
// ---- | ---- || --------------
// null | null || valid, null s2
// null | y || valid, y s2
// x | null || valid, x s1
// x | x || valid, x s1
// x | y || invalid
s1 = emptyAsNull(s1);
s2 = emptyAsNull(s2);
if (s1 == null) {
// s2 can be either null or y
return s2;
}
// x / null or x / x
if (s2 == null || s1.equals(s2)) {
return s1;
}
throw err.instance();
}This method is defined in the io.nats.client.support.Validator class. It takes three parameters: s1 and s2 of type String, and err of type NatsJetStreamClientError. The purpose of this method is to validate whether s1 and s2 must match based on certain conditions.
Here is a step-by-step description of what the method does:
- Assigns the value of
s1after converting empty string to null using theemptyAsNullhelper method. - Assigns the value of
s2after converting empty string to null using theemptyAsNullhelper method. - Checks if
s1is null:- If
s1is null, it means that it is eithernullor an empty string. - Then, it checks if
s2is null or equal to "y".- If
s2is eithernullor "y", it returns the value ofs2. - This is considered a valid scenario.
- If
- If
- If
s1is not null, it means that it has a non-empty value. - Checks if
s2isnullor equal tos1:- If
s2isnullor equal tos1, it returns the value ofs1. - This is considered a valid scenario.
- If
- If none of the above conditions are met, it means that
s1ands2have different non-null, non-empty values, which is considered an invalid scenario. - Throws an instance of
NatsJetStreamClientErrorusing theerr.instance()method to indicate an invalid scenario.
The method essentially follows a set of conditions to determine whether s1 and s2 must match or not. It returns the appropriate value or throws an error based on these conditions.
The validateMustMatchIfBothSupplied method in the io.nats.client.support.Validator class is used to validate two string inputs, s1 and s2, and ensure that they match certain conditions.
The method starts by converting any empty strings to null using the emptyAsNull helper method.
The method then proceeds to check various combinations of s1 and s2 using a table:
- If both
s1ands2are null, the method returns null, indicating a valid condition. - If
s1is null ands2is not null, the method returnss2, indicating a valid condition. - If
s1is not null ands2is null ors1is equal tos2, the method returnss1, indicating a valid condition. - If none of the above conditions are met, the method throws an exception using the provided
NatsJetStreamClientErrorinstance.
In summary, this method validates s1 and s2 based on the conditions described in the table and returns the appropriate value or throws an exception.

public static String required(String s, String label) {
if (emptyAsNull(s) == null) {
throw new IllegalArgumentException(label + " cannot be null or empty.");
}
return s;
}The required method in the io.nats.client.support.Validator class is used to validate a string value and ensure that it is not null or empty. It takes two parameters:
-
s- the string value that needs to be validated. -
label- the label or name of the string value, which is used in the error message if the validation fails.
Here is a step-by-step description of what the required method is doing:
-
Check if the
sstring value is empty or null by calling theemptyAsNullmethod, which is not provided in the given code snippet. Assuming that this method returns null if the string value is empty or null and returns the original string value otherwise. -
If the result of
emptyAsNull(s)is null, it means that the string value is either empty or null, which is considered invalid. -
Throw an
IllegalArgumentExceptionwith an error message indicating that the string value specified by thelabelparameter cannot be null or empty. -
If the string value passes the validation, i.e., it is not empty or null, return the original string value.
In summary, the required method ensures that a string value is not null or empty and throws an IllegalArgumentException if it is.
The required method, defined in the io.nats.client.support.Validator class, is used to validate that a given string parameter is not null or empty.
The method takes two parameters: s, which is the string to be validated, and label, which is a label or description of the string parameter.
Inside the method, it first checks if the given string parameter is null or empty using the emptyAsNull helper method. If the string is null or empty, it throws an IllegalArgumentException with a message indicating that the string parameter cannot be null or empty, using the provided label.
If the string is not null or empty, the method simply returns the original string.
This method is useful for enforcing that a required string parameter is provided, and can be used to validate user input or ensure that necessary data is provided before continuing with further processing.

public static <T> T required(T o, String label) {
if (o == null) {
throw new IllegalArgumentException(label + " cannot be null or empty.");
}
return o;
}This method is defined in the io.nats.client.support.Validator class and is used to validate if a given object o is null or not.
The method has the following signature:
public static <T> T required(T o, String label) {
// Method body
}-
o: The object that needs to be validated. -
label: A string value representing a label or description for the objecto.
This method returns the validated object o if it is not null.
The method body checks if the object o is null using the condition o == null. If the condition evaluates to true, it throws an IllegalArgumentException with an error message formatted as "{label} cannot be null or empty.", where {label} is the value passed as the label parameter.
If the object o is not null, it directly returns the object o.
String text = "Sample Text";
String validatedText = Validator.required(text, "Text");
// The value of 'validatedText' will be "Sample Text"In the above example, the required() method is used to validate if the text object is null or not. Since the text object is not null, it is returned as the validated object.
The required method in the io.nats.client.support.Validator class is a static method that takes two parameters: an object of type T (o) and a String (label).
This method is used to check if the object o is null. If o is null, the method throws an IllegalArgumentException with a descriptive message indicating that the label (provided as a parameter) cannot be null or empty.
Otherwise, if o is not null, the method simply returns the object o.
This method is typically used to validate that a required parameter or argument in a method call is provided, and it serves as a convenient way to enforce a non-null value.

public static String _validate(String s, boolean required, String label, Check check) {
if (emptyAsNull(s) == null) {
if (required) {
throw new IllegalArgumentException(label + " cannot be null or empty.");
}
return null;
}
return check.check();
}The method _validate in the class io.nats.client.support.Validator performs the following steps:
-
The method takes four parameters:
-
s: A string to be validated. -
required: A boolean value indicating whether the string is required. -
label: A string label for the parameter being validated. -
check: An instance of theCheckfunctional interface which provides acheckmethod to be executed.
-
-
If the string
sis empty or null (determined by theemptyAsNullmethod), the following actions are taken:- If
requiredistrue, anIllegalArgumentExceptionis thrown with a message indicating that thelabelcannot be null or empty. - If
requiredisfalse,nullis returned.
- If
-
If the string
sis not empty or null, thecheck.check()method is called. The purpose of this method is not specified in the given code snippet, but it is expected to perform some kind of validation or processing on the provided string. The return value of thecheckmethod is then returned from the_validatemethod.
Note: The implementation of the emptyAsNull method and the exact behavior of the check method are not available in the provided code snippet, so further analysis would be required to understand their functionality.
The _validate method is a static method defined in the Validator class in the io.nats.client.support package.
This method takes four parameters:
-
String s- the value to be validated -
boolean required- specifies whether the value is required or not -
String label- a label for the value being validated (used for error messages) -
Check check- an instance of theCheckinterface, which is responsible for performing the actual validation logic
The purpose of this method is to validate a given value based on the specified requirements.
First, it checks if the value is empty or null by invoking the emptyAsNull method (which is not shown in the provided code). If the value is empty or null and it is marked as required, it throws an IllegalArgumentException with an appropriate error message.
If the value is not empty or null, it then calls the check.check() method, which is responsible for performing the actual validation logic. The return value of this method is then returned by the _validate method.
Overall, this method provides a reusable way to validate a value based on the specified requirements and perform custom validation logic using the Check interface.

public static String validateMaxLength(String s, int maxLength, boolean required, String label) {
return _validate(s, required, label, () -> {
int len = s.getBytes(StandardCharsets.UTF_8).length;
if (len > maxLength) {
throw new IllegalArgumentException(label + " cannot be longer than " + maxLength + " bytes but was " + len + " bytes");
}
return s;
});
}The validateMaxLength method in the io.nats.client.support.Validator class is used to validate a string against a maximum length. Here is a step-by-step description of what the method does:
-
The method takes four parameters:
-
s- the string to be validated -
maxLength- the maximum length allowed for the string -
required- a boolean value indicating if the string is required or not -
label- a label to identify the string in case of an error message
-
-
The method calls the
_validatemethod, passing thes,required,label, and a lambda expression as parameters. The lambda expression is used to define the validation logic. -
Inside the lambda expression, the method calculates the length of the string in bytes using the UTF-8 character encoding. The
getBytesmethod is used to convert the string to a byte array, and thelengthproperty of the byte array is then used to get the length in bytes. -
If the length of the string is greater than the
maxLengthparameter, anIllegalArgumentExceptionis thrown. The exception message includes thelabel,maxLength, and the actual length of the string in bytes. -
If the string passes the length validation, it is returned as the result of the method.
In summary, the validateMaxLength method checks if a given string exceeds a maximum length in bytes. It throws an exception if the length is exceeded and returns the string if it is within the allowed length.
The validateMaxLength method, defined in the Validator class in the io.nats.client.support package, is used to validate if a given string s is not longer than a specified maxLength in bytes.
The method takes four parameters:
-
s: The string to be validated. -
maxLength: The maximum allowed length of the string in bytes. -
required: A boolean value indicating whether the string is required or not. -
label: A label to identify the string being validated.
Internally, the method calculates the length of the string s in bytes using the UTF-8 character encoding. If the length exceeds the maxLength, the method throws an IllegalArgumentException with an error message indicating the violation.
If the string passes the validation, it is returned unchanged.
Overall, validateMaxLength provides a convenient way to validate the maximum length of a string in bytes while considering the UTF-8 encoding.

public static String validatePrintable(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notPrintable(s)) {
throw new IllegalArgumentException(label + " must be in the printable ASCII range [" + s + "]");
}
return s;
});
}The validatePrintable method, defined in the io.nats.client.support.Validator class, is responsible for validating a given string s based on its printability in the ASCII range. It takes three parameters: the string to validate s, a label for the string label, and a boolean flag indicating whether the string is required or not required.
Here's a step-by-step breakdown of what the method is doing:
-
The method delegates the actual validation to the
_validatemethod, passing in the strings, the boolean flagrequired, the string labellabel, and a lambda expression. -
The lambda expression
() -> { ... }defines an inline function that is executed within the_validatemethod. -
Within the lambda expression, the method first checks if the string
sis not printable by calling thenotPrintablefunction. If the string is not printable, anIllegalArgumentExceptionis thrown. The exception message includes the label and the actual string value. -
If the string is printable, the method returns the original string
s.
Overall, the validatePrintable method ensures that a given string is within the printable ASCII range and throws an exception if it is not.
The validatePrintable method in the Validator class is a public static method that takes three parameters:
-
s- a String that needs to be validated -
label- a String representing the label of the value being validated -
required- a boolean indicating if the value is required to be non-null and non-empty
The purpose of this method is to validate that the provided s parameter contains only printable ASCII characters. If the s parameter contains any characters that are not within the printable ASCII range, an IllegalArgumentException is thrown with an error message indicating the violation.
The underlying implementation of this method involves calling a private method _validate from within the validatePrintable method, passing in the necessary parameters. This private method handles the common validation logic for various types of validations and returns the validated s parameter if it passes all the validation checks.

public static String validatePrintableExceptWildDotGt(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notPrintableOrHasWildGtDot(s)) {
throw new IllegalArgumentException(label + " must be in the printable ASCII range and cannot include `*`, `.` or `>` [" + s + "]");
}
return s;
});
}The validatePrintableExceptWildDotGt method is a static method defined in the Validator class located in the io.nats.client.support package. It takes three parameters: String s, String label, and boolean required. It returns a String.
Here is a step-by-step description of what this method does:
-
It calls the
_validatemethod passing in thesparameter,requiredparameter,labelparameter, and a lambda expression as arguments. This method is responsible for performing the actual validation and throwing an exception if the validation fails. -
Inside the lambda expression, it checks whether the
sstring is not in the printable ASCII range or contains the characters*,., or>. This check is done using thenotPrintableOrHasWildGtDotmethod. -
If the check in step 2 fails, it throws an
IllegalArgumentExceptionwith a message that includes thelabel, the invalid strings, and a description of the invalid characters. -
If the check in step 2 passes, it returns the original string
s.
Overall, this method is used to validate a string s to ensure that it is in the printable ASCII range and does not contain the characters *, ., or >. If the validation fails, an exception is thrown.
The method validatePrintableExceptWildDotGt in the class Validator is used to validate a string s to ensure that it is in the printable ASCII range and does not include the characters *, ., or >.
If the string s is not printable or contains any of the prohibited characters, an IllegalArgumentException is thrown with a message indicating the invalid characters found in the string.
Otherwise, the method returns the validated string s.

public static String validatePrintableExceptWildDotGtSlashes(String s, String label, boolean required)
public static String validatePrintableExceptWildDotGtSlashes(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notPrintableOrHasWildGtDotSlashes(s)) {
throw new IllegalArgumentException(label + " must be in the printable ASCII range and cannot include `*`, `.`, `>`, `\\` or `/` [" + s + "]");
}
return s;
});
}The validatePrintableExceptWildDotGtSlashes method is defined in the io.nats.client.support.Validator class. This method is used to validate a string and ensure that it only contains printable ASCII characters, except for the characters *, ., >, \, or /.
public static String validatePrintableExceptWildDotGtSlashes(String s, String label, boolean required)-
s: The string to be validated -
label: The label or name of the string being validated -
required: A boolean flag indicating whether the string is required or not
- The validated string
s
The method call _validate(s, required, label, () -> {...}) is used to perform the validation. It uses a lambda expression to define the validation logic.
The validation logic checks if the string s is not printable or contains any of the following characters: *, ., >, \, or /. If the validation fails, an IllegalArgumentException is thrown with an error message that includes the label and the invalid string. Otherwise, the method returns the validated string s.
Example error message:
[label] must be in the printable ASCII range and cannot include `*`, `.`, `>`, `\` or `/` [invalidString]
-
IllegalArgumentException: Thrown if the validation fails
The validatePrintableExceptWildDotGtSlashes method is a static method defined in the Validator class within the io.nats.client.support package. This method takes three parameters: s, label, and required.
The purpose of this method is to validate the input string s and ensure that it contains only printable ASCII characters, excluding specific characters such as *, ., >, \, and /. If the input string s contains any of these forbidden characters or is not within the printable ASCII range, an IllegalArgumentException is thrown with a descriptive message including the label and the invalid input.
The method follows a functional programming style, making use of a lambda expression to perform the actual validation. The lambda expression checks if the input string s is not printable or contains any of the forbidden characters using the notPrintableOrHasWildGtDotSlashes method. If any of these conditions are true, the validation fails and an IllegalArgumentException is thrown. Otherwise, the validated string s is returned.
Overall, the validatePrintableExceptWildDotGtSlashes method ensures that the input string s meets the required criteria of being printable while excluding specific forbidden characters.

public static String validatePrintableExceptWildGt(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notPrintableOrHasWildGt(s)) {
throw new IllegalArgumentException(label + " must be in the printable ASCII range and cannot include `*` or `>` [" + s + "]");
}
return s;
});
}The validatePrintableExceptWildGt method is defined in the io.nats.client.support.Validator class. It takes three parameters:
-
s- A string that needs to be validated. -
label- A string label that provides context to the validation process. -
required- A boolean flag that indicates whether the string is required or not.
The purpose of this method is to validate the input string s and ensure that it only contains printable characters from the ASCII range, except for the characters * and >. The validation process includes checking if the string is required and whether it meets the specified criteria.
The method calls a private method _validate to handle the validation process. Here is a step-by-step description of what happens in the method body:
-
The method delegates the validation process to the
_validatemethod, passing the input strings, therequiredflag, the providedlabel, and a lambda expression. -
The lambda expression represents the validation logic. It checks if the input string
sis not printable or contains the characters*or>. If any of these conditions are true, it throws anIllegalArgumentExceptionwith a descriptive error message that includes thelabeland the input strings. -
If the lambda expression's validation logic passes without any exceptions being thrown, the method returns the input string
s.
Overall, the validatePrintableExceptWildGt method ensures that the input string s is valid, printable, and does not contain the characters * or >. If the validation fails, it throws an exception with a detailed error message.
The method validatePrintableExceptWildGt in the Validator class is used to validate a string by checking if it contains any characters that are not within the printable ASCII range, and also if it includes the characters * or >.
The method takes three parameters: s (the string to be validated), label (a label that describes the string), and required (a boolean value indicating if the string is required).
If the string s is not printable or contains * or >, an IllegalArgumentException is thrown with a message indicating that the string must be in the printable ASCII range and cannot include * or >, along with the invalid string.
If the validation passes, the method returns the validated string s.
The method uses an underlying private method _validate to handle the common logic of validating the string and throwing an exception if necessary.

public static String validateIsRestrictedTerm(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notRestrictedTerm(s)) {
throw new IllegalArgumentException(label + " must only contain A-Z, a-z, 0-9, `-` or `_` [" + s + "]");
}
return s;
});
}This method is a static method defined in class io.nats.client.support.Validator. It takes three parameters:
-
String s: The input string that needs to be validated. -
String label: A label or name for the input string. This is used in exception messages for readability. -
boolean required: A flag indicating whether the input string is required (true) or optional (false).
The method returns a String value, which is the validated input string if it passes all the checks.
public static String validateIsRestrictedTerm(String s, String label, boolean required)- The method calls a private method
_validatewith the input strings, therequiredflag, thelabel, and a lambda expression as parameters. The lambda expression contains the actual validation logic. - Inside the lambda expression, the method checks if the input string
sis not a restricted term. If it is not a restricted term, anIllegalArgumentExceptionis thrown with a specific message indicating that the input string must only contain A-Z, a-z, 0-9,-, or_. - If the input string passes the check, it is returned as the result of the method.
Please note that the actual implementation of the _validate and notRestrictedTerm methods is not provided in the given code snippet.
The method validateIsRestrictedTerm in the class Validator is used to check if a given string contains restricted terms. It takes three parameters: s (the string to be validated), label (a descriptive label for the string), and required (a boolean indicating if the string is required or not).
The method calls a private helper method _validate passing the string, label, and required as arguments, along with a lambda expression that performs the actual validation.
Inside the lambda expression, the method checks if s is not a restricted term by calling the notRestrictedTerm function. If s is not a restricted term, an IllegalArgumentException is thrown with a message indicating that the string should only contain letters, numbers, hyphens, or underscores.
If the string passes the validation, it is returned as the result of the method.

public static String validateWildcardKvKey(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notWildcardKvKey(s)) {
throw new IllegalArgumentException(label + " must only contain A-Z, a-z, 0-9, `*`, `-`, `_`, `/`, `=`, `>` or `.` and cannot start with `.` [" + s + "]");
}
return s;
});
}This method is defined in the io.nats.client.support.Validator class and is used to validate wildcard key-value pairs.
The method takes the following parameters:
-
s(String): The key-value pair to be validated. -
label(String): The label or name of the key-value pair. -
required(boolean): Indicates whether the key-value pair is required or optional.
The method returns a String value.
The method performs the following steps:
- It calls the
_validatemethod passing thes,required,label, and a lambda expression as arguments. - Inside the lambda expression, it checks if the key-value pair does not match the required pattern by calling the
notWildcardKvKeymethod. - If the key-value pair is invalid, it throws an
IllegalArgumentExceptionwith an error message indicating the invalid characters in the key-value pair. - If the key-value pair is valid, it returns the key-value pair.
Note:
The notWildcardKvKey method is not provided in the given code snippet, so the details of its implementation are unknown. This method is likely used to check if the given key-value pair matches a specific pattern.
The validateWildcardKvKey method in the Validator class is used to validate a given string s as a wildcard key-value key.
The method takes three parameters:
-
s: The string to be validated -
label: A label used for error messages -
required: A flag indicating whether the string is required or not
The method calls a private method _validate passing in the string s, the required flag, the label, and a lambda expression. If the string s does not meet the validation criteria, an IllegalArgumentException is thrown with an appropriate error message indicating that the string must only contain certain characters and cannot start with a dot.
If the string s passes the validation, it is returned unchanged.

public static String validateNonWildcardKvKey(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (notNonWildcardKvKey(s)) {
throw new IllegalArgumentException(label + " must only contain A-Z, a-z, 0-9, `-`, `_`, `/`, `=` or `.` and cannot start with `.` [" + s + "]");
}
return s;
});
}The validateNonWildcardKvKey method within the io.nats.client.support.Validator class is responsible for validating a given key string based on specific criteria.
Here is a step-by-step description of what the method is doing:
-
The method accepts three parameters:
-
s- the key string to be validated -
label- a label to describe the key (used in exception messages) -
required- a flag indicating if the key is required or not
-
-
The method calls a private method
_validatewith the parameterss,required,label, and a lambda expression. -
Within the lambda expression, the method checks if the key string
sdoes not meet the criteria of a non-wildcard key by calling thenotNonWildcardKvKeyhelper method. If the key string does not meet the criteria, anIllegalArgumentExceptionis thrown with an informative error message. -
The error message indicates that the key must only contain letters A-Z (uppercase and lowercase), digits 0-9, hyphen (
-), underscore (_), forward slash (/), equal sign (=), or period (.). Additionally, the key cannot start with a period. The original key string that failed the validation is included in the error message. -
If the key string passes all the validation checks, it is returned as the result of the method.
Note: The implementation of the notNonWildcardKvKey method is not provided in the given code snippet. Its purpose is to determine if the key string violates the criteria for a non-wildcard key.
The validateNonWildcardKvKey method is a static method in the Validator class that takes in three parameters: a String s, a String label, and a boolean required.
This method is used to validate a non-wildcard key (s) for a key-value pair. It ensures that the key only contains valid characters and does not violate any restrictions.
If the key is found to be invalid, an IllegalArgumentException is thrown, with a detailed error message indicating the specific validation failure. If the key is deemed valid, it is returned as the output of the method.

public static int validateMaxHistory(int max) {
if (max < 1 || max > MAX_HISTORY_PER_KEY) {
throw new IllegalArgumentException("Max History must be from 1 to " + MAX_HISTORY_PER_KEY + " inclusive.");
}
return max;
}This method is defined in the class io.nats.client.support.Validator. It takes an integer parameter max and returns an integer value.
-
max(type: int): The value to be validated.
- Check if the value of
maxis less than 1 or greater than a constant valueMAX_HISTORY_PER_KEY. - If the condition in step 1 is true, throw an
IllegalArgumentExceptionwith a message stating that themaxvalue must be between 1 andMAX_HISTORY_PER_KEY, inclusive. - If the condition in step 1 is false, return the
maxvalue.
- The validated
maxvalue.
The validateMaxHistory method in the Validator class of the io.nats.client.support package is used to validate a given maximum history value.
The method takes an integer parameter max, representing the maximum history value to be validated. It checks if the value is less than 1 or greater than a constant variable MAX_HISTORY_PER_KEY. If either of these conditions is true, it throws an IllegalArgumentException with an error message stating that the maximum history must be between 1 and MAX_HISTORY_PER_KEY, inclusive.
If the input value passes the validation, it simply returns the value itself.
This method is useful in ensuring that the maximum history value provided by the caller falls within the permissible range.

public static int validateNumberOfReplicas(int replicas) {
if (replicas < 1 || replicas > 5) {
throw new IllegalArgumentException("Replicas must be from 1 to 5 inclusive.");
}
return replicas;
}The method validateNumberOfReplicas is defined in the class io.nats.client.support.Validator and is responsible for validating the number of replicas passed as an argument.
Here is a step-by-step description of what this method does based on its body:
-
The method takes an integer argument
replicas. -
It checks if the value of
replicasis less than 1 or greater than 5 using the logical OR operator (||). -
If the condition evaluates to
true, it means that the value ofreplicasis either less than 1 or greater than 5, which is invalid. In this case, anIllegalArgumentExceptionis thrown with the message "Replicas must be from 1 to 5 inclusive." This exception is used to indicate that an illegal argument has been passed to the method. -
If the condition in step 2 evaluates to
false, it means that the value ofreplicasis within the valid range of 1 to 5 inclusive. -
In this case, the method simply returns the value of
replicas.
Overall, the purpose of this method is to ensure that the number of replicas provided is within the valid range of 1 to 5. If an invalid value is detected, it throws an exception, otherwise, it returns the given replica count as is.
The method validateNumberOfReplicas, defined in the class io.nats.client.support.Validator, is used to validate the number of replicas in a system. It takes an integer argument replicas and checks if it is within the valid range of 1 to 5 (inclusive). If the replicas value is outside this range, an IllegalArgumentException is thrown with an appropriate error message. If the replicas value is valid, it is returned as the output of the method.
This method is useful to ensure that the number of replicas specified for a system is within a valid and supported range. If the replicas value is invalid, it can lead to unexpected behavior or errors in the system.

public static Duration validateDurationRequired(Duration d) {
if (d == null || d.isZero() || d.isNegative()) {
throw new IllegalArgumentException("Duration required and must be greater than 0.");
}
return d;
}Method Definition:
The validateDurationRequired method is defined in the io.nats.client.support.Validator class as a public static method.
Method Signature:
public static Duration validateDurationRequired(Duration d)
Method Description:
This method takes a Duration object as input and validates it to ensure that it is not null, not zero, and not negative.
Step-by-Step Description:
- Check if the input
Durationobject,d, is null or if it is equal to zero or if it is negative. - If any of the above conditions are true, throw an
IllegalArgumentExceptionwith the message "Duration required and must be greater than 0." - If none of the above conditions are true, return the input
Durationobject,d.
The validateDurationRequired method in the io.nats.client.support.Validator class checks if a provided Duration meets specific requirements. The method takes in a Duration object as a parameter.
If the provided Duration is null, zero, or negative, the method throws an IllegalArgumentException with the message "Duration required and must be greater than 0.". Otherwise, it returns the provided Duration.
This method is used to ensure that a valid and non-zero Duration value is provided, rejecting any invalid inputs.

public static Duration validateDurationNotRequiredGtOrEqZero(Duration d, Duration ifNull) {
if (d == null) {
return ifNull;
}
if (d.isNegative()) {
throw new IllegalArgumentException("Duration must be greater than or equal to 0.");
}
return d;
}The method validateDurationNotRequiredGtOrEqZero in the class io.nats.client.support.Validator performs the following steps:
-
Check if the input
disnull.- If
disnull, return the inputifNullduration.
- If
-
Check if the input
dis negative.- If
dis negative, throw anIllegalArgumentExceptionwith the message "Duration must be greater than or equal to 0."
- If
-
If both conditions are false, return the input
dduration.
This method is used to validate a Duration object, ensuring that it is not null and greater than or equal to 0.
The method validateDurationNotRequiredGtOrEqZero checks if a given Duration is greater than or equal to zero. If the duration is null, it returns a specified default value (ifNull). If the duration is negative, it throws an IllegalArgumentException with a descriptive error message. If the duration is valid (greater than or equal to zero), it returns the duration itself.

public static Duration validateDurationNotRequiredGtOrEqZero(long millis) {
if (millis < 0) {
throw new IllegalArgumentException("Duration must be greater than or equal to 0.");
}
return Duration.ofMillis(millis);
}This method is defined in the class io.nats.client.support.Validator and is used to validate a duration value to ensure that it is greater than or equal to zero.
public static Duration validateDurationNotRequiredGtOrEqZero(long millis)if (millis < 0) {
throw new IllegalArgumentException("Duration must be greater than or equal to 0.");
}
return Duration.ofMillis(millis);The method validateDurationNotRequiredGtOrEqZero takes a long value representing duration in milliseconds as input.
- Check if the input
millisis less than zero. - If step 1 is true, throw an
IllegalArgumentExceptionwith the message "Duration must be greater than or equal to 0." - If step 1 is false, create a
Durationobject using the value ofmillisas the duration in milliseconds. - Return the created
Durationobject.
Note: The purpose of this method is to ensure that the duration value provided is valid and meets the requirement of being greater than or equal to zero.
The validateDurationNotRequiredGtOrEqZero method is a static method defined in the Validator class in the io.nats.client.support package.
This method takes a long parameter millis representing a duration in milliseconds. It validates that the duration is not negative (i.e., greater than or equal to zero). If the duration is negative, it throws an IllegalArgumentException with the message "Duration must be greater than or equal to 0."
If the duration is valid (greater than or equal to zero), it returns a Duration object representing the specified number of milliseconds.

public static String validateNotNull(String s, String fieldName) {
if (s == null) {
throw new IllegalArgumentException(fieldName + " cannot be null");
}
return s;
}The validateNotNull method is a static method defined in the io.nats.client.support.Validator class. This method takes two parameters: a string s and a string fieldName. The purpose of this method is to validate that the provided string (s) is not null.
The method implementation starts with an if statement that checks if the s parameter is null. If it is null, an IllegalArgumentException is thrown with a message that includes the fieldName parameter. This exception indicates that the provided field name cannot be null.
If the s parameter is not null, the method simply returns the s string.
In summary, the validateNotNull method ensures that the provided string is not null, and if it is null, it throws an exception. Otherwise, it returns the string as is.
The validateNotNull method in the io.nats.client.support.Validator class is a static method that validates whether a given string s is not null.
If the s string is null, it throws an IllegalArgumentException with a message stating that the fieldName (provided as a parameter) cannot be null.
The method returns the same string s if it is not null.

public static Object validateNotNull(Object o, String fieldName) {
if (o == null) {
throw new IllegalArgumentException(fieldName + " cannot be null");
}
return o;
}This method is defined in the io.nats.client.support.Validator class. It takes in two parameters, an Object o and a String fieldName. The purpose of this method is to validate that the given object is not null.
The method starts by checking if the parameter o is null using the == operator. If the object is indeed null, an IllegalArgumentException is thrown, with the error message constructed by concatenating the fieldName parameter with the string " cannot be null".
If the object is not null, the method simply returns the object.
It is important to note that this method does not modify the object in any way; it is purely used for validation purposes.
The validateNotNull method in the io.nats.client.support.Validator class is used to validate that an object is not null.
The method takes two parameters: o, which is the object to be validated, and fieldName, which is a string representing the name of the field being checked.
If the o parameter is null, the method throws an IllegalArgumentException with a message that includes the fieldName. Otherwise, if the o parameter is not null, the method simply returns the object.

public static int validateGtZero(int i, String label) {
if (i < 1) {
throw new IllegalArgumentException(label + " must be greater than zero");
}
return i;
}The validateGtZero method, defined in the io.nats.client.support.Validator class, is responsible for validating whether a given integer value is greater than zero.
public static int validateGtZero(int i, String label)-
int i: the integer value to be validated -
String label: the label associated with the integer value, used for error messaging purposes
- Returns the validated integer value
iif it is greater than zero
- Check if the value of
iis less than 1. - If the above condition is true, throw an
IllegalArgumentExceptionwith the error message format:label + " must be greater than zero". - If the value of
iis greater than zero, returni.
The method validateGtZero defined in class io.nats.client.support.Validator is a static method that takes an integer i and a string label as parameters.
The purpose of this method is to validate that the integer i is greater than zero. If the condition i < 1 is not met, meaning that i is less than or equal to zero, an IllegalArgumentException is thrown with a message stating that the given label should be greater than zero.
If the condition is met and i is greater than zero, the method returns the same integer i.
In summary, the validateGtZero method ensures that the provided integer value is higher than zero, throwing an exception if not, and returning the integer value otherwise.

public static long validateGtZeroOrMinus1(long l, String label) {
if (zeroOrLtMinus1(l)) {
throw new IllegalArgumentException(label + " must be greater than zero or -1 for unlimited");
}
return l;
}This method, validateGtZeroOrMinus1, is defined in the io.nats.client.support.Validator class. It takes two parameters: l, which is a long value, and label, which is a String.
The purpose of this method is to validate the l value, ensuring that it is either greater than zero or equal to -1. If the l value does not meet this condition, an IllegalArgumentException is thrown with a message indicating that the label must be greater than zero or equal to -1 for unlimited.
public static long validateGtZeroOrMinus1(long l, String label)-
l- thelongvalue that needs to be validated. -
label- theStringlabel used for generating an error message if the validation fails.
-
long- the validated value ofl.
if (zeroOrLtMinus1(l)) {
throw new IllegalArgumentException(label + " must be greater than zero or -1 for unlimited");
}
return l;- The method checks if the
lvalue satisfies the condition specified by thezeroOrLtMinus1method (implementation details not provided). This condition is meant to determine iflis either zero or less than -1. - If the condition is satisfied, an
IllegalArgumentExceptionis thrown with an error message stating that thelabelmust be greater than zero or equal to -1 for unlimited. - If the condition is not satisfied, the method returns the original
lvalue. - The method execution completes.
The validateGtZeroOrMinus1 method in the Validator class within the io.nats.client.support package is used to validate if a given long value is greater than zero or equal to -1.
If the value passed as the first argument is equal to or less than zero, an IllegalArgumentException is thrown with a message indicating that the value specified by the label parameter must be greater than zero or -1 for unlimited.
If the value is greater than zero or equal to -1, it is returned as the result of the method.

public static long validateGtEqMinus1(long l, String label) {
if (l < -1) {
throw new IllegalArgumentException(label + " must be greater than zero or -1 for unlimited");
}
return l;
}The validateGtEqMinus1 method is defined in the class io.nats.client.support.Validator. It takes in two parameters: l of type long and label of type String.
The method checks if the value of l is less than -1 using the condition l < -1.
If the value of l is less than -1, an IllegalArgumentException is thrown with the message label + " must be greater than zero or -1 for unlimited". This exception indicates that the label value must be greater than zero or equal to -1 in order to proceed.
If the value of l is greater than or equal to -1, the method simply returns the value of l.
The validateGtEqMinus1 method in the Validator class, defined in the io.nats.client.support package, is used to validate if a given long value is greater than or equal to -1.
The method takes two parameters: l (the long value to be validated) and label (a string indicating the label or name of the value being validated).
Inside the method, it checks if the long value l is less than -1. If it is, an IllegalArgumentException is thrown with a message indicating that the value must be greater than zero or -1 for unlimited.
If the value passes the validation, it is returned without any modifications.
This method ensures that the long value provided is valid and meets the required criteria, helping to maintain data integrity and prevent incorrect usage of the value in the code.

public static long validateNotNegative(long l, String label) {
if (l < 0) {
throw new IllegalArgumentException(label + " cannot be negative");
}
return l;
}The validateNotNegative method is defined in the io.nats.client.support.Validator class. It takes two parameters: a long value l and a String label.
The purpose of this method is to validate that the provided long value is not negative. It ensures that the value is greater than or equal to zero.
Here is a step-by-step description of what the method does:
-
Check if the value of
lis less than zero:- If
lis indeed less than zero, it means that the value is negative. - In such a case, an
IllegalArgumentExceptionis thrown with a message that includes the provided label. - The message states that the value cannot be negative.
- This exception serves as an indicator that the provided value is invalid.
- If
-
If the value of
lis not negative, it means it is valid.- The method continues execution and returns the provided value
l.
- The method continues execution and returns the provided value
By utilizing this method, you can verify that a given long value is not negative by calling Validator.validateNotNegative and providing the value to validate along with a label for identification.
The validateNotNegative method in the Validator class, defined in the io.nats.client.support package, is responsible for checking if a given long value is not negative.
The method takes two parameters: l, which is the long value to be validated, and label, which is a string label used in the exception message if the value is negative.
If the value of l is less than 0, the method throws an IllegalArgumentException, with the message "label cannot be negative", where label is the provided string label concatenated with the message.
If the value is non-negative, the method simply returns the value.
This method can be used to enforce the constraint that a certain long value should always be non-negative.

public static long validateGtEqZero(long l, String label) {
if (l < 0) {
throw new IllegalArgumentException(label + " must be greater than or equal to zero");
}
return l;
}The method validateGtEqZero in the io.nats.client.support.Validator class is responsible for validating if a given value is greater than or equal to zero. Here is a step-by-step description of how the method works:
- Accept two parameters:
l, which is the value to be validated, andlabel, which is a description of the value being checked. - Check if the value
lis less than zero using the conditionif (l < 0). - If the value is less than zero, it indicates that the value is invalid.
- Throw an
IllegalArgumentExceptionwith a custom error message. The error message consists of the providedlabelfollowed by the string "must be greater than or equal to zero". - If the value is greater than or equal to zero, it indicates that the value is valid.
- Return the value
las it has been successfully validated.
This method is useful when you want to ensure that a given value is not negative but is instead greater than or equal to zero. By throwing an exception when the value is invalid, it provides a clear indication of the validation failure and allows for proper error handling in the calling code.
The validateGtEqZero method in the Validator class of the io.nats.client.support package checks if a given long value is greater than or equal to zero.
If the value is less than zero, it throws an IllegalArgumentException with a specific message indicating that the value must be greater than or equal to zero.
Regardless of the comparison result, the method returns the original value.

// ----------------------------------------------------------------------------------------------------
// Helpers // ---------------------------------------------------------------------------------------------------- public static boolean nullOrEmpty(String s)
// ----------------------------------------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------------------------------------
public static boolean nullOrEmpty(String s) {
return s == null || s.trim().length() == 0;
}The nullOrEmpty method in the io.nats.client.support.Validator class is a static helper method used to check if a given string is either null or empty. It follows the following steps:
- Check if the input string
sis null. - If
sis null, return true to indicate that the string is null or empty. - If
sis not null, trim the string using thetrim()method. - Use the
length()method to get the length of the trimmed string. - Check if the length of the trimmed string is 0.
- If the length is 0, return true to indicate that the string is empty.
- If the length is greater than 0, return false to indicate that the string is not empty.
Here is the method in code:
public static boolean nullOrEmpty(String s) {
return s == null || s.trim().length() == 0;
}This method provides a convenient way to check if a string is null or empty before performing any further processing or validation.
The nullOrEmpty method, defined in the io.nats.client.support.Validator class, is a helper method that checks whether a given string is null or empty.
The method takes a string s as input and returns a boolean value indicating whether the string is null or its trimmed length is 0.
This method is useful for validating string inputs in the context of the Nats client.

public static boolean notPrintable(String s) {
for (int x = 0; x < s.length(); x++) {
char c = s.charAt(x);
if (c < 33 || c > 126) {
return true;
}
}
return false;
}The method notPrintable is defined in the class io.nats.client.support.Validator and is used to determine if a given string contains any non-printable characters.
public static boolean notPrintable(String s)-
s: A string to be checked for non-printable characters.
-
trueif the string contains any non-printable characters. -
falseif the string does not contain any non-printable characters.
- Start the loop from
x = 0and continue as long asxis less than the length of the strings. - Get the character at index
xfrom the stringsand assign it to the variablec. - Check if the ASCII value of
cis less than 33 or greater than 126.- If the condition is true, it means that
cis a non-printable character. - In this case, return
trueto indicate that the string contains non-printable characters.
- If the condition is true, it means that
- If the loop completes without finding any non-printable characters, return
falseto indicate that the string does not contain any non-printable characters.
The notPrintable method in the Validator class is a static method that takes a string as input and checks whether the string contains any non-printable characters. Non-printable characters are defined as characters with ASCII codes below 33 or above 126.
The method uses a loop to iterate through each character in the input string. If a character is found that falls outside the range of printable ASCII characters, the method returns true, indicating that the string contains non-printable characters. If no non-printable characters are found, the method returns false.
This method can be used to validate input strings and ensure that they only contain printable characters, which are typically characters that can be displayed or printed by most systems and devices.

public static boolean notPrintableOrHasChars(String s, char[] charsToNotHave) {
for (int x = 0; x < s.length(); x++) {
char c = s.charAt(x);
if (c < 33 || c > 126) {
return true;
}
for (char cx : charsToNotHave) {
if (c == cx) {
return true;
}
}
}
return false;
}The notPrintableOrHasChars method is a static method defined in the io.nats.client.support.Validator class. This method takes two parameters:
-
s: A string which needs to be checked for printable characters and the presence of specific characters. -
charsToNotHave: An array of characters that should not be present in the strings.
The purpose of this method is to determine if the given string s contains any non-printable characters or any of the characters specified in charsToNotHave. The method returns a boolean value indicating if any of these conditions are met.
The method accomplishes this by iterating over each character in the string s using a for loop. Inside the loop, each character is checked against two conditions:
-
If the character is less than 33 (
c < 33) or greater than 126 (c > 126), it is considered a non-printable character. In this case, the method immediately returnstrueindicating that the string contains non-printable characters. -
The character is then compared with each character in the
charsToNotHavearray using another for-each loop. If a match is found (c == cx), the method returnstrueindicating that the specific character is present in the string.
If neither of the above conditions is met within the loop, the method continues to the next character until all characters in the string have been checked. If the method reaches this point without returning true, it means that no non-printable or unwanted characters were found in the string, and it returns false.
The notPrintableOrHasChars method, defined in the io.nats.client.support.Validator class, checks if a given string s contains any characters that are not printable or are present in the charsToNotHave array.
Here's a breakdown of the method's behavior:
-
The method takes two parameters:
s(the string to be checked) andcharsToNotHave(an array of characters that should not be present in the string). -
It iterates over each character in the input string
susing aforloop. -
For each character, it checks if it is not a printable character (ASCII value less than 33 or greater than 126). If so, it returns
true. -
It then iterates over each character
cxin thecharsToNotHavearray and checks if the current charactercis equal to any of these characters. If a match is found, it returnstrue. -
If none of the non-printable characters or prohibited characters are found in the string, it returns
false.
In summary, this method is used to validate whether a given string contains characters that are not printable or are listed in the charsToNotHave array.

public static boolean notRestrictedTerm(String s)
// restricted-term = (A-Z, a-z, 0-9, dash 45, underscore 95)+
public static boolean notRestrictedTerm(String s) {
for (int x = 0; x < s.length(); x++) {
char c = s.charAt(x);
if (c < '0') {
// before 0
if (c == '-') {
// only dash is accepted
continue;
}
// "not"
return true;
}
if (c < ':') {
// means it's 0 - 9
continue;
}
if (c < 'A') {
// between 9 and A is "not restricted"
return true;
}
if (c < '[') {
// means it's A - Z
continue;
}
if (c < 'a') {
// before a
if (c == '_') {
// only underscore is accepted
continue;
}
// "not"
return true;
}
if (c > 'z') {
// 122 is z, characters after of them are "not restricted"
return true;
}
}
return false;
}This method is used to check whether a given string contains any characters that are not allowed in a restricted term.
-
s- A string which needs to be checked.
-
boolean- Returnstrueif the string contains any characters that are not allowed in a restricted term, otherwise returnsfalse.
- Iterate over each character in the given string.
- Check the value of the character against certain ASCII values to determine if it is a restricted character.
- If the character is before '0' (ASCII value < 48), check if it is '-'. If it is, continue to the next character.
- If the character is between '0' and ':' (ASCII values 48-57), it is a digit and is allowed in a restricted term. Continue to the next character.
- If the character is between '9' and 'A' (ASCII values 58-65), it is not a restricted character. Return
true. - If the character is between 'A' and '[' (ASCII values 65-91), it is a capital letter and is allowed in a restricted term. Continue to the next character.
- If the character is between '[' and 'a' (ASCII values 91-97), it is not a restricted character. Return
true. - If the character is between 'a' and 'z' (ASCII values 97-123), it is a lowercase letter and is allowed in a restricted term. Continue to the next character.
- If the character has an ASCII value greater than 'z' (ASCII value > 122), it is not a restricted character. Return
true. - If none of the above conditions are met for any character in the string, return
falseas it is a restricted term.
String term = "my_Term";
boolean isRestricted = notRestrictedTerm(term);
System.out.println(isRestricted); // Output: falseIn the above example, the string "my_Term" is checked using the notRestrictedTerm method. Since all characters in the string are allowed in a restricted term, the method returns false.
The notRestrictedTerm method in the Validator class checks if a given string contains any characters that are not allowed in a restricted term.
The method iterates through each character of the string and checks its value against specific ASCII ranges.
- If the character is before the numerical range (less than '0'), it returns true, indicating that the string is not a restricted term.
- If the character is within the numerical range ('0' to '9'), it continues to the next character.
- If the character is between the numerical range and the uppercase alphabetical range, it returns true.
- If the character is within the uppercase alphabetical range ('A' to 'Z'), it continues to the next character.
- If the character is before the lowercase alphabetical range, it returns true.
- If the character is within the lowercase alphabetical range ('a' to 'z'), it continues to the next character.
- If the character is after the lowercase alphabetical range (greater than 'z'), it returns true.
If none of these conditions are met after iterating through all characters, the method returns false, indicating that the given string is a valid restricted term.

// kv-key-name = limited-term (dot limited-term)* public static boolean notNonWildcardKvKey(String s)
// limited-term = (A-Z, a-z, 0-9, dash 45, dot 46, fwd-slash 47, equals 61, underscore 95)+
// kv-key-name = limited-term (dot limited-term)*
public static boolean notNonWildcardKvKey(String s) {
if (s.charAt(0) == '.') {
// can't start with dot
return true;
}
for (int x = 0; x < s.length(); x++) {
char c = s.charAt(x);
if (c < '0') {
// before 0
if (c == '-' || c == '.' || c == '/') {
// only dash dot and fwd slash are accepted
continue;
}
// "not"
return true;
}
if (c < ':') {
// means it's 0 - 9
continue;
}
if (c < 'A') {
if (c == '=') {
// equals is accepted
continue;
}
// between 9 and A is "not limited"
return true;
}
if (c < '[') {
// means it's A - Z
continue;
}
if (c < 'a') {
// before a
if (c == '_') {
// only underscore is accepted
continue;
}
// "not"
return true;
}
if (c > 'z') {
// 122 is z, characters after of them are "not limited"
return true;
}
}
return false;
}The notNonWildcardKvKey method in the io.nats.client.support.Validator class is used to validate a string s to determine if it is a valid key for a key-value pair in a limited-term format. Here is a step-by-step description of what the method is doing based on its body:
-
The method starts by checking if the first character of the string is a dot (
.). If it is, the method returnstrueindicating that the key cannot start with a dot. -
The method then enters a
forloop to iterate over each character in the string. -
Within the loop, the method checks the value of the current character
c. -
If
cis less than the character'0', it means thatccomes before the numbers 0-9. In this case, the method checks ifcis equal to dash (-), dot (.), or forward slash (/) and if it is, it continues to the next character. Ifcis not one of these characters, the method returnstrue, indicating that the key contains a character that is not allowed before the numbers 0-9. -
If
cis between the characters'0'and'9', the method continues to the next character because it is a valid digit in the key. -
If
cis less than the character'A', it means thatccomes between the numbers 9 and the uppercase letters A-Z. In this case, the method checks ifcis equal to equal sign (=) and if it is, it continues to the next character. Ifcis not an equal sign, the method returnstrue, indicating that the key contains a character that is not allowed between the numbers 9 and the uppercase letters A-Z. -
If
cis between the characters'A'and'Z', the method continues to the next character because it is a valid uppercase letter in the key. -
If
cis less than the character'a', it means thatccomes between the uppercase letters A-Z and the lowercase letters a-z. In this case, the method checks ifcis equal to underscore (_) and if it is, it continues to the next character. Ifcis not an underscore, the method returnstrue, indicating that the key contains a character that is not allowed between the uppercase letters A-Z and the lowercase letters a-z. -
If
cis greater than the character'z', it means thatccomes after the lowercase letters a-z. In this case, the method returnstrue, indicating that the key contains a character that is not allowed after the lowercase letters a-z. -
After iterating over all the characters in the string and not encountering any invalid characters, the method returns
false, indicating that the key is valid.
This method can be used to validate whether a string is a valid key for a key-value pair in a limited-term format.
The notNonWildcardKvKey method is a static method defined in the Validator class of the io.nats.client.support package. It takes a string s as an input and returns a boolean value.
This method verifies if the input string s is a valid key for a key-value store based on specific criteria. The criteria for a valid key are that it must start with a character other than a dot (.), and can only contain alphanumeric characters (A-Z, a-z, 0-9), dash (-), dot (.), forward slash (/), equals (=), and underscore (_).
The method checks each character of the input string against these criteria using a series of if statements. If any character does not meet the criteria, the method returns true, indicating that the key is not valid. If all characters pass the criteria, the method returns false, indicating that the key is valid.

public static boolean notWildcardKvKey(String s)
// (A-Z, a-z, 0-9, star 42, dash 45, dot 46, fwd-slash 47, equals 61, gt 62, underscore 95)+
public static boolean notWildcardKvKey(String s) {
if (s.charAt(0) == '.') {
// can't start with dot
return true;
}
for (int x = 0; x < s.length(); x++) {
char c = s.charAt(x);
if (c < '0') {
// before 0
if (c == '*' || c == '-' || c == '.' || c == '/') {
// only star dash dot and fwd slash are accepted
continue;
}
// "not"
return true;
}
if (c < ':') {
// means it's 0 - 9
continue;
}
if (c < 'A') {
if (c == '=' || c == '>') {
// equals, gt is accepted
continue;
}
// between 9 and A is "not limited"
return true;
}
if (c < '[') {
// means it's A - Z
continue;
}
if (c < 'a') {
// before a
if (c == '_') {
// only underscore is accepted
continue;
}
// "not"
return true;
}
if (c > 'z') {
// 122 is z, characters after of them are "not limited"
return true;
}
}
return false;
}This method, notWildcardKvKey, is defined in class io.nats.client.support.Validator. It takes a string s as input and checks if the string represents a valid key for a key-value pair.
-
Check if the first character of the input string
sis a period (.).- If it is, return
trueas keys cannot start with a dot.
- If it is, return
-
Iterate through each character
cin the input strings.- For each character:
- If it is less than the character
'0':- Check if it is one of the allowed characters:
'*','-','.','/'.- If it is, continue to the next character.
- If it is not, return
trueas only the allowed characters are accepted before'0'.
- Check if it is one of the allowed characters:
- If it is less than the character
':'and greater than or equal to character'0', continue to the next character as it is a number (0-9). - If it is less than character
'A'and greater than character'9':- Check if it is one of the allowed characters:
'=','>'.- If it is, continue to the next character.
- If it is not, return
trueas only the allowed characters are accepted between'9'and'A'.
- Check if it is one of the allowed characters:
- If it is less than character
'['and greater than or equal to character'A', continue to the next character as it is an uppercase letter (A-Z). - If it is less than character
'a'and greater than character'A':- Check if it is the allowed character
'_'.- If it is, continue to the next character.
- If it is not, return
trueas only the allowed character'_'is accepted before lowercase letters.
- Check if it is the allowed character
- If it is greater than character
'z'(122 is the ASCII value of'z'), returntrueas characters after'z'are not limited.
- If it is less than the character
- For each character:
-
If none of the above conditions are met, return
falseas the input stringsrepresents a valid key for a key-value pair.
Note: The method follows a pattern-based validation where the characters in the input string are checked against specific ranges and allowed characters. Any character found outside the allowed ranges or characters will result in the method returning true, indicating that the input string is not a valid key.
The notWildcardKvKey method, defined in the Validator class of the io.nats.client.support package, is used to validate a key string for a key-value pair.
The method checks if the given string contains characters that follow the specified pattern, which includes uppercase letters (A-Z), lowercase letters (a-z), numbers (0-9), special characters like star (*), dash (-), dot (.), forward slash (/), equals (=), and greater than (>). The string can also contain an underscore (_) character.
The method ensures that the string does not start with a dot (.), as that is not allowed. It also performs checks for specific characters based on their ASCII values, rejecting any characters that do not meet the allowed criteria.
If the string meets the criteria, the method returns false, indicating that it is a valid key. If the string does not meet the criteria or violates the specified pattern, the method returns true, indicating that it is not a valid key.

public static String validateSemVer(String s, String label, boolean required) {
return _validate(s, required, label, () -> {
if (!isSemVer(s)) {
throw new IllegalArgumentException(label + " must be a valid SemVer");
}
return s;
});
}The validateSemVer method, defined in the io.nats.client.support.Validator class, is used to validate a string representing a Semantic Version (SemVer) number. Here is a step-by-step description of what the method does:
-
The method takes three parameters:
s(the string to be validated),label(a label used for error messages), andrequired(a boolean value indicating whether the string is required or not). -
The method calls a private static method
_validateand passes thes,required,label, and a lambda expression as arguments. The lambda expression is used to define the behavior in case of successful validation. -
The
_validatemethod performs the actual validation by checking if the stringsis a valid SemVer number. If it is not, anIllegalArgumentExceptionis thrown with an error message containing thelabeland the requirement that the value must be a valid SemVer number. -
If the validation passes and the string is a valid SemVer number, the lambda expression defined in the
_validatemethod is executed. This lambda expression returns the validated strings. -
Finally, the
validateSemVermethod returns the validated stringsas the result of the method call.
In summary, the validateSemVer method validates a string representation of a Semantic Version number by calling the _validate method, which performs the actual validation and throws an exception if the string is not a valid SemVer number. If the validation passes, the method returns the validated string.
The validateSemVer method in the Validator class is used to validate a given string s as a Semantic Version (SemVer) according to the SemVer specification.
The method takes three parameters:
-
s- the string to be validated as a SemVer. -
label- a label or identifier for the string being validated. -
required- a boolean flag indicating whether the validated string is required or not.
The method internally calls a private _validate method, passing the required parameters along with a lambda expression that performs the actual validation. If the provided string s is not a valid SemVer, an IllegalArgumentException is thrown, with a specific error message indicating that the provided label must be a valid SemVer.
If the provided string s is valid according to the SemVer specification, it is returned as the result of the method.

public static <T> boolean listsAreEqual(List<T> l1, List<T> l2, boolean nullSecondEqualsEmptyFirst) {
if (l1 == null) {
return l2 == null;
}
if (l2 == null) {
return nullSecondEqualsEmptyFirst && l1.size() == 0;
}
return l1.equals(l2);
}The listsAreEqual method, defined in the io.nats.client.support.Validator class, compares two lists - l1 and l2 - to determine if they are equal. Here is a step-by-step description of what the method is doing:
- Check if
l1isnull:
- If
l1isnull, proceed to step 2. - If
l1is notnull, proceed to step 3.
- Check if
l2is alsonull:
- If
l2isnull, returntrue, indicating that both lists arenulland therefore equal. - If
l2is notnull, returnfalse, indicating thatl1isnullbutl2is not, so they are not equal.
- Check if
l2isnull:
- If
l2isnullandnullSecondEqualsEmptyFirstistrue, check ifl1is empty (i.e., it has a size of 0).- If
l1is empty, returntrue, indicating that both lists are empty and therefore equal. - If
l1is not empty, returnfalse, indicating thatl1is not empty butl2is, so they are not equal.
- If
- If
l2is notnull, proceed to step 4.
- Use the
equals()method to compare the contents ofl1andl2:
- If the contents of
l1andl2are equal, returntrue. - If the contents of
l1andl2are not equal, returnfalse.
Note: The equals() method used in step 4 will use the implementation of equals() provided by the elements in the lists l1 and l2.
The method listsAreEqual is a static method defined in the Validator class in the io.nats.client.support package.
This method takes two generic lists (l1 and l2) as inputs and a boolean flag (nullSecondEqualsEmptyFirst). It compares the equality of the two lists based on the following logic:
-
If the first list (
l1) isnull, the method checks if the second list (l2) is alsonull. If yes, it returnstrue, indicating that both lists are equal. If the second list is notnull, it returnsfalse, indicating that the lists are not equal. -
If the first list (
l1) is notnullbut the second list (l2) isnull, the method checks if thenullSecondEqualsEmptyFirstflag is set totrueand if the size of the first list is0. If both conditions are met, it returnstrue, indicating that the lists are equal. Otherwise, it returnsfalse. -
If both lists are not
null, the method uses theequalsmethod of the first list (l1) to compare it with the second list (l2). If the lists are equal, it returnstrue. Otherwise, it returnsfalse.
In summary, this method checks the equality of two lists, taking into account potential null lists and the option to treat a null second list as equal to an empty first list.
public static boolean mapsAreEqual(Map<String, String> m1, Map<String, String> m2, boolean nullSecondEqualsEmptyFirst)
public static boolean mapsAreEqual(Map<String, String> m1, Map<String, String> m2, boolean nullSecondEqualsEmptyFirst) {
if (m1 == null) {
return m2 == null;
}
if (m2 == null) {
return nullSecondEqualsEmptyFirst && m1.size() == 0;
}
if (m1.size() != m2.size()) {
return false;
}
for (Map.Entry<String, String> entry : m1.entrySet()) {
if (!entry.getValue().equals(m2.get(entry.getKey()))) {
return false;
}
}
return true;
}The mapsAreEqual method is defined in the io.nats.client.support.Validator class. It takes in two Map<String, String> objects (m1 and m2) and a boolean flag (nullSecondEqualsEmptyFirst).
The purpose of this method is to compare two maps for equality. It returns true if the maps are equal and false otherwise.
Here is a step-by-step breakdown of what the method is doing:
-
If
m1isnull, it checks ifm2is alsonull. If true, it means both maps arenulland returnstrue. Ifm2is notnull, it returnsfalsebecause they are not equal. -
If
m1is notnull, it checks ifm2isnull. If true, it checks the value of thenullSecondEqualsEmptyFirstflag. If the flag istrueand the size ofm1is0, it means the second map is considered as an empty map, and it returnstrue. Otherwise, it returnsfalse. -
If both
m1andm2are notnull, it checks if the sizes of the two maps are equal. If they are not equal, it returnsfalse. -
If the sizes of both maps are equal, it iterates through each entry in
m1. -
For each entry, it retrieves the corresponding value from
m2using the key. If the value is not equal to the value inm1, it means the maps are not equal, and it returnsfalse. -
If all entries in
m1have been checked and they are equal to their corresponding values inm2, the method returnstrueindicating that the maps are equal.
The mapsAreEqual method, defined in the io.nats.client.support.Validator class, is used to compare two maps (m1 and m2) and determine if they are equal.
The method takes three parameters:
-
m1: The first map to compare. -
m2: The second map to compare. -
nullSecondEqualsEmptyFirst: A boolean flag indicating whether a null second map should be considered equal to an empty first map.
The method first checks if m1 is null. If it is, the method returns true if m2 is also null, and false otherwise.
Next, it checks if m2 is null. If it is and nullSecondEqualsEmptyFirst is true, the method returns true if m1 is also empty (i.e., has a size of 0), and false otherwise.
If both maps are not null, the method checks if their sizes are equal. If they are not, the method returns false.
Finally, the method iterates over the entries of m1 using a for-each loop. For each entry, it compares the value in m1 to the corresponding value in m2 based on the key. If any pair of values are not equal, the method returns false. If all pairs are equal, the method returns true.
In summary, the mapsAreEqual method compares two maps, accounting for null maps and specifying whether a null second map should be considered equal to an empty first map. It returns true if the maps are equal and false otherwise.

SSLUtils
The SSLUtils class is a public class that provides utilities for working with SSL (Secure Sockets Layer) in software engineering. It includes methods and functionalities for managing SSL certificates, configuring SSL connections, and handling SSL exceptions. This class is designed to facilitate secure communication over network sockets using SSL protocols.
public static SSLContext createOpenTLSContext() {
SSLContext context = null;
try {
context = SSLContext.getInstance(Options.DEFAULT_SSL_PROTOCOL);
context.init(null, trustAllCerts, SRAND);
} catch (Exception e) {
context = null;
}
return context;
}The createOpenTLSContext method in the SSLUtils class is used to create an SSLContext object for establishing a secure TLS connection.
Here is a step-by-step description of what the method does:
- It declares a variable
contextof type SSLContext and initializes it to null. - It tries to create an SSLContext object using the
getInstancemethod from the SSLContext class, passing in the value ofOptions.DEFAULT_SSL_PROTOCOL.-
Options.DEFAULT_SSL_PROTOCOLtypically specifies the default SSL/TLS protocol version to be used, such as "TLSv1.2".
-
- It initializes the SSLContext object
contextby calling itsinitmethod, passing in the following parameters:-
nullas the first parameter, indicating that no KeyManager should be used. -
trustAllCertsas the second parameter, indicating that all server certificates should be trusted. -
SRANDas the third parameter, which is aSecureRandomobject used for seed generation in the handshake process. -
trustAllCertsis likely an array ofTrustManagerobjects that implement a trust manager that trusts all certificates. -
SRANDis likely aSecureRandomobject that provides a cryptographically strong random number generator.
-
- If any exception occurs during the creation or initialization of the SSLContext object, the
contextvariable is set back to null. - Finally, the method returns the SSLContext object
context, which may be null if any exception occurred.
Overall, the createOpenTLSContext method attempts to create and initialize an SSLContext object with the default SSL/TLS protocol and with trust in all server certificates. It is typically used for establishing a secure TLS connection in the NATS Java client library.
The createOpenTLSContext method in the SSLUtils class is used to create an SSLContext object for establishing a TLS connection.
Inside the method, it first calls SSLContext.getInstance method to create an SSLContext object with the default SSL protocol specified in the Options class.
Then, it initializes the SSLContext object by calling the init method with null as the TrustManager array, trustAllCerts as the TrustManager implementation (presumably, an array of all-trusting trust managers), and SRAND as the source of randomness.
If any exception occurs during the creation or initialization process, the SSLContext object will be set to null.
Finally, the method returns the created SSLContext object.
Overall, this method is responsible for creating and initializing an SSLContext object for TLS connections with the default SSL protocol.

DateTimeUtils
This class, DateTimeUtils, is an abstract class that provides internal json parsing helpers.
public static ZonedDateTime parseDateTime(String dateTime, ZonedDateTime dflt) {
try {
return toGmt(ZonedDateTime.parse(dateTime));
} catch (DateTimeParseException s) {
return dflt;
}
}The parseDateTime method is defined in the io.nats.client.support.DateTimeUtils class and is responsible for parsing a given dateTime string and returning a ZonedDateTime object. If the parsing fails, the method will return a default ZonedDateTime object specified by the dflt parameter.
-
dateTime(String): ThedateTimestring to be parsed. -
dflt(ZonedDateTime): The defaultZonedDateTimeobject to be returned if parsing fails.
-
ZonedDateTime: AZonedDateTimeobject representing the parsed date and time. If parsing fails, the defaultZonedDateTimeobject will be returned.
-
Try to execute the following steps:
- Parse the
dateTimestring using theZonedDateTime.parsemethod. - Convert the parsed
ZonedDateTimeobject to GMT time zone using thetoGmtmethod. - Return the converted
ZonedDateTimeobject.
- Parse the
-
If any
DateTimeParseExceptionoccurs during the parsing process:- Catch the exception.
- Return the default
ZonedDateTimeobject specified by thedfltparameter.
The parseDateTime method in the DateTimeUtils class is a static method that takes a string representing a date and time, and returns a ZonedDateTime object. If the string cannot be parsed into a ZonedDateTime, it returns a default value provided as a parameter.
The method attempts to parse the dateTime string using the ZonedDateTime.parse method. If the parsing is successful, the resulting ZonedDateTime object is converted to GMT using the toGmt method (which is not shown in the code snippet). If the parsing fails and throws a DateTimeParseException, the method returns the default value dflt.

WebsocketOutputStream
The WebsocketOutputStream class is a public class that extends the OutputStream class. This class is used to handle output stream operations for websockets.
public void close() throws IOException
@Override
public void close() throws IOException {
// NOTE: Per spec, we should technically wait to receive the close frame,
// but we are not in control of the InputStream here...
WebsocketFrameHeader header = new WebsocketFrameHeader().withOp(OpCode.CLOSE, true).withNoMask().withPayloadLength(0);
int length = header.read(headerBuffer, 0, headerBuffer.length);
wrap.write(headerBuffer, 0, length);
wrap.close();
}The close method in the WebsocketOutputStream class, defined in the io.nats.client.support package, is used to close the output stream for a WebSocket connection.
Here are the step-by-step description of what this method does:
-
The method overrides the
closemethod from the superclass, which isjava.io.OutputStream, and it throws anIOException. -
Before closing the output stream, the method makes a note that, as per the WebSocket specification, ideally, it should wait to receive the close frame. However, since it is not in control of the input stream, it doesn't wait.
-
It creates a new instance of the
WebsocketFrameHeaderclass. -
The
WebsocketFrameHeaderinstance is configured with theOpCode.CLOSEoperation code, indicating that it wants to close the WebSocket connection. The second parametertruesets the "final" bit of the frame header to true, indicating that this frame represents the entire payload. -
The
WebsocketFrameHeaderinstance is further configured with thewithNoMaskmethod, which disables the masking of the payload. Masking is a security feature to prevent certain attacks, but in this case, it is not required, so it is disabled. -
The payload length is set to 0 because it is an empty frame.
-
The
headerobject reads the frame header data into a byte array calledheaderBufferusing thereadmethod, which returns the length of the read data. -
The
wrapobject, which represents the underlying output stream, writes theheaderBufferdata to the stream using thewritemethod. Thelengthparameter specifies the number of bytes to write. -
Finally, the
wrapobject'sclosemethod is called to close the underlying output stream, releasing any system resources associated with it.
Overall, this close method sends a close frame header with no payload length to indicate the intention to close the WebSocket connection and then closes the output stream.
The close method in the io.nats.client.support.WebsocketOutputStream class is responsible for closing the WebSocket output stream.
In the method, it first creates a WebSocket frame header with the CLOSE opcode and no payload. It then writes the header to the underlying output stream using the write method of the wrap object. Finally, it closes the wrap object, which will flush any remaining data and close the output stream.
It is important to note that according to the WebSocket specification, the method should technically wait to receive the close frame, but that is not possible in this context because the method has no control over the underlying input stream.

public void write(byte[] buffer, int offset, int length) throws IOException
@Override
public void write(byte[] buffer, int offset, int length) throws IOException {
header.withPayloadLength(length);
if (masked) {
header.withMask(random.nextInt());
}
int headerBufferOffset = header.read(headerBuffer, 0, headerBuffer.length);
int consumed = Math.min(length, headerBuffer.length - headerBufferOffset);
System.arraycopy(buffer, offset, headerBuffer, headerBufferOffset, consumed);
header.filterPayload(headerBuffer, headerBufferOffset, consumed);
wrap.write(headerBuffer, 0, headerBufferOffset + consumed);
if (consumed < length) {
// NOTE: We could perform a "mark" operation before filtering the
// payload which saves the payloadLength and maskingKeyOffset, then
// perform a "resetMark" operation after writing the masked buffer
// and finally re-applying the filter in order to preserve the
// original values of the bytes. However, there appears to be no
// code which relies on the bytes in the buffer to be preserved,
// so we are keeping things efficient by not performing these
// operations.
header.filterPayload(buffer, offset + consumed, length - consumed);
wrap.write(buffer, offset + consumed, length - consumed);
}
}The write(byte[] buffer, int offset, int length) method, defined in the WebsocketOutputStream class, is responsible for writing the specified portion of a byte array to the underlying output stream.
- Set the length of the payload in the header.
- If the payload is masked, generate a random mask and set it in the header.
- Read the header into a buffer and calculate the offset.
- Calculate the number of bytes to be consumed, which is the minimum of the length and the remaining space in the header buffer.
- Copy the bytes from the input buffer to the header buffer.
- Filter the payload bytes in the header buffer.
- Write the header buffer to the underlying output stream.
- If the number of consumed bytes is less than the length of the payload:
- Filter the remaining payload bytes.
- Write the remaining payload bytes to the underlying output stream.
The write method in the WebsocketOutputStream class is used to write data to a WebSocket connection.
This method takes in three parameters: buffer, offset, and length. The buffer parameter is the array of bytes to be written, the offset parameter is the starting index of the data to be written in the buffer, and the length parameter is the number of bytes to be written.
Within the method, the payloadLength of the WebSocket header is updated with the length of the data to be written. If the WebSocket is masked, a random mask value is generated and added to the header.
A portion of the data is then copied from the buffer to a headerBuffer, which is a buffer for the WebSocket header. The data in the headerBuffer is then filtered according to the WebSocket payload filtering rules.
After that, the filtered headerBuffer is written to the WebSocket connection using the wrap.write method.
If there is still remaining data in the original buffer after writing the headerBuffer, it is filtered and then written to the WebSocket connection using the wrap.write method again.
Note: There is a comment indicating that a more complex "mark" and "resetMark" operation could be performed to preserve the original values of the bytes in the buffer, but it is mentioned that there is no code relying on this preservation, so the more efficient approach is taken.

WebSocket
The WebSocket class is a public class that extends the Socket class. It provides functionality for handling communication over a WebSocket connection.
private static void handshake(Socket socket, String host, List<Consumer> interceptors) throws IOException
private static void handshake(Socket socket, String host, List<Consumer<HttpRequest>> interceptors) throws IOException {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
HttpRequest request = new HttpRequest();
// The value of this header field MUST be a
// nonce consisting of a randomly selected 16-byte value that has
// been base64-encoded
byte[] keyBytes = new byte[16];
new SecureRandom().nextBytes(keyBytes);
String key = Base64.getEncoder().encodeToString(keyBytes);
request.getHeaders().add("Host", host).add("Upgrade", "websocket").add("Connection", "Upgrade").add("Sec-WebSocket-Key", key).add("Sec-WebSocket-Protocol", "nats").add("Sec-WebSocket-Version", "13");
// TODO: Support Sec-WebSocket-Extensions: permessage-deflate
// TODO: Support Nats-No-Masking: TRUE
for (Consumer<HttpRequest> interceptor : interceptors) {
interceptor.accept(request);
}
out.write(request.toString().getBytes(UTF_8));
// rfc6455 4.1 "The client MUST validate the server's response as follows:"
byte[] buffer = new byte[MAX_LINE_LEN];
String responseLine = readLine(buffer, in);
if (null == responseLine) {
throw new IllegalStateException("Expected HTTP response line not to exceed " + MAX_LINE_LEN);
}
// 1. expect 101:
if (!responseLine.toLowerCase().startsWith(WEBSOCKET_RESPONSE_LINE.toLowerCase())) {
throw new IllegalStateException("Expected " + WEBSOCKET_RESPONSE_LINE + ", but got " + responseLine);
}
Map<String, String> headers = new HashMap<>();
while (true) {
String line = readLine(buffer, in);
if (null == line) {
throw new IllegalStateException("Expected HTTP header to not exceed " + MAX_LINE_LEN);
}
if ("".equals(line)) {
break;
}
int colon = line.indexOf(':');
if (colon >= 0) {
if (headers.size() >= MAX_HTTP_HEADERS) {
throw new IllegalStateException("Exceeded max HTTP headers=" + MAX_HTTP_HEADERS);
}
headers.put(line.substring(0, colon).trim().toLowerCase(), line.substring(colon + 1).trim());
} else {
throw new IllegalStateException("Expected HTTP header to contain ':', but got " + line);
}
}
// 2. Expect `Upgrade: websocket`
if (!"websocket".equalsIgnoreCase(headers.get("upgrade"))) {
throw new IllegalStateException("Expected HTTP `Upgrade: websocket` header");
}
// 3. Expect `Connection: Upgrade`
if (!"upgrade".equalsIgnoreCase(headers.get("connection"))) {
throw new IllegalStateException("Expected HTTP `Connection: Upgrade` header");
}
// 4. Sec-WebSocket-Accept: base64(sha1(key + "258EAF..."))
MessageDigest sha1;
try {
sha1 = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException(ex);
}
sha1.update(key.getBytes(UTF_8));
sha1.update("258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(UTF_8));
String acceptKey = Base64.getEncoder().encodeToString(sha1.digest());
String gotAcceptKey = headers.get("sec-websocket-accept");
if (!acceptKey.equals(gotAcceptKey)) {
throw new IllegalStateException("Expected HTTP `Sec-WebSocket-Accept: " + acceptKey + ", but got " + gotAcceptKey);
}
// 5 & 6 are not valid, since nats-server doesn't
// implement extensions or protocols.
}The handshake method is defined in the io.nats.client.support.WebSocket class, and it is responsible for establishing a WebSocket connection between the client and the server.
- Create an input stream from the socket to receive data from the server.
- Create an output stream from the socket to send data to the server.
- Create an instance of
HttpRequest. - Generate a 16-byte random value and encode it in base64 format to create a nonce.
- Set the necessary headers in the request, including "Host", "Upgrade", "Connection", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol", and "Sec-WebSocket-Version".
- Optionally, support additional headers using the provided interceptors.
- Convert the request into a byte array and write it to the output stream.
- Define a byte buffer to read data from the input stream.
- Read the response line from the input stream.
- Ensure that the response line does not exceed the maximum line length.
- Verify that the response line starts with "HTTP/1.1 101" to indicate a successful upgrade to WebSocket.
- Create a map to store the HTTP headers.
- Read each header line from the input stream until an empty line is encountered.
- Ensure that each header line does not exceed the maximum line length.
- Split each header line by the colon (":") character to separate the header name and value.
- Store the header name and value in the map, converting the header name to lowercase.
- Ensure that the number of headers does not exceed the maximum allowed limit.
- Verify that the "Upgrade" header is set to "websocket".
- Verify that the "Connection" header is set to "Upgrade".
- Create an instance of
MessageDigestusing the SHA-1 algorithm. - Update the digest with the base64-encoded nonce and a constant string.
- Generate the expected accept key by encoding the digest into base64 format.
- Retrieve the received accept key from the headers.
- Ensure that the received accept key matches the expected accept key.
The server does not support Sec-WebSocket-Extensions or Sec-WebSocket-Protocol, so these steps are skipped.
The server does not support Sec-WebSocket-Extensions or Sec-WebSocket-Protocol, so these steps are skipped.
The handshake method in the io.nats.client.support.WebSocket class is responsible for performing the handshake process between the client and server when establishing a WebSocket connection.
Here is a breakdown of what the method does:
- Creates an
HttpRequestobject and sets the necessary headers for the handshake. - Invokes any interceptors that have been registered with the method.
- Writes the request string to the output stream of the socket.
- Reads the response line from the input stream and checks that it starts with the expected response code "101".
- Parses the HTTP headers from the response and checks that the "Upgrade" and "Connection" headers are set to "websocket" and "upgrade" respectively.
- Calculates the accept key for the "Sec-WebSocket-Accept" header by hashing the generated key with a predefined value and encoding it to Base64.
- Verifies that the received "Sec-WebSocket-Accept" header value matches the calculated accept key.
- Performs additional checks that are not currently used by the
nats-serverimplementation.
Overall, the handshake method ensures that the server accepts the WebSocket connection by validating the response and headers received during the handshake process.

private static String readLine(byte[] buffer, InputStream in) throws IOException {
int offset = 0;
int lastCh = -1;
while (true) {
int ch = in.read();
switch(ch) {
case -1:
// Premature EOF (everything should be terminated with \n)
return new String(buffer, 0, offset, StandardCharsets.ISO_8859_1);
case '\n':
// Found \n, remove \r if it is there:
return new String(buffer, 0, '\r' == lastCh ? offset - 1 : offset, StandardCharsets.ISO_8859_1);
}
// Line length exceeded:
if (offset >= buffer.length) {
return null;
}
buffer[offset++] = (byte) ch;
lastCh = ch;
}
}The readLine method in the WebSocket class is used to read a line from an input stream. It takes a byte array called buffer and an input stream called in as parameters.
Here is a step-by-step description of what the method does:
-
Initialize variables:
-
offsetis set to 0, which represents the current index in thebufferarray. -
lastChis set to -1, which represents the last character read from the input stream.
-
-
Enter an infinite loop:
- This loop will continue until the method explicitly returns a value.
-
Read a character from the input stream:
- The
in.read()method is called to read the next character from the input stream. - The character is stored in the variable
ch.
- The
-
Process the character:
-
The method uses a
switchstatement to check the value ofch. -
If
chis -1:- This indicates that the end of the input stream has been reached (premature EOF).
- The method constructs a new string using the
bufferarray, from index 0 tooffset, using the ISO-8859-1 character encoding. - The constructed string is returned as the result of the method.
-
If
chis '\n' (newline character):- This indicates that a complete line has been read.
- The method constructs a new string using the
bufferarray, from index 0 tooffset, using the ISO-8859-1 character encoding. - If the last character read (
lastCh) is '\r' (carriage return character), it means that the line might contain a Windows-style line ending.- In this case, the method subtracts 1 from
offsetto remove the '\r' character from the line.
- In this case, the method subtracts 1 from
- The constructed string is returned as the result of the method.
-
If none of the above conditions are met (line length exceeded):
- The method checks if the
offsetis greater than or equal to the length of thebufferarray. - If the condition is true, the method returns
nullto indicate that the line length has exceeded the buffer size.
- The method checks if the
-
-
Store the read character in the
bufferarray:- The read character is cast to a byte and stored in the
bufferarray at the currentoffsetindex. - The
offsetis then incremented.
- The read character is cast to a byte and stored in the
-
Update the
lastChvariable:- The
lastChvariable is updated with the value of the current character (ch).
- The
-
Repeat the loop to read the next character from the input stream.
Note: The method assumes that the input stream contains lines terminated with either '\n' or '\r\n' characters.
The readLine method is used to read a line of text from an input stream in the context of a WebSocket. It takes in a byte[] buffer and an InputStream as parameters.
The method reads characters from the input stream until it encounters either the end of the stream or a line break character ('\n'). If it reaches the end of the stream, it returns the contents of the buffer as a string.
If it encounters a line break character, it checks if the previous character was a carriage return character ('\r'). If so, it removes it from the buffer before returning the contents as a string.
If the line length exceeds the size of the buffer, the method returns null.
The method uses the StandardCharsets.ISO_8859_1 character encoding when converting the buffer to a string.

RandomUtils
The RandomUtils class is an abstract class that provides various utility methods for generating random values. It is designed to be extended by concrete classes, which can then access these random utility methods to generate random numbers, strings, and other types of values. This class serves as a convenient tool for developers who need to incorporate randomization into their software applications.
public static long nextLong(Random rng, long maxValue) {
// error checking and 2^x checking removed for simplicity.
long bits;
long val;
do {
bits = (rng.nextLong() << 1) >>> 1;
val = bits % maxValue;
} while (bits - val + (maxValue - 1) < 0L);
return val;
}The nextLong method, defined in the io.nats.client.support.RandomUtils class, generates a random long integer value within a specified range.
public static long nextLong(Random rng, long maxValue)-
rng: ARandomobject used for generating random numbers. -
maxValue: The upper bound (exclusive) of the range within which the randomlongvalue should be generated.
- Error checking and checking whether
maxValueis a power of 2 are removed for simplicity. - Declare two
longvariables,bitsandval, to store the generated random bits and the final random value, respectively. - Start a do-while loop that will run until a suitable random value is found.
- Generate random bits using the
nextLong()method of therngobject and store them in thebitsvariable. - Shift the bits one position to the left and then one position back to the right using the bitwise left shift (
<<) and the bitwise right shift (>>>) operators, respectively. This operation is performed to ensure that thebitsvalue is non-negative (signed shift right operator preserves the sign bit). - Calculate the remainder of dividing
bitsbymaxValueand store it in thevalvariable. This will give a random value within the range[0, maxValue). - Check if the difference between
bits,val, andmaxValue - 1is less than0L. If the condition is true, it means that the generated value is larger thanmaxValue - 1, which would create a bias towards smaller values. In this case, the loop repeats to generate a new random value. - If the condition in step 7 is false, the loop is exited, and the
valvariable containing the randomly generated value is returned as the result of the method.
The method nextLong in the class io.nats.client.support.RandomUtils generates a pseudo-random long value within a specified range.
The method takes two parameters: rng, which is an instance of the Random class used to generate the random values, and maxValue, which represents the upper bound of the range (exclusive).
Inside the method, the logic is as follows:
- Generate a random long value using the provided
rnginstance. - Shift the generated value one bit to the left and then one bit to the right, effectively clearing the sign bit.
- Calculate the remainder of dividing the resulting value by
maxValueto bring it within the specified range. - Repeat steps 1-3 until a valid value is obtained, satisfying the condition
bits - val + (maxValue - 1) < 0L. - Return the generated value.
This method provides a way to generate random long values within a given range using the provided random number generator.

public static long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE);
buffer.put(bytes);
// need flip
buffer.flip();
return buffer.getLong();
}The bytesToLong method is a static method defined in the io.nats.client.support.RandomUtils class. The method takes in a byte array as a parameter and converts it into a long value. Here is a step-by-step description of what the method does:
-
Allocate a new
ByteBufferwith the capacity equivalent toLong.SIZE. This means the buffer will have enough space to hold a long value. -
Copy the contents of the
bytesparameter into the buffer using theputmethod. This will fill the buffer with the bytes from the byte array. -
Call the
flipmethod on the buffer. This method is used to prepare the buffer for reading. It sets the buffer's limit to the current position and resets the position to 0. -
Retrieve the long value from the buffer using the
getLongmethod. This method reads eight bytes from the buffer and interprets them as a long value. -
Return the long value.
In summary, the bytesToLong method takes a byte array, copies it into a ByteBuffer, flips the buffer to prepare it for reading, and then retrieves a long value from the buffer.
The bytesToLong method in the io.nats.client.support.RandomUtils class is a utility method that converts a byte array to a long value.
Here's how it works:
- The method takes a byte array (
bytes) as input. - It creates a
ByteBufferobject with a size ofLong.SIZE(which is the size of a long value in bits). - The byte array is then copied into the
ByteBufferusing theputmethod. - The
flipmethod is called on theByteBufferto prepare it for reading. - Finally, the
getLongmethod is called on theByteBufferto retrieve the long value.
In summary, the bytesToLong method allows you to convert a byte array to a long value using the ByteBuffer class.

Digester
The Digester class is a utility class for making digesting data. It provides methods that can be used to compute digests of data using various algorithms.
public boolean matches(String digestEntry) {
String algo = digest.getAlgorithm().toUpperCase();
if (!digestEntry.toUpperCase().startsWith(algo)) {
return false;
}
// + 1 for equals
return getDigestValue().equals(digestEntry.substring(algo.length() + 1));
}This method is defined in the class io.nats.client.support.Digester and takes a String parameter named digestEntry. It returns a boolean value.
-
digestEntry: The digest entry that needs to be matched.
- The method starts by converting the algorithm of the
digestobject (assuming it is an instance variable in the class) to uppercase using thetoUpperCase()method. - It then checks if the
digestEntrystring starts with the uppercase algorithm string. If it doesn't, the method returnsfalse. - If the
digestEntrystring does start with the algorithm string, the method compares the digest value obtained from thegetDigestValue()method (assuming it is a method in the same class) with the substring ofdigestEntryobtained by removing the algorithm string plus one additional character (to remove the space after the algorithm). - If the digest value and the substring match, the method returns
true. Otherwise, it returnsfalse.
The matches method in the Digester class is used to check whether a given digestEntry string matches the expected algorithm and digest value.
The method first compares the starting characters of the digestEntry string with the uppercase value of the algorithm used to generate the digest. If they do not match, the method returns false.
If the starting characters match, the method then extracts the substring after the algorithm name and checks if it is equal to the expected digest value by calling the getDigestValue() method. If the extracted digest value matches the expected value, the method returns true, indicating a successful match.
Overall, this method provides a way to verify if a given digest entry matches the expected algorithm and digest value.

IncomingHeadersProcessor
The IncomingHeadersProcessor class is a public class that is responsible for processing incoming headers. It handles the processing of headers that are received by the software application.
private void initHeader(byte[] serialized, int len, Token tCrlf, boolean hadStatus) {
// REGULAR HEADER
Token peek = new Token(serialized, len, tCrlf, null);
while (peek.isType(TokenType.TEXT)) {
Token tKey = new Token(serialized, len, tCrlf, TokenType.KEY);
Token tVal = new Token(serialized, len, tKey, null);
if (tVal.isType(TokenType.SPACE)) {
tVal = new Token(serialized, len, tVal, null);
}
if (tVal.isType(TokenType.TEXT)) {
tCrlf = new Token(serialized, len, tVal, TokenType.CRLF);
} else {
tVal.mustBe(TokenType.CRLF);
tCrlf = tVal;
}
if (headers == null) {
headers = new Headers();
}
headers.add(tKey.getValue(), tVal.getValue());
peek = new Token(serialized, len, tCrlf, null);
}
peek.mustBe(TokenType.CRLF);
}The initHeader method in class io.nats.client.support.IncomingHeadersProcessor is responsible for initializing the headers based on the provided serialized byte array.
Here is a step-by-step description of what the method does:
-
Initialize a
Tokenobjectpeekwith the provided serialized byte array, length, and a token of typetCrlf. -
Start a
whileloop that iterates as long as thepeektoken is of typeTEXT. -
Within the loop, create a new
TokenobjecttKeywith the same parameters aspeek, but with a token type ofKEY. -
Create a new
TokenobjecttValwith the same parameters astKey, but with anulltoken type. -
Check if
tValis of typeSPACE. If it is, create a newTokenobjecttValusing the currenttValas the base token andnullas the token type. -
Check if
tValis of typeTEXT. If it is, create a newTokenobjecttCrlfusing the currenttValas the base token and a token type ofCRLF. Otherwise,tValmust be of typeCRLF, so settCrlftotVal. -
Check if the
headersobject isnull. If it is, initialize a newHeadersobject. -
Add the key-value pair represented by
tKeyandtValto theheadersobject. -
Update the
peektoken to the next token in the array by creating a newTokenobject with the same parameters astCrlf, but with a token type ofnull. -
Check that the
peektoken is of typeCRLF. If it is not, an exception is thrown. -
Repeat the loop until the
peektoken is not of typeTEXT.
Once the loop finishes, the method will have processed all the headers in the serialized byte array and stored them in the headers object.
The initHeader method is used to initialize the headers of a message. It takes in a serialized byte array, its length, a token representing the carriage return line feed (CRLF), and a boolean indicating whether the message had a status.
The method processes the serialized header information by iterating over the tokens. It starts by creating a peek token and checks if it is of type TEXT. If it is, it creates a tKey token representing the key of the header using the serialized byte array, its length, and the CRLF token.
Next, it creates a tVal token representing the value of the header. If the tVal token is of type SPACE, it creates a new token without a parent to eliminate the space.
Then, it checks if the tVal token is of type TEXT or CRLF. If it is TEXT, it sets the CRLF token to a new token with the tVal token as its parent. If it is CRLF, it sets the CRLF token to the tVal token itself.
If the headers object is null, it creates a new Headers object.
Finally, it adds the key-value pair to the headers object, and updates the peek token to continue processing the next token. This process continues until the peek token is of type CRLF.
The method ensures that the last token must be of type CRLF.

private Token initStatus(byte[] serialized, int len, Token tSpace) {
Token tCode = new Token(serialized, len, tSpace, TokenType.WORD);
Token tVal = new Token(serialized, len, tCode, null);
Token crlf;
if (tVal.isType(TokenType.SPACE)) {
tVal = new Token(serialized, len, tVal, TokenType.TEXT);
crlf = new Token(serialized, len, tVal, TokenType.CRLF);
} else {
tVal.mustBe(TokenType.CRLF);
crlf = tVal;
}
inlineStatus = new Status(tCode, tVal);
return crlf;
}The initStatus method in the IncomingHeadersProcessor class is responsible for initializing the status of the incoming headers based on the provided byte[] serialized data.
Here is a step-by-step description of what the method does:
-
The method takes in three parameters:
serialized(the byte array containing the serialized data),len(the length of the serialized data), andtSpace(a token object of typeToken). -
It creates a new token object
tCodeusing theserialized,len,tSpace, andTokenType.WORD. ThetCodetoken represents the code of the status. -
It creates a new token object
tValusing theserialized,len,tCode, andnull. Initially,tValis set tonull. -
It creates a new token object
crlfto represent the carriage return line feed (CRLF) characters. The value ofcrlfwill depend on the type oftVal. -
If
tValis of typeTokenType.SPACE, it means that there is a space character between the status code and the status value. In this case,tValis replaced with a new token object created using theserialized,len,tVal, andTokenType.TEXT. Then,crlfis set to a new token object created using theserialized,len,tVal, andTokenType.CRLF. -
If
tValis not of typeTokenType.SPACE, it means that there is no space character between the status code and the status value. In this case,tValmust be of typeTokenType.CRLF, andcrlfis set totVal. -
A new
Statusobject is created using thetCodeandtValtokens, and assigned to theinlineStatusmember variable. -
Finally, the method returns the
crlftoken.
This method essentially parses the serialized data, extracts the status code and value, creates a Status object, and returns the token representing the CRLF characters.
The initStatus method in the IncomingHeadersProcessor class takes in a byte array, its length, and a Token object as parameters. It initializes and sets the inlineStatus variable by creating a new Status object with tCode and tVal as its parameters. It then returns a Token object named crlf.

NatsKeyValueUtil
The NatsKeyValueUtil class is an abstract class designed to provide utility methods for working with key-value stores in the Nats system. This class serves as a base for other classes that implement specific functionality for different types of key-value stores.
public static String trimPrefix(String bucketName) {
if (bucketName.startsWith(KV_STREAM_PREFIX)) {
return bucketName.substring(KV_STREAM_PREFIX.length());
}
return bucketName;
}The trimPrefix method is defined in the io.nats.client.support.NatsKeyValueUtil class and is used to remove a specific prefix string from the beginning of a given bucketName string.
public static String trimPrefix(String bucketName)-
bucketName- The string from which the prefix needs to be removed.
-
String- The modifiedbucketNamestring after removing the prefix.
- Check if the
bucketNamestarts with the prefix stringKV_STREAM_PREFIX. - If it starts with the prefix, then remove the prefix from the
bucketNamestring by using thesubstringmethod with the indexlengthof theKV_STREAM_PREFIX. - Return the modified
bucketNamestring without the prefix. - If the
bucketNamedoes not start with the prefix, then simply return thebucketNameas it is.
public static String trimPrefix(String bucketName) {
if (bucketName.startsWith(KV_STREAM_PREFIX)) {
return bucketName.substring(KV_STREAM_PREFIX.length());
}
return bucketName;
}The method trimPrefix in class NatsKeyValueUtil is a utility method that takes a String parameter bucketName and returns the bucketName with the prefix removed if it starts with the constant KV_STREAM_PREFIX.
If the bucketName starts with the KV_STREAM_PREFIX, the method returns the portion of the bucketName that comes after the KV_STREAM_PREFIX by using the substring method.
If the bucketName does not start with the KV_STREAM_PREFIX, the method simply returns the original bucketName.

ByteArrayBuilder
ByteArrayBuilder is a public class that extends BuilderBase. It is used to efficiently build byte arrays.
public int copyTo(byte[] dest, int destPos) {
int len = length();
byte[] hb = buffer.array();
System.arraycopy(hb, 0, dest, destPos, len);
return len;
}The copyTo method in the io.nats.client.support.ByteArrayBuilder class is responsible for copying the contents of the internal buffer to a specified destination array.
Here is a step-by-step description of what the method does:
-
Retrieve the length of the internal buffer using the
length()method. -
Access the underlying byte array by calling
buffer.array(), wherebufferis an instance variable of typeByteBuffer. -
Use the
System.arraycopy()method to copy the bytes from the internal buffer to the destination array. The source array ishb(the underlying byte array) and the starting position in the source array is 0. The destination array isdest, and the starting position in the destination array isdestPos. The number of bytes to copy islen(the length of the internal buffer). -
Return the length of the copied data.
Please note that this description assumes that you have already imported the required classes and have instantiated an object of the ByteArrayBuilder class.
The copyTo method in the ByteArrayBuilder class, defined in the io.nats.client.support package, is used to copy the contents of the builder's internal buffer to a destination byte array.
The method takes two parameters: dest, which is the destination byte array where the contents will be copied to, and destPos, which is the starting position in the destination byte array where the copying will begin.
The method first retrieves the length of the data in the builder using the length method. Then, it accesses the internal buffer of the builder using the buffer.array() method and assigns it to the hb variable.
Finally, using the System.arraycopy() method, it copies the contents of the internal buffer (hb) to the specified destination byte array (dest) starting at the given position (destPos) and copied data length (len). The method then returns the length of the copied data.
In summary, the copyTo method allows you to efficiently copy the contents of the ByteArrayBuilder to a destination byte array, starting from a specified position.

public ByteArrayBuilder ensureCapacity(int bytesNeeded) {
int bytesAvailable = buffer.capacity() - buffer.position();
if (bytesAvailable < bytesNeeded) {
ByteBuffer newBuffer = ByteBuffer.allocate(bufferAllocSize(buffer.position() + bytesNeeded, allocationSize));
newBuffer.put(buffer.array(), 0, buffer.position());
buffer = newBuffer;
}
return this;
}The ensureCapacity method in the ByteArrayBuilder class defined in the io.nats.client.support package is used to ensure that the internal buffer has enough capacity to hold the specified number of bytes.
Here is a step-by-step description of what the method does:
-
Get the number of bytes available in the buffer by subtracting the current position from the total capacity of the buffer.
-
Check if the number of bytes available is less than the number of bytes needed.
-
If the condition in step 2 is true, create a new
ByteBufferwith a capacity calculated based on the current position of the buffer and the number of bytes needed. -
Copy the content of the existing buffer into the new buffer up to the current position.
-
Set the internal buffer reference to the new buffer.
-
Return a reference to the
ByteArrayBuilderobject to allow method chaining.
This method ensures that the ByteArrayBuilder has enough capacity to hold the specified number of bytes by creating a new buffer if necessary and copying the existing content into the new buffer.
The ensureCapacity method in the ByteArrayBuilder class is used to ensure that the buffer used by the ByteArrayBuilder has enough capacity to accommodate the specified number of bytes.
The method first calculates the number of bytes available in the current buffer by subtracting the buffer's position from its capacity. If the available capacity is less than the requested number of bytes, a new buffer is allocated with an increased size using the bufferAllocSize method.
The contents of the existing buffer are then copied into the new buffer, and the reference to the new buffer is assigned to the buffer field of the ByteArrayBuilder. Finally, the method returns a reference to the ByteArrayBuilder object itself.
In summary, the ensureCapacity method ensures that the ByteArrayBuilder has enough capacity to accommodate the requested number of bytes by reallocating a larger buffer if necessary.

public ByteArrayBuilder append(CharBuffer src, Charset charset) {
if (src == null) {
append(NULL, 0, 4);
} else {
append(src.toString().getBytes(charset));
}
return this;
}The append method in the ByteArrayBuilder class is used to add data to the builder's internal byte array.
Here is a step-by-step description of what the method does based on its body:
-
It takes two parameters:
src, which is aCharBuffercontaining the data to be appended, andcharset, which is the character set used for encoding the data. -
If the
srcparameter isnull, it calls theappendmethod of theByteArrayBuilderclass with the following parameters:- The
NULLconstant, which is a reference to a byte array representing the valuenull. - The offset (
0), which specifies the starting index in the byte array. - The length (
4), which indicates the number of bytes to be copied from the byte array.
- The
-
If the
srcparameter is notnull, it converts theCharBufferto aStringby calling itstoStringmethod, and then gets the byte representation of the string using the specifiedcharsetencoding. This byte array is then passed to the overloadedappendmethod of theByteArrayBuilderclass. -
After appending the data to the builder's internal byte array, the method returns a reference to the
ByteArrayBuilderobject itself, enabling method chaining.
Overall, the append method allows you to add data to the ByteArrayBuilder by providing a CharBuffer or a String object, and it takes care of converting the data to bytes using the specified character encoding.
The append method in the ByteArrayBuilder class of the io.nats.client.support package is used to add characters from a CharBuffer to the byte array.
First, it checks if the src (CharBuffer) is null. If it is, it appends NULL to the byte array. Otherwise, it converts the CharBuffer to a string using the specified charset and converts that string to bytes. Finally, it appends the resulting byte array to the existing byte array.
After performing these operations, the append method returns a reference to the current ByteArrayBuilder object, allowing for method chaining.

public ByteArrayBuilder append(byte[] src) {
if (src.length > 0) {
ensureCapacity(src.length);
buffer.put(src, 0, src.length);
}
return this;
}The append method in the ByteArrayBuilder class is used to append a byte array to the existing builder object. Here is a step-by-step description of what the method does:
- Check if the length of the provided byte array (
src) is greater than zero. - If the length is greater than zero, proceed to the next step. Otherwise, return the current builder object.
- Call the
ensureCapacitymethod to ensure that the internal buffer of the builder has enough space to accommodate the new bytes being appended. - Use the
putmethod to copy the bytes from thesrcarray into the internal buffer of the builder, starting from index 0 and copyingsrc.lengthnumber of bytes. - Finally, return the updated builder object.
Note: The ensureCapacity method is not provided in the given code snippet. It is assumed to handle the resizing of the internal buffer to accommodate the new bytes if necessary.
The append method in the ByteArrayBuilder class (defined in io.nats.client.support) allows you to append a byte array to the existing byte array builder.
This method takes in a byte[] parameter named src. It first checks if the length of the src array is greater than zero. If it is, it ensures that the builder has enough capacity to accommodate the new byte array by calling the ensureCapacity method.
Finally, it uses the put method of the internal buffer to copy the content of the src array to the builder's buffer starting from index 0.
After appending the src array, the method returns a reference to the same ByteArrayBuilder object, allowing method chaining.

public ByteArrayBuilder append(byte[] src, int len) {
if (len > 0) {
ensureCapacity(len);
buffer.put(src, 0, len);
}
return this;
}The append method in the ByteArrayBuilder class of the io.nats.client.support package is used to append a byte array to the buffer managed by the ByteArrayBuilder object.
Here is a step-by-step description of what the append method does:
-
Check if the given length
lenis greater than zero. If it is not, the method does nothing and returns the currentByteArrayBuilderobject. -
If the length
lenis greater than zero, the method proceeds to the next step. -
Ensure that the buffer has enough capacity to accommodate the additional data. If the current capacity of the buffer is not sufficient, it will be increased to meet the required capacity.
-
Copy the first
lenbytes from the source byte arraysrcinto the buffer managed by theByteArrayBuilderobject. Theputmethod of the buffer is used for this purpose. -
The method returns the current
ByteArrayBuilderobject, which allows for method chaining.
In summary, the append method appends a specified number of bytes from a given byte array to the buffer managed by the ByteArrayBuilder object, ensuring that the buffer has enough capacity to hold the data.
The append method defined in the ByteArrayBuilder class in the io.nats.client.support package is used to append bytes from a source byte array into the ByteArrayBuilder object. The method takes two parameters: src, which is the source byte array, and len, which specifies the number of bytes to append from the source array.
The method first checks if the len value is greater than 0, indicating that there are bytes to be appended. If len is greater than 0, the method ensures that the ByteArrayBuilder has enough capacity to accommodate the additional bytes.
Finally, the method uses the put method of the internal buffer object to append the specified number of bytes from the source array into the ByteArrayBuilder.
The method returns the updated ByteArrayBuilder object, allowing for chained method calls if needed.

public ByteArrayBuilder append(byte[] src, int offset, int len) {
if (len > 0) {
ensureCapacity(len);
buffer.put(src, offset, len);
}
return this;
}The append method in the io.nats.client.support.ByteArrayBuilder class is used to add a specified portion of a byte array to the current buffer.
Here is a step by step description of what the method does:
- Check if the specified length (
len) is greater than 0. - If the length is greater than 0, proceed to the next step.
- Call the
ensureCapacitymethod to make sure that the buffer has enough capacity to accommodate the specified length. - Use the
putmethod of the buffer to copy the specified portion of the source byte array (src) into the buffer. The offset and length of the portion to be copied are specified by theoffsetandlenparameters. - Return a reference to the current instance of the
ByteArrayBuilderto allow for method chaining.
Overall, the append method appends a portion of a byte array to the buffer and returns a reference to the ByteArrayBuilder.
The append method, defined in the ByteArrayBuilder class of the io.nats.client.support package, is used to append a specified portion of a byte array to the existing byte array held by the builder.
The method takes three arguments: src (the source byte array from which the portion needs to be appended), offset (the starting index in the source array from where the portion begins), and len (the length of the portion to be appended).
First, the method checks if the length of the portion to be appended is greater than zero. If it is, the method proceeds to ensure that the builder's internal buffer has enough capacity to accommodate the new portion. If necessary, the buffer's size is increased.
Finally, the portion of the source byte array specified by the offset and len arguments is copied into the builder's buffer using the put method. The builder's reference is then returned.
In summary, the append method is responsible for appending a specified portion of a byte array to the byte array held by the builder, ensuring capacity if needed.

public ByteArrayBuilder append(ByteArrayBuilder bab) {
if (bab != null && bab.length() > 0) {
append(bab.buffer.array(), 0, bab.length());
}
return this;
}The append method in the ByteArrayBuilder class is used to concatenate the contents of another ByteArrayBuilder object to the current object.
Here are the steps performed by this method:
- Check if the provided ByteArrayBuilder object, bab, is not null and has a length greater than 0.
- If bab is not null and has a length greater than 0: a. Retrieve the buffer array from bab using bab.buffer.array(). b. Call the append method of the current ByteArrayBuilder object, passing the buffer array, a starting index of 0, and the length of bab as parameters.
- Return the current ByteArrayBuilder object.
In summary, this append method adds the contents of another ByteArrayBuilder object to the current object, as long as the provided ByteArrayBuilder is not null and has a non-zero length.
The append method in the ByteArrayBuilder class in the io.nats.client.support package is used to append the contents of another ByteArrayBuilder object to the current ByteArrayBuilder object.
In the method, it first checks if the bab object is not null and if it has a length greater than zero. If these conditions are met, it calls the append method again with the byte array, start index, and length of the bab object. This effectively appends the contents of bab to the current ByteArrayBuilder.
Finally, it returns the current ByteArrayBuilder object, allowing for method chaining if desired.

NatsObjectStoreUtil
NatsObjectStoreUtil is an abstract class representing a utility for interacting with an object store in the context of a Nats system. This class provides methods for managing and manipulating objects within the store, allowing software engineers to efficiently store and retrieve data.
WebsocketInputStream
The WebsocketInputStream class is a Java class that extends the InputStream class. It provides a specialized input stream for handling WebSocket connections. With this class, you can read data from a WebSocket connection as if it were a regular input stream.
public int read(byte[] buffer, int offset, int length) throws IOException
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
// Just in case we get headers with empty payloads:
while (0 == header.getPayloadLength()) {
if (!readHeader()) {
return -1;
}
}
if (header.getOpCode() == OpCode.CLOSE) {
// Ignore the websocket close message body:
in.skip(header.getPayloadLength());
return -1;
}
final long headerPayloadLength = header.getPayloadLength();
final int payloadLength = Math.min(length, headerPayloadLength > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) headerPayloadLength);
length = in.read(buffer, offset, payloadLength);
if (-1 == length) {
return length;
}
return header.filterPayload(buffer, offset, length);
}The read method in the io.nats.client.support.WebsocketInputStream class is used to read data from a WebSocket connection. Here is a step-by-step description of what this method does based on its body:
-
Check if the payload length in the header is zero. This is done in a while loop to handle the case where headers with empty payloads are received. If the payload length is zero, it means there is no data to read and the next header is fetched.
-
If the operation code in the header is
CLOSE, it means it is a WebSocket close message. In this case, the method skips the length specified in the header, ignoring the close message body, and returns -1 to indicate the end of the stream. -
Get the payload length from the header and determine the length of the data to be read. This length is the minimum of the specified length parameter and the payload length, considering the maximum value of an integer.
-
Invoke the
readmethod of the underlying input stream (in) to read the data into the given buffer, starting at the specified offset, and up to the determined payload length. The actual number of bytes read is stored in thelengthvariable. -
Check if the end of the stream has been reached. If the value returned by the
readmethod is -1, it means no more data can be read and the method returns -1. -
Filter the payload using the
filterPayloadmethod in the header. This method applies any filtering or transformations to the payload before returning it. -
Finally, the method returns the filtered payload length.
This read method handles the reading of WebSocket data, excluding the header and any close message, and applies any necessary payload filtering before returning the data.
The read method in the WebsocketInputStream class is responsible for reading data from the input stream of a WebSocket connection.
Here are the steps performed by the method:
- It checks if the headers have empty payloads. If so, it continues reading the headers until a non-empty payload is found.
- If the OpCode of the header is CLOSE, it skips the WebSocket close message body and returns -1 to indicate the end of the stream.
- It determines the payload length based on the smaller of the provided length or the header's payload length. If the header's payload length is greater than
Integer.MAX_VALUE, it sets the payload length toInteger.MAX_VALUE. - It reads data from the underlying input stream
ininto the provided buffer starting from the specified offset and up to the determined payload length. - If the read length is -1, it indicates the end of the stream and returns -1.
- Finally, it applies a filter to the payload in the buffer, starting from the specified offset and with the read length, using the
header.filterPayloadmethod. The filtered payload is returned as the result of thereadmethod.

public int read() throws IOException
@Override
public int read() throws IOException {
int result = read(oneByte, 0, 1);
if (-1 == result) {
return result;
}
return oneByte[0];
}The read() method in the WebsocketInputStream class, located in the io.nats.client.support package, is used to read bytes from the websocket input stream.
Here is a step-by-step description of what the method is doing:
-
The method overrides the
read()method from theInputStreamclass and indicates that it can throw anIOException. -
In the method, a variable named
resultis declared to hold the result of the next step. -
The
read()method is called on theWebsocketInputStreamobject, passing in theoneBytearray, starting at index 0, and specifying the number of bytes to read as 1. This method call reads one byte from the websocket input stream and stores it in theoneBytearray. -
The
resultvariable is assigned the value returned by theread()method. If the value is equal to-1, it signifies the end of the stream has been reached, so theresultis returned. -
If the
resultis not equal to-1, the method returns the first element of theoneBytearray, which represents the byte that was read.
In summary, the read() method reads one byte from the websocket input stream, stores it in the oneByte array, and returns that byte. If the end of the stream is reached, it returns -1.
This method, read, is an override of the read method defined in the WebsocketInputStream class in the io.nats.client.support package.
The purpose of this method is to read a single byte from the input stream and return it as an integer. It does this by calling the read method with a byte array of size 1, and then returning the first element of that array as an integer. If the result of the read operation is -1 (indicating the end of the input stream), then -1 is returned.

private boolean readHeader() throws IOException {
int len = 0;
while (len < 2) {
int result = in.read(buffer, len, 2 - len);
if (result < 0) {
return false;
}
len += result;
}
int headerSize = WebsocketFrameHeader.size(buffer, 0);
if (headerSize > 2) {
while (len < headerSize) {
int result = in.read(buffer, len, headerSize - len);
if (result < 0) {
return false;
}
len += result;
}
}
header.write(buffer, 0, headerSize);
return true;
}The readHeader method is defined in the WebsocketInputStream class and is responsible for reading the header of a WebSocket frame. Here is a step-by-step description of its functionality:
- Create a variable
lenand set it to0. - Start a while loop and continue until
lenis less than2. - Read from the input stream (
in) and store the result in a variableresultusing thereadmethod of the input stream. Thebufferis used as the destination for the read bytes. The number of bytes to read is2 - len, which ensures that two bytes are read in total. - Check if
resultis less than0. If true, it means that the end of the stream has been reached, so returnfalse. - Increment
lenby the value ofresultto keep track of the number of bytes read so far. - If the code execution reaches this point, it means that
lenis at least2. - Calculate the size of the header by calling the
sizemethod of theWebsocketFrameHeaderclass, passing in thebufferand0as parameters. Store the result in a variableheaderSize. - Check if
headerSizeis greater than2. If true, it means that the header contains metadata beyond the initial two bytes. - Start a while loop and continue until
lenis less thanheaderSize. - Read from the input stream (
in) and store the result in a variableresultusing thereadmethod of the input stream. The number of bytes to read isheaderSize - len, which ensures that the remaining bytes of the header are read. - Check if
resultis less than0. If true, it means that the end of the stream has been reached, so returnfalse. - Increment
lenby the value ofresultto keep track of the number of bytes read so far. - If the code execution reaches this point, it means that all the bytes of the header have been read.
- Write the header bytes to the
headerobject using thewritemethod, passing in thebuffer,0, andheaderSizeas parameters. - Return
trueto indicate that the header has been successfully read.
The readHeader method in the io.nats.client.support.WebsocketInputStream class is responsible for reading the header of a WebSocket frame from an input stream.
The method initially reads 2 bytes from the input stream and stores them in a buffer. If the result is less than 0 (signifying the end of the input stream), the method returns false. Otherwise, it keeps reading from the input stream until it has read 2 bytes.
The method then calculates the header size using the WebsocketFrameHeader.size method, passing the buffer and the offset 0. If the header size is greater than 2, the method continues reading from the input stream until it has read headerSize bytes.
Finally, the method writes the header bytes from the buffer to the header object and returns true.
Overall, the readHeader method is responsible for reading and processing the header of a WebSocket frame from an input stream.

Token
The Token class represents a token, which is an essential element for parsing and processing data. This class provides a structure to store and manage tokens, allowing engineers to easily manipulate and analyze data using tokens.
JsonParser
The JsonParser class is a public class that provides functionality for parsing JSON data. It allows developers to easily convert JSON strings or files into Java objects, making it easier to work with JSON data in a structured and organized manner. The class offers various methods for parsing JSON, including parsing from a string, parsing from a file, and parsing directly from an input stream. Additionally, it supports parsing of JSON arrays, objects, and individual values, supporting a wide range of JSON data structures.
public static JsonValue parseUnchecked(char[] json) {
try {
return parse(json);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}This method is a public static method that takes a single parameter json of type char[] and returns a JsonValue.
-
The method starts by wrapping the core parsing logic in a try-catch block.
-
Inside the try block, the
parse(json)method is called to parse the given JSON string. -
If the JSON parsing is successful, the parsed
JsonValueobject is returned. -
If an exception of type
JsonParseExceptionis caught during the parsing process, it is wrapped in aRuntimeExceptionand rethrown. -
Upon catching the
JsonParseException, a new instance ofRuntimeExceptionis created with the caught exception as the cause. -
The
RuntimeExceptionis then thrown, propagating the original exception as an unchecked exception.
Note: This method provides a convenient way to parse JSON strings without explicitly handling the checked JsonParseException, allowing for cleaner code at the calling code level. However, it also introduces a risk of catching other types of exceptions and throwing them as unchecked exceptions. Hence, caution should be exercised while using this method.
The parseUnchecked method in the JsonParser class is a static method that takes a char array containing JSON data as input and returns a JsonValue object.
Internally, the method calls another method parse to parse the JSON data. If there is a JsonParseException during the parsing process, the method catches it and throws a RuntimeException with the same exception as the cause.
This method is useful when you want to parse JSON data without explicitly handling the exception. However, be aware that this method may throw a RuntimeException if the parsing fails.

public static JsonValue parseUnchecked(char[] json, int startIndex) {
try {
return parse(json, startIndex);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}This method is used to parse a JSON string into a Java JsonValue object. It takes a character array representing the JSON string and the starting index as parameters. If the JSON parsing fails and throws a JsonParseException, it catches the exception and rethrows a RuntimeException.
public static JsonValue parseUnchecked(char[] json, int startIndex)-
json: a character array representing the JSON string to be parsed. -
startIndex: the starting index in thejsonarray from where parsing should begin.
JsonValue : a Java object representing the parsed JSON value.
- Invoke the
parsemethod with thejsonandstartIndexparameters. - If the parsing is successful, return the parsed
JsonValue. - If a
JsonParseExceptionis thrown during the parsing process: a. Catch the exception. b. Throw aRuntimeExceptionwith the caughtJsonParseExceptionas its cause.
The parseUnchecked method, defined in the JsonParser class in the io.nats.client.support package, is responsible for parsing a JSON string into a JsonValue object without explicitly handling any exceptions.
The method takes a char array json and an int startIndex as parameters. It internally calls the parse method from the same class, passing the json and startIndex values. If the parse method throws a JsonParseException, it catches the exception and rethrows it as a RuntimeException.
In other words, the parseUnchecked method provides a simplified way to parse a JSON string without having to handle the JsonParseException explicitly. However, it does come with the risk of an unchecked exception being thrown if the given JSON string is invalid.

public static JsonValue parseUnchecked(char[] json, Option... options) {
try {
return parse(json, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}The parseUnchecked method in the io.nats.client.support.JsonParser class is responsible for parsing a JSON string and returning a JsonValue object. Below is a step-by-step description of what this method does:
- The
parseUncheckedmethod accepts two parameters:json, a character array containing the JSON string to be parsed, andoptions, an optional array ofOptionobjects. - The method tries to parse the JSON string using the
parsemethod, passing in thejsonandoptionsparameters. - If the parse is successful, the method returns the resulting
JsonValueobject. - If an exception of type
JsonParseExceptionis thrown during the parse, the method catches it and rethrows it as aRuntimeException. This is done to simplify error handling, as theparsemethod may throw a checked exception. - If the exception is rethrown as a
RuntimeException, the caller of theparseUncheckedmethod will need to handle it appropriately.
Overall, the parseUnchecked method provides a simplified way to parse a JSON string without having to handle checked exceptions directly.
The parseUnchecked method is a static method defined in the JsonParser class within the io.nats.client.support package.
This method takes a char array json as input, along with optional Option arguments. The purpose of this method is to parse the given JSON string and return a JsonValue object.
Internally, the method calls the parse method from the same class which returns a JsonValue object. If a JsonParseException occurs during the parsing process, it is caught and re-thrown as a RuntimeException.
Overall, the parseUnchecked method allows for easy and unchecked parsing of a JSON string into a JsonValue object, simplifying exception handling for the caller.

public static JsonValue parseUnchecked(char[] json, int startIndex, Option... options) {
try {
return parse(json, startIndex, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}The parseUnchecked method is defined in the io.nats.client.support.JsonParser class.
The parseUnchecked method is used to parse a JSON value from a character array, starting from a specified index. This method internally calls the parse method and handles any JsonParseException by throwing a RuntimeException.
public static JsonValue parseUnchecked(char[] json, int startIndex, Option... options)The method takes the following parameters:
-
json- A character array containing the JSON string to parse. -
startIndex- An integer representing the index in thejsonarray from where the parsing should start. -
options(optional) - One or moreOptionobjects specifying parsing options.
The method returns a JsonValue representing the parsed JSON value.
The method may throw a RuntimeException if a JsonParseException occurs during parsing.
char[] json = "{\"name\": \"John\", \"age\": 30}".toCharArray();
int startIndex = 0;
try {
JsonValue result = JsonParser.parseUnchecked(json, startIndex);
System.out.println(result);
} catch (RuntimeException e) {
System.err.println("Failed to parse JSON: " + e.getMessage());
}In the above example, the parseUnchecked method is called with a JSON string and a starting index of 0. The parsed JsonValue is then printed to the console. If a JsonParseException occurs, a RuntimeException is thrown and the error message is printed to the console.
The parseUnchecked method in the JsonParser class is a public static method that allows you to parse a JSON string into a JsonValue object.
This method takes in three parameters:
-
json: a character array representing the JSON string to be parsed -
startIndex: an integer representing the starting index of the JSON string -
options: an optional array ofOptionobjects that can be used to customize the parsing behavior
Internally, the parseUnchecked method calls the parse method from the same class, passing in the provided parameters and options. If an exception of type JsonParseException is caught during the parsing process, it is wrapped in a RuntimeException and re-thrown.
Overall, the purpose of this method is to provide a convenient way to parse a JSON string into a JsonValue object, while handling any parsing exceptions in a consistent manner.

public static JsonValue parseUnchecked(String json) {
try {
return parse(json);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}The parseUnchecked method in the JsonParser class is used to parse JSON data provided as a string and return a corresponding JsonValue object.
- The method accepts a
jsonparameter, which is a string containing the JSON data to be parsed. - Inside the method, a try-catch block is used to handle any potential
JsonParseExceptionthat may occur during parsing. - The
parsemethod is called with thejsonparameter to parse the JSON data and return aJsonValueobject. - If no exception occurs during parsing, the parsed
JsonValueobject is returned. - If a
JsonParseExceptionoccurs, it is caught in the catch block. - Inside the catch block, a
RuntimeExceptionis thrown with the caughtJsonParseExceptionas the cause. - This allows any exception during parsing to be re-thrown as a
RuntimeException. - Finally, the
parseUncheckedmethod is concluded.
Note: It's important to handle exceptions during parsing JSON data as parsing errors can occur if the JSON structure is not properly formatted.
The parseUnchecked method in the JsonParser class is a static method that takes a JSON string as input and returns a JsonValue object.
This method calls the parse method, which is responsible for parsing the JSON string and returning the corresponding JsonValue object. However, if a JsonParseException occurs during the parsing process, the method catches the exception and rethrows it as a RuntimeException to ensure the caller is aware of the failure.
The parseUnchecked method is designed to provide a convenient way to parse a JSON string without explicitly handling the JsonParseException. This is useful in scenarios where the caller expects the input JSON to be valid and does not want to handle the exception explicitly.
public static JsonValue parseUnchecked(String json, int startIndex) {
try {
return parse(json, startIndex);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}parseUnchecked Method Description
The parseUnchecked method in class io.nats.client.support.JsonParser is used to parse a JSON string starting from a specified index. It takes two parameters, a String representing the JSON string to be parsed, and an int representing the index at which parsing should begin.
-
The method starts by wrapping the parsing logic in a try-catch block. This is done to catch any
JsonParseExceptionthat may occur while parsing the JSON string. -
Inside the try block, the
parsemethod is called, passing thejsonstring andstartIndexas arguments. Theparsemethod is responsible for parsing the JSON string and returning the parsed result as aJsonValueobject. -
If the parsing is successful, the parsed
JsonValueobject is returned from theparseUncheckedmethod. -
However, if a
JsonParseExceptionis caught during parsing, the method throws aRuntimeException. This is done by wrapping the caught exception in aRuntimeExceptionand rethrowing it. This allows the calling code to handle the exception in a consistent manner.
In summary, the parseUnchecked method provides a convenient way to parse a JSON string starting from a specified index. It handles any JsonParseException that may occur during parsing and rethrows it as a RuntimeException for consistent error handling.
The parseUnchecked method is a static method defined in the JsonParser class of the io.nats.client.support package.
This method takes a JSON string and a starting index as parameters and returns a JsonValue object representing the parsed JSON value. It uses the parse method (which is not explicitly defined in the code snippet) to parse the JSON string, starting from the specified index. If a JsonParseException occurs during the parsing process, it is caught and re-thrown as a RuntimeException.
Based on the code provided, this method provides a way to parse a JSON string and obtain a JsonValue object representation, ensuring that any exceptions thrown during parsing are handled and converted to a RuntimeException.

public static JsonValue parseUnchecked(String json, Option... options) {
try {
return parse(json, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}The method parseUnchecked in the class io.nats.client.support.JsonParser is responsible for parsing a JSON string and returning a JsonValue object. Here is a step-by-step description of what the method does:
- The method accepts a JSON string as the
jsonparameter and an optional array ofOptionobjects as theoptionsparameter. - Inside the method, it tries to parse the
jsonstring by calling theparsemethod (which is not included in the provided code snippet), passing thejsonandoptionsparameters. - If the
parsemethod throws aJsonParseException, it catches the exception and throws a newRuntimeExceptionwrapping the original exception. - If the
parsemethod successfully parses the JSON string, it returns aJsonValueobject.
It's worth noting that the actual implementation of the parse method is not shown in the provided code snippet, so the specific parsing logic is unknown. However, based on the provided code, we can infer that the parse method is expected to handle the parsing of the json string and return a JsonValue object accordingly.
The parseUnchecked method in the JsonParser class is a static method that accepts a JSON string as input and optional parsing options. It uses the parse method from the same class to parse the provided JSON string. If a JsonParseException occurs during the parsing process, it catches the exception and rethrows it as a RuntimeException.
In summary, the parseUnchecked method parses a JSON string and handles any parsing exceptions by throwing a RuntimeException.

public static JsonValue parseUnchecked(String json, int startIndex, Option... options) {
try {
return parse(json, startIndex, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}public static JsonValue parseUnchecked(String json, int startIndex, Option... options) {
try {
return parse(json, startIndex, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}This method is defined in the JsonParser class in the io.nats.client.support package.
-
json(String): The JSON string to parse. -
startIndex(int): The index to start parsing from. -
options(Option...): Optional parsing options.
-
JsonValue: The parsed JSON value.
This method is used to parse a JSON string into a JsonValue object.
- The method starts by calling the
parsemethod, passing thejson,startIndex, andoptionsparameters. - If the
parsemethod throws aJsonParseException, it catches the exception and throws aRuntimeExceptionwith the original exception as the cause. - If the
parsemethod is successful, it returns the parsed JSON value.
Note: The JsonParseException is a checked exception. This method wraps it in a RuntimeException to allow it to be used without explicitly handling the exception.
The parseUnchecked method is a static method defined in the io.nats.client.support.JsonParser class. It takes three parameters: json (a string representing JSON), startIndex (an integer specifying the index from which to start parsing), and options (an array of Option objects specifying parsing options).
The purpose of this method is to parse a JSON string into a JsonValue object. It uses the parse method from the same class, passing the provided parameters. If an exception of type JsonParseException is thrown during the parsing process, it catches the exception and rethrows it as a RuntimeException.
Overall, this method provides a convenient way to parse a JSON string without explicitly handling the JsonParseException exception, making it suitable for situations where exception handling can be simplified.

public static JsonValue parseUnchecked(byte[] json) {
try {
return parse(json);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}This method is defined in the class io.nats.client.support.JsonParser. It takes a single parameter, json, which represents a byte array of JSON data.
The purpose of this method is to parse the given JSON data and return the resulting JsonValue.
The method executes the following steps:
- It tries to invoke the
parsemethod by passing thejsonparameter. - If the
parsemethod throws aJsonParseException, the method catches it and throws a newRuntimeException. This is done to convert the checked exception into an unchecked exception.
Please note that the parse method is not defined in the provided body. It is assumed to be present in the io.nats.client.support.JsonParser class and handles the actual parsing of the JSON data.
The parseUnchecked method in the JsonParser class is a utility method for parsing JSON data represented as a byte array into a JsonValue object.
The method calls the parse method, which is responsible for performing the actual parsing of the JSON data. If a JsonParseException is thrown during the parsing process, it is caught and rethrown as a RuntimeException.
This method is named "parseUnchecked" because it wraps the checked exception (JsonParseException) into an unchecked exception (RuntimeException), allowing a caller to handle any parsing errors in a more consistent and simplified manner.

public static JsonValue parseUnchecked(byte[] json, Option... options) {
try {
return parse(json, options);
} catch (JsonParseException j) {
throw new RuntimeException(j);
}
}The parseUnchecked method is defined in the JsonParser class of the io.nats.client.support package. It takes a byte array as input and an optional array of Option objects.
The purpose of this method is to parse the given byte array as JSON and return the parsed JsonValue object. However, since the parse method that actually performs the parsing can throw a JsonParseException, the parseUnchecked method catches this exception and rethrows it as a RuntimeException.
Here is a step-by-step description of what the parseUnchecked method does:
-
The method signature declares the method as
public static, meaning it can be called without an instance of theJsonParserclass and it can be called from any other class in the same package or from a different package. -
The method takes two parameters:
byte[] json, which represents the JSON data to be parsed, andOption... options, which is an optional array ofOptionobjects that can be used to customize the parsing behavior. -
Inside the method, a
try-catchblock is used to handle anyJsonParseExceptionthat might occur during the parsing process. -
The
tryblock calls theparsemethod, passing thejsonbyte array and theoptionsarray as arguments, to perform the actual parsing and return the resultingJsonValueobject. -
If the parsing is successful and no
JsonParseExceptionis thrown, the parsedJsonValueobject is returned by theparsemethod. -
If a
JsonParseExceptionis thrown during the parsing process, thecatchblock catches it, encapsulates it inside aRuntimeException, and throws this new exception. -
The
RuntimeExceptionthat is thrown in case of a parsing error will contain the originalJsonParseExceptionas its cause.
Overall, the parseUnchecked method provides a convenient way to parse JSON data without explicitly handling the JsonParseException, as it wraps any thrown exception and rethrows it as a RuntimeException.
The parseUnchecked method in the JsonParser class is a static method that takes a byte array json as input along with optional Option parameters.
This method is used to parse the given byte array json into a JsonValue object. It internally calls the parse method with the given parameters and returns the parsed JsonValue.
If the parsing fails and throws a JsonParseException, the method catches the exception and rethrows it as a RuntimeException. This is done to handle any parsing errors in a more generic way.
Overall, this method allows for parsing a byte array of JSON data into a JsonValue object, with the option to customize the parsing behavior using optional parameters.

public JsonValue parse() throws JsonParseException {
char c = peekToken();
if (c == 0) {
return NULL;
}
return nextValue();
}The parse() method is defined in the JsonParser class, located in the io.nats.client.support package. It is used to parse a JSON string and return the corresponding JsonValue object. The method has the following steps:
- Get the next character from the JSON string by calling the
peekToken()method and assign it to the variablec. - Check if the character
cis equal to0(null character). If it is, return aNULLJsonValueobject. - If the character
cis not null, call thenextValue()method to parse the next JSON value and return it.
The method may throw a JsonParseException if there are any issues encountered during the parsing process.
The parse method in the JsonParser class is used to parse a JSON string and convert it into a JsonValue object.
It starts by checking the next token in the JSON string using the peekToken method. If the next token is a null character (ASCII value 0), it returns a NULL value indicating that the JSON string is empty.
Otherwise, it calls the nextValue method to parse the next JSON value in the string and returns it. The nextValue method is responsible for iterating through the JSON string and parsing each individual value.
If any error occurs while parsing the JSON string, a JsonParseException is thrown.
In summary, the parse method takes a JSON string as input, checks if it is empty, and if not, parses it into a JsonValue object.

private JsonValue nextValue() throws JsonParseException {
char c = peekToken();
if (c == 0) {
throw new JsonParseException("Unexpected end of data.");
}
if (c == '"') {
nextToken();
return new JsonValue(nextString());
}
if (c == '{') {
nextToken();
return new JsonValue(nextObject());
}
if (c == '[') {
nextToken();
return new JsonValue(nextArray());
}
return nextPrimitiveValue();
}The nextValue method is defined in the JsonParser class within the io.nats.client.support package. This method is responsible for parsing the next JSON value in a string and returning it as a JsonValue object. Here is a step-by-step description of what this method does:
- Get the next character from the input string using the
peekTokenmethod and assign it to the variablec. - Check if the value of
cis 0, which indicates the end of the input data. If it is, throw aJsonParseExceptionwith the message "Unexpected end of data." - Check if the value of
cis". If it is, call thenextTokenmethod to consume the", then call thenextStringmethod to parse the next JSON string, and finally return a newJsonValueobject with the parsed string. - Check if the value of
cis{. If it is, call thenextTokenmethod to consume the{, then call thenextObjectmethod to parse the next JSON object, and finally return a newJsonValueobject with the parsed object. - Check if the value of
cis[. If it is, call thenextTokenmethod to consume the[, then call thenextArraymethod to parse the next JSON array, and finally return a newJsonValueobject with the parsed array. - If none of the above conditions are met, call the
nextPrimitiveValuemethod to parse the next JSON primitive value, and return the result.
Overall, the nextValue method determines the type of the next JSON value (string, object, array, or primitive) based on the next character in the input string and uses the appropriate method to parse and return the value as a JsonValue object.
The nextValue method is a private method defined in the JsonParser class in the io.nats.client.support package. This method is used to parse the next JSON value from the input data.
The method starts by checking the next character in the input data and throws a JsonParseException if it encounters an unexpected end of data.
Next, it checks if the next character is a double quotation mark ("), indicating that the next value is a string. If it is, it moves to the next character and returns a new JsonValue object containing the parsed string.
If the next character is an opening curly brace ({), indicating the start of an object, it moves to the next character and returns a new JsonValue object containing the parsed object.
Similarly, if the next character is an opening square bracket ([), indicating the start of an array, it moves to the next character and returns a new JsonValue object containing the parsed array.
If none of the above conditions are met, it assumes the next value is a primitive value (e.g., number, boolean, or null) and calls the nextPrimitiveValue method to parse it. The result is then returned as a JsonValue object.
In summary, the nextValue method in the JsonParser class is responsible for parsing the next JSON value from the input data, handling different types of values such as strings, objects, arrays, and primitive values.

private List<JsonValue> nextArray() throws JsonParseException {
List<JsonValue> list = new ArrayList<>();
char p = peekToken();
while (p != ']') {
if (p == ',') {
// advance past the peek
nextToken();
} else {
list.add(nextValue());
}
p = peekToken();
}
// advance past the peek
nextToken();
return list;
}The nextArray() method is a private method defined in the io.nats.client.support.JsonParser class. It is responsible for parsing a JSON array and returning a List of JsonValue objects.
Here is a step-by-step description of how the nextArray() method works:
- Create a new
ArrayListcalledlistto store theJsonValueobjects. - Peek at the next token using the
peekToken()method and store it in a variable calledp. - Start a loop that continues until the next token is
']'. - Inside the loop, check if the next token is
','. If it is, advance past the token by calling thenextToken()method. - If the next token is not
',', it means it is a JSON value. Call thenextValue()method to parse the value and add it to thelistusing theadd()method. - Peek at the next token again and update the value of
p. - After the loop, call the
nextToken()method to advance past the closing'['token. - Return the
listcontaining the parsed JSON values.
It is worth noting that the nextArray() method assumes that the input JSON is well-formed, with elements separated by commas and enclosed in square brackets. If the JSON is not well-formed, the method may throw a JsonParseException.
The nextArray method in the JsonParser class is used to parse and retrieve a list of JsonValue objects from a JSON string.
Here's a brief overview of what the method does:
- It initializes an empty
ArrayListto store the parsedJsonValueobjects. - It checks the next character in the JSON string (referred to as
p) to determine if the end of the array is reached. - If
pis not ']', it proceeds to check ifpis ',' or a value by calling other methods. - If
pis ',', it advances to the next token and checks the newpagain. - If
pis neither ']' nor ',', it calls thenextValuemethod to parse and retrieve the nextJsonValueobject, and adds it to the list. - After adding the value to the list, it proceeds to check the new
pagain. - This process continues until
pis ']'. - Once the end of the array is reached, it advances to the next token (i.e., the next character after ']') for further parsing.
- Finally, it returns the list of parsed
JsonValueobjects.
In summary, the nextArray method reads and processes the JSON array tokens, extracting the JsonValue objects and returning a list of those objects.

private JsonValue nextPrimitiveValue() throws JsonParseException {
StringBuilder sb = new StringBuilder();
char c = peekToken();
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
sb.append(nextToken());
c = peekToken();
}
String string = sb.toString();
if ("true".equalsIgnoreCase(string)) {
return new JsonValue(Boolean.TRUE);
}
if ("false".equalsIgnoreCase(string)) {
return new JsonValue(Boolean.FALSE);
}
if ("null".equalsIgnoreCase(string)) {
return JsonValue.NULL;
}
try {
return asNumber(string);
} catch (Exception e) {
throw new JsonParseException("Invalid value.");
}
}
```### // next object assumes you have already seen the starting
```java
// next object assumes you have already seen the starting {
private Map<String, JsonValue> nextObject() throws JsonParseException {
Map<String, JsonValue> map = new HashMap<>();
String key;
while (true) {
char c = nextToken();
switch(c) {
case 0:
throw new JsonParseException("Text must end with '}'");
case '}':
return map;
case '{':
case '[':
if (previous == '{') {
throw new JsonParseException("Cannot directly nest another Object or Array.");
}
// fall through
default:
key = nextString();
}
c = nextToken();
if (c != ':') {
throw new JsonParseException("Expected a ':' after a key.");
}
JsonValue value = nextValue();
if (value != NULL || keepNulls) {
map.put(key, value);
}
switch(nextToken()) {
case ',':
if (peekToken() == '}') {
// dangling comma
return map;
}
break;
case '}':
return map;
default:
throw new JsonParseException("Expected a ',' or '}'.");
}
}
}The nextObject() method in the JsonParser class is used to parse a JSON object from a given input stream. It assumes that the starting { character has already been seen.
Here is a step-by-step description of what the method does:
- Create a new
HashMapcalledmapto store the key-value pairs of the JSON object. - Start a while loop that continues until the method returns. This loop is used to iterate through each key-value pair in the JSON object.
- Get the next character from the input stream using the
nextToken()method. - Switch on the value of the character:
- If the value is 0, throw a
JsonParseExceptionwith the message "Text must end with '}'". - If the value is
}, return themap, indicating that the end of the object has been reached. - If the value is
{or[, check if the previous token was{. If it was, throw aJsonParseExceptionwith the message "Cannot directly nest another Object or Array." - For any other character, assume it is a key and assign it to the
keyvariable using thenextString()method.
- If the value is 0, throw a
- Get the next character from the input stream and check if it is
:. If it is not, throw aJsonParseExceptionwith the message "Expected a ':' after a key." - Call the
nextValue()method to parse the value of the key. Assign this value to thevaluevariable. - Check if the
valueis not null or ifkeepNullsflag is set totrue. If either condition is true, add the key-value pair to themapusing theput()method. - Get the next character from the input stream.
- Switch on the value of the character:
- If the value is
,and the next token is}, return themap. This means there is a dangling comma at the end of the object. - If the value is
,, continue to the next iteration of the loop to process the next key-value pair. - If the value is
}, return themap, indicating that the end of the object has been reached. - For any other character, throw a
JsonParseExceptionwith the message "Expected a ',' or '}'."
- If the value is
- Repeat steps 3-9 until the end of the JSON object is reached.
Note: The exact behavior of some steps may depend on the specific implementation of the JsonParser class. This description assumes the provided code is the complete and correct implementation.
The method nextObject in the class JsonParser is used to parse the next JSON object from a JSON input. It assumes that the input starts with a { character, indicating the beginning of the object.
The method reads the input character by character and constructs a Map<String, JsonValue> to represent the key-value pairs of the JSON object. It iterates over the input until it encounters the closing } character, indicating the end of the object.
Inside the loop, the method checks each character and handles different cases accordingly:
- If the character is not one of
{,},[, or], it considers it as a key and calls thenextStringmethod to parse the corresponding key string. - After parsing the key, the method expects to encounter a
:character, indicating the separation between the key and the associated value. - The method then calls the
nextValuemethod to parse the JSON value associated with the key. - If the parsed value is not
NULL(or if the flagkeepNullsis set to true), the method adds the key-value pair to themap. - After parsing a value, the method expects to encounter either
,indicating more key-value pairs are present, or}indicating the end of the object. If a,is encountered and the next character is}, it means that a dangling comma is present, and the method returns the constructedmapat that point.
Once the method reaches the end of the object, it returns the map containing the parsed key-value pairs.
Overall, this method allows the user to extract a JSON object from a JSON input stream and convert it into a Map<String, JsonValue> representation.

private char nextToken() {
peekToken();
idx = nextIdx;
nextIdx = -1;
previous = current;
current = next;
next = 0;
return current;
}The nextToken() method in the JsonParser class is responsible for returning the next character token while parsing JSON content. Here is a step-by-step description of what the method does based on its body:
- The
peekToken()method is called to determine the next token without consuming it. - The current index (
idx) is assigned to the previous index (nextIdx) to keep track of the position of the previous token. - The next index (
nextIdx) is set to -1 to indicate that it hasn't been determined yet. - The current character (
current) is assigned to the previous character (previous) to keep track of the previous token. - The next character (
next) is set to 0 as a placeholder for the next token. - The value of the current character (
current) is returned as the result of the method.
In summary, the nextToken() method updates the state of the parser, including the current and previous characters and their corresponding indices, and returns the current character as the next token.
The nextToken method in the JsonParser class is used to retrieve the next JSON token while parsing a JSON string.
Here is a brief description of what this method does based on its body:
-
peekToken()is called to determine the type of the next token without consuming it. - The index (
idx) is updated to the value ofnextIdx, which represents the starting position of the next token. -
nextIdxis set to -1, indicating that the starting position of the next token is not yet known. - The current character (
current) is preserved as the previous character. - The next character (
next) becomes the current character. - The value of
nextis reset to 0, indicating that the next character has not yet been determined. - The current character is returned.
This method allows the JSON parser to iterate through the JSON string, token by token, by updating the necessary variables to keep track of the current and next characters.

private char nextChar() {
previous = current;
if (idx == len) {
current = 0;
} else {
current = json[idx++];
}
next = 0;
nextIdx = -1;
return current;
}- Set the
previouscharacter variable to the value of the current character. - Check if the index (
idx) is equal to the length of thejsonstring.- If true, set the
currentcharacter variable to 0. - If false, proceed to the next step.
- If true, set the
- If the index is not equal to the length of the
jsonstring:- Set the
currentcharacter variable to the character at the current indexidxin thejsonstring. - Increment the
idxby 1.
- Set the
- Set the
nextcharacter variable to 0. - Set the
nextIdxvariable to -1. - Return the value of the
currentcharacter.
The nextChar method, defined in the JsonParser class in the io.nats.client.support package, reads the next character from a JSON input string.
The method updates the previous variable to hold the value of the current character and then checks if idx (the current index) is equal to len (the length of the JSON input string). If idx is equal to len, it means that the method has reached the end of the JSON string and sets current to 0. Otherwise, the method sets current to the character at the idx index of the json string and increments idx.
The method also sets next to 0 and nextIdx to -1, indicating that there is no next character or next index. Finally, the method returns the value of the current character.

private char peekToken() {
if (nextIdx == -1) {
nextIdx = idx;
next = 0;
while (nextIdx < len) {
char c = json[nextIdx++];
switch(c) {
case ' ':
case '\r':
case '\n':
case '\t':
continue;
}
return next = c;
}
}
return next;
}The peekToken method is defined in the io.nats.client.support.JsonParser class. It is used to retrieve the next character token in a JSON string without consuming it.
Here is a step-by-step description of what the peekToken method does based on its body:
- The method starts with a check for the value of
nextIdx. IfnextIdxis equal to -1, it means that the next character token has not been set yet. - If
nextIdxis -1, the method initializesnextIdxwith the value ofidx(which is the index of the current character token) and setsnextto 0. - Then a
whileloop is started, which continues untilnextIdxis less thanlen(which represents the length of the JSON string). - Inside the
whileloop, the method retrieves the next charactercfrom thejsonarray using thenextIdx++expression. This incrementsnextIdxafter retrieving the character. - The
switchstatement considers the value of the retrieved characterc. - If
cis a whitespace character (space, carriage return, newline, or tab), the loop continues without doing anything else. - If
cis not a whitespace character, then the method assignsctonextand returns its value as the next character token. - If the
whileloop completes without finding a non-whitespace character, it means that the end of the JSON string has been reached. - In that case, the method returns the value of
next(which will be 0 if no non-whitespace character was found in the JSON string).
This peekToken method allows you to check the next character token in a JSON string without actually consuming it. This can be useful when parsing JSON and determining the structure or content of the JSON string.
The peekToken() method in the JsonParser class is used to peek at the next character in a JSON string without consuming it.
The method initializes a variable next to store the next character and nextIdx to keep track of the current index in the JSON string. If nextIdx is -1, it means that the method has not yet read the next character. In this case, the method iterates through the JSON string (json) starting from idx and checks each character using a switch statement.
If the character is a whitespace character (such as space, newline, carriage return, or tab), the method continues to the next character. Otherwise, the method sets next to the current character and increments nextIdx. The method then returns the character stored in next.
If nextIdx is not -1, it means that the method has already read the next character, so it simply returns the value stored in next.
Overall, the peekToken() method is responsible for peeking at the next non-whitespace character in a JSON string without consuming it.
private String nextString() throws JsonParseException
// next string assumes you have already seen the starting quote
private String nextString() throws JsonParseException {
StringBuilder sb = new StringBuilder();
while (true) {
char c = nextChar();
switch(c) {
case 0:
case '\n':
case '\r':
throw new JsonParseException("Unterminated string.");
case '\\':
c = nextChar();
switch(c) {
case 'b':
sb.append('\b');
break;
case 't':
sb.append('\t');
break;
case 'n':
sb.append('\n');
break;
case 'f':
sb.append('\f');
break;
case 'r':
sb.append('\r');
break;
case 'u':
sb.append(parseU());
break;
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
default:
throw new JsonParseException("Illegal escape.");
}
break;
default:
if (c == '"') {
return sb.toString();
}
sb.append(c);
}
}
}
```### private char[] parseU() throws JsonParseException
```java
private char[] parseU() throws JsonParseException {
char[] a = new char[4];
for (int x = 0; x < 4; x++) {
a[x] = nextToken();
if (a[x] == 0) {
throw new JsonParseException("Illegal escape.");
}
}
try {
int code = Integer.parseInt("" + a[0] + a[1] + a[2] + a[3], 16);
return Character.toChars(code);
} catch (RuntimeException e) {
throw new JsonParseException("Illegal escape.", e);
}
}The method parseU defined in class io.nats.client.support.JsonParser is responsible for parsing a Unicode escape sequence in a JSON string. Here is the step-by-step description of what this method is doing:
- It declares and initializes a
chararrayawith a length of 4. - It enters a
forloop that iterates 4 times, with the loop variablexstarting from 0 and incrementing by 1 in each iteration. - Inside the loop, it calls the
nextTokenmethod and assigns the returnedcharvalue to thex-th index ofa. - It checks if the
x-th element ofais equal to 0. If it is, it throws aJsonParseExceptionwith the message "Illegal escape." - After the loop, it tries to parse the hexadecimal representation of the
chararrayaas an integer.- It concatenates the
charelements ofainto a string, and then parses it as an integer usingInteger.parseInt. - The parsed integer will represent a Unicode code point.
- It concatenates the
- It calls
Character.toCharswith the parsed code point to convert it into achararray representing the character(s) corresponding to the code point.- This is necessary because a Unicode code point can represent a single character or a surrogate pair that requires two
charelements.
- This is necessary because a Unicode code point can represent a single character or a surrogate pair that requires two
- It returns the resulting
chararray.
If any exception occurs during parsing or conversion, it catches a RuntimeException, wraps it in a JsonParseException with the message "Illegal escape," and rethrows the wrapped exception.
The parseU() method in the io.nats.client.support.JsonParser class is used to parse and decode a Unicode escape sequence in the JSON input.
Here's a breakdown of what the method does:
- It initializes a character array
awith a length of 4. - It iterates 4 times using a for loop, and in each iteration, it assigns the next token character to
a[x]. - It checks if the assigned character is equal to 0; if it is, it throws a
JsonParseExceptionwith the message "Illegal escape." - It attempts to convert the 4 characters in
ainto an integer code by parsing them as a hexadecimal number. - It uses the
Character.toChars()method to convert the code into a character or characters (as an array). - It returns the resulting character or characters.
If there is any exception encountered during this process, a JsonParseException with the message "Illegal escape." is thrown, and if provided, the original exception is included as the cause of the thrown exception.

private JsonValue asNumber(String val) throws JsonParseException {
char initial = val.charAt(0);
if ((initial >= '0' && initial <= '9') || initial == '-') {
// decimal representation
if (isDecimalNotation(val)) {
// Use a BigDecimal all the time to keep the original
// representation. BigDecimal doesn't support -0.0, ensure we
// keep that by forcing a decimal.
try {
BigDecimal bd = new BigDecimal(val);
if (initial == '-' && BigDecimal.ZERO.compareTo(bd) == 0) {
return new JsonValue(-0.0);
}
return new JsonValue(bd);
} catch (NumberFormatException retryAsDouble) {
// this is to support "Hex Floats" like this: 0x1.0P-1074
try {
double d = Double.parseDouble(val);
if (Double.isNaN(d) || Double.isInfinite(d)) {
throw new JsonParseException("val [" + val + "] is not a valid number.");
}
return new JsonValue(d);
} catch (NumberFormatException ignore) {
throw new JsonParseException("val [" + val + "] is not a valid number.");
}
}
}
// block items like 00 01 etc. Java number parsers treat these as Octal.
if (initial == '0' && val.length() > 1) {
char at1 = val.charAt(1);
if (at1 >= '0' && at1 <= '9') {
throw new JsonParseException("val [" + val + "] is not a valid number.");
}
} else if (initial == '-' && val.length() > 2) {
char at1 = val.charAt(1);
char at2 = val.charAt(2);
if (at1 == '0' && at2 >= '0' && at2 <= '9') {
throw new JsonParseException("val [" + val + "] is not a valid number.");
}
}
BigInteger bi = new BigInteger(val);
if (bi.bitLength() <= 31) {
return new JsonValue(bi.intValue());
}
if (bi.bitLength() <= 63) {
return new JsonValue(bi.longValue());
}
return new JsonValue(bi);
}
throw new JsonParseException("val [" + val + "] is not a valid number.");
}The asNumber method in class io.nats.client.support.JsonParser is responsible for parsing a string representation of a number and converting it to a JsonValue object. Here is a step-by-step description of what the method does based on its body:
- Get the first character of the input string and store it in the variable
initial. - Check if the first character is a digit (
0to9) or a hyphen (-). - If the first character is a digit or a hyphen, proceed to the next steps. Otherwise, throw a
JsonParseExceptionwith an error message indicating that the input string is not a valid number. - Check if the number is represented in decimal notation by calling the
isDecimalNotationmethod. If it is, continue to the next steps. If not, go to step 13. - Try to create a
BigDecimalobject from the input string usingnew BigDecimal(val). This ensures that the original representation of the number is preserved. If the value ofinitialis-and theBigDecimal.ZEROis equal to the createdBigDecimalobject, create a newJsonValueobject representing negative zero (-0.0). Otherwise, create a newJsonValueobject with theBigDecimalvalue. - If an exception of type
NumberFormatExceptionis caught during theBigDecimalcreation, proceed to the next steps to handle other special cases. - This part is to support "Hex Floats" like
0x1.0P-1074. Attempt to parse the input string as adoubleusingDouble.parseDouble(val). - Check if the parsed
doublevalue isNaN(not a number) orInfinity. If it is, throw aJsonParseExceptionwith an error message indicating that the input string is not a valid number. - If the parsed
doublevalue is valid, create a newJsonValueobject with thedoublevalue. - If an exception of type
NumberFormatExceptionis caught during thedoubleparsing, throw aJsonParseExceptionwith an error message indicating that the input string is not a valid number. - If the first character is
0and the length of the input string is greater than1, check if the second character is a digit (0to9). If it is, throw aJsonParseExceptionwith an error message indicating that the input string is not a valid number. - If the first character is a hyphen (
-) and the length of the input string is greater than2, check if the second character is0and the third character is a digit (0to9). If it is, throw aJsonParseExceptionwith an error message indicating that the input string is not a valid number. - Create a
BigIntegerobject from the input string usingnew BigInteger(val). - Check the bit length of the
BigIntegerobject. If it is less than or equal to31, create a newJsonValueobject with theintvalue of theBigInteger. - If the bit length of the
BigIntegeris less than or equal to63, create a newJsonValueobject with thelongvalue of theBigInteger. - For larger
BigIntegervalues, create a newJsonValueobject with theBigIntegervalue. - If the first character of the input string is not a digit or a hyphen, throw a
JsonParseExceptionwith an error message indicating that the input string is not a valid number.
The asNumber method in the JsonParser class is used to parse a string representation of a number and convert it into a JsonValue object.
Here's a brief overview of what the method does:
- It checks the first character of the input string to determine if it is a valid number or not.
- If the number is a decimal representation, it uses a
BigDecimalto keep the original representation. It also handles cases like -0.0 by checking if the value is equal to zero and negative. If it is, it returns aJsonValueobject representing -0.0. - If the number is not a decimal representation, it checks for other special cases like "Hex Floats" and blocks certain items like 00 and 01 that Java number parsers treat as Octal.
- If the number passes all the checks, it converts it into a
BigIntegerobject. If thebitLengthof theBigIntegeris less than or equal to 31, it returns aJsonValueobject representing the number as anint. If thebitLengthis less than or equal to 63, it returns aJsonValueobject representing the number as along. Otherwise, it returns aJsonValueobject representing the number as aBigInteger. - If the input string is not a valid number, it throws a
JsonParseExceptionwith an appropriate error message.
Overall, the asNumber method handles various cases and provides a flexible way to parse and convert different types of numbers into a JsonValue object.

Encoding
The Encoding class is an abstract class that provides a framework for implementing different encoding algorithms. It serves as a base class for specific encoding classes and defines common properties and methods that are shared by these classes. Being an abstract class, it cannot be instantiated on its own. Instead, it provides a template for creating encoding classes that adhere to the specified structure and functionality.
public static char[] base32Encode(final byte[] input) {
int last = input.length;
char[] charBuff = new char[(last + 7) * 8 / SHIFT];
int offset = 0;
int buffer = input[offset++];
int bitsLeft = 8;
int i = 0;
while (bitsLeft > 0 || offset < last) {
if (bitsLeft < SHIFT) {
if (offset < last) {
buffer <<= 8;
buffer |= (input[offset++] & 0xff);
bitsLeft += 8;
} else {
int pad = SHIFT - bitsLeft;
buffer <<= pad;
bitsLeft += pad;
}
}
int index = MASK & (buffer >> (bitsLeft - SHIFT));
bitsLeft -= SHIFT;
charBuff[i] = BASE32_CHARS.charAt(index);
i++;
}
int nonBlank;
for (nonBlank = charBuff.length - 1; nonBlank >= 0; nonBlank--) {
if (charBuff[nonBlank] != 0) {
break;
}
}
char[] retVal = new char[nonBlank + 1];
System.arraycopy(charBuff, 0, retVal, 0, retVal.length);
Arrays.fill(charBuff, '\0');
return retVal;
}
```### public static byte[] base32Decode(final char[] input)
```java
public static byte[] base32Decode(final char[] input) {
byte[] bytes = new byte[input.length * SHIFT / 8];
int buffer = 0;
int next = 0;
int bitsLeft = 0;
for (int i = 0; i < input.length; i++) {
int lookup = input[i] - '0';
if (lookup < 0 || lookup >= BASE32_LOOKUP.length) {
continue;
}
int c = BASE32_LOOKUP[lookup];
buffer <<= SHIFT;
buffer |= c & MASK;
bitsLeft += SHIFT;
if (bitsLeft >= 8) {
bytes[next++] = (byte) (buffer >> (bitsLeft - 8));
bitsLeft -= 8;
}
}
return bytes;
}This method is defined in the class io.nats.client.support.Encoding. It takes in a character array as input and returns a byte array.
- Initialize a byte array
byteswith a length calculated asinput.length * SHIFT / 8. (line 2) - Initialize variables
buffer,next, andbitsLeftto 0. (lines 3-5) - Iterate through each character in the
inputarray. (line 6) - Calculate the index of the character in the
BASE32_LOOKUParray by subtracting the ASCII value of '0' from the current character. (line 7) - If the calculated index is invalid (less than 0 or greater than or equal to the length of
BASE32_LOOKUP), skip to the next iteration. (line 8) - Retrieve the value from the
BASE32_LOOKUParray corresponding to the calculated index and store it in variablec. (line 9) - Shift the content of
bufferto the left bySHIFTbits. (line 10) - Perform a bitwise OR operation between
bufferand the lowerMASKbits ofc, and updatebufferwith the result. (line 11) - Increment
bitsLeftbySHIFT. (line 12) - If
bitsLeftis greater than or equal to 8, extract the most significant 8 bits frombufferand store them in thebytesarray at the indexnext. (line 13)- Shift
bufferto the right by(bitsLeft - 8)bits to get the 8 most significant bits. - Cast the result to a byte and store it in
bytes[next]. - Decrease
bitsLeftby 8. - Increment
nextby 1.
- Shift
- Repeat from step 3 for the next character in
input. - Return the
bytesarray. (line 19)
The method base32Decode in the class io.nats.client.support.Encoding is used to decode a base32 encoded input represented as a char array and return the decoded result as a byte array.
The method follows the base32 decoding algorithm by iteratively processing each character in the input array. It uses a lookup table to convert each character to its corresponding decimal value.
The decoding process involves shifting the bits of the decimal value into a buffer, accumulating bits until there are at least 8 bits available. Once there are 8 or more bits, the method stores the byte formed by the 8 most significant bits in the bytes array, and then adjusts the bitsLeft count accordingly.
This process continues until all characters in the input array have been processed, and finally, the resulting bytes array is returned as the decoded output.

public static String jsonDecode(String s) {
int len = s.length();
StringBuilder sb = new StringBuilder(len);
for (int x = 0; x < len; x++) {
char ch = s.charAt(x);
if (ch == '\\') {
char nextChar = (x == len - 1) ? '\\' : s.charAt(x + 1);
switch(nextChar) {
case '\\':
ch = '\\';
break;
case 'b':
ch = '\b';
break;
case 'f':
ch = '\f';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
// Hex Unicode: u????
case 'u':
if (x >= len - 5) {
ch = 'u';
break;
}
int code = Integer.parseInt("" + s.charAt(x + 2) + s.charAt(x + 3) + s.charAt(x + 4) + s.charAt(x + 5), 16);
sb.append(Character.toChars(code));
x += 5;
continue;
default:
ch = nextChar;
break;
}
x++;
}
sb.append(ch);
}
return sb.toString();
}The jsonDecode method in the Encoding class is used to decode a JSON-encoded string. Here is a step-by-step description of how this method works:
- The method takes a string
sas input. - It initializes a variable
lenwith the length of the input string. - It creates a
StringBuilderobjectsbwith a initial capacity oflen. - It starts a loop from
x = 0tolen - 1. - Inside the loop, it retrieves the character at index
xof the input string usingcharAt()method, and assigns it to a variablech. - It checks if
chis the escape character ''. - If
chis '', then it retrieves the next characternextChar. Ifxis equal tolen - 1, it assigns a single quote ('') tonextChar. - It then checks the value of
nextCharusing a switch statement.- If
nextCharis '', it setschto ''. - If
nextCharis 'b', it setschto a backspace character. - If
nextCharis 'f', it setschto a form feed character. - If
nextCharis 'n', it setschto a new line character. - If
nextCharis 'r', it setschto a carriage return character. - If
nextCharis 't', it setschto a tab character. - If
nextCharis 'u', it parses the next four characters after 'u' as a hexadecimal number and converts it to the corresponding Unicode character. It then appends this character to thesbStringBuilder. The loop variablexis incremented by 5 to skip the four parsed hexadecimal characters and the 'u' character. - If
nextCharis any other character, it assignsnextChartoch. - The loop variable
xis incremented by 1 before continuing to the next iteration of the loop.
- If
- If
chis not '', it appendschto thesbStringBuilder. - After the loop finishes, it returns the contents of the
sbStringBuilder as a string using thetoString()method.
This jsonDecode method is used to replace the escape sequences in a JSON-encoded string with their original characters.
The jsonDecode method is a static method defined in the io.nats.client.support.Encoding class. It takes a String parameter s and returns a decoded JSON string.
Here's a breakdown of what the method does:
- It initializes a
StringBuildersbto store the decoded string. - It iterates through each character in the input string
s. - If the current character is a backlash (
\), it checks the next character to determine the escape sequence:- If the next character is also a backlash, it appends a backlash character to the
sb. - If the next character is
b, it appends a backspace character () to thesb. - If the next character is
f, it appends a form feed character () to thesb. - If the next character is
n, it appends a newline character ('\n') to thesb. - If the next character is
r, it appends a carriage return character ('\r') to thesb. - If the next character is
t, it appends a tab character ('\t') to thesb. - If the next character is
u, it expects the next 4 characters to be a hexadecimal Unicode code representing a character. It converts the code to a character usingCharacter.toChars(code)and appends it to thesb. It increments the loop variablexby 5 to skip the next 4 characters. - If the next character doesn't match any of the above cases, it appends the next character as is to the
sb. - It increments the loop variable
xby 1 to skip the next character since it has already been processed as part of an escape sequence.
- If the next character is also a backlash, it appends a backlash character to the
- If the current character is not a backlash, it appends it as is to the
sb. - Finally, it returns the decoded string by calling
sb.toString().
The jsonDecode method essentially decodes JSON escape sequences in a given JSON string and returns the decoded string.

public static StringBuilder jsonEncode(StringBuilder sb, String s) {
int len = s.length();
for (int x = 0; x < len; x++) {
char ch = s.charAt(x);
switch(ch) {
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
if (ch < ' ') {
sb.append(String.format("\\u%04x", (int) ch));
} else {
sb.append(ch);
}
break;
}
}
return sb;
}
```### public static String uriDecode(String source)
```java
public static String uriDecode(String source) {
try {
return URLDecoder.decode(source.replace("+", "%2B"), "UTF-8");
} catch (UnsupportedEncodingException e) {
return source;
}
}This method is defined in the io.nats.client.support.Encoding class and is responsible for URI decoding of a given input string.
-
source(String): The input string that needs to be decoded.
-
String: The URI decoded string.
- Replace all occurrences of the
+character in thesourcestring with%2B. - Use the
URLDecoder.decode()method to perform URL decoding on the modifiedsourcestring. - Specify the encoding to use as "UTF-8".
- If the specified encoding is unsupported and an
UnsupportedEncodingExceptionis thrown, catch the exception and return the originalsourcestring. - Return the decoded string obtained from step 2.
String input = "Hello%20World%21";
String decoded = Encoding.uriDecode(input);
System.out.println(decoded);
// Output: "Hello World!"In the example above, the input string is URI encoded with "%20" representing a space character. The uriDecode method is called on the input string, which decodes it and returns the decoded string "Hello World!". Finally, the decoded string is printed to the console.
The uriDecode method defined in the Encoding class within the io.nats.client.support package is used to decode a URI-encoded string. It takes a source string as input and replaces any occurrences of the "+" character with "%2B". It then uses the URLDecoder.decode method to decode the modified source string using the "UTF-8" character encoding. If an UnsupportedEncodingException occurs during this decoding process, the original source string is returned as is. The method returns the decoded string.

NatsUri
The NatsUri class is a public class that represents a URI for a NATS (North American Trading System) connection. It allows for the parsing and manipulation of NATS URIs, making it easier to connect to and communicate with a NATS messaging system.
private void postConstruct() {
String s = uri.getScheme().toLowerCase();
isSecure = SECURE_PROTOCOLS.contains(s);
isWebsocket = WSS_PROTOCOLS.contains(s);
s = uri.getHost();
hostIsIpAddress = IPV4_RE.matcher(s).matches() || s.startsWith("[") && s.endsWith("]");
}The postConstruct() method defined in class io.nats.client.support.NatsUri performs the following steps:
- Converts the scheme of the provided URI to lowercase and assigns it to a local variable
s. - Checks if the value of
sis present in theSECURE_PROTOCOLSlist.- If present, sets the
isSecureboolean variable totrue. - If not present, sets the
isSecureboolean variable tofalse.
- If present, sets the
- Checks if the value of
sis present in theWSS_PROTOCOLSlist.- If present, sets the
isWebsocketboolean variable totrue. - If not present, sets the
isWebsocketboolean variable tofalse.
- If present, sets the
- Retrieves the host from the provided URI and assigns it to the variable
s. - Checks if the host is an IP address using regular expression matching or if the host is enclosed within square brackets (
[and]).- If the above condition is met, sets the
hostIsIpAddressboolean variable totrue. - If the condition is not met, sets the
hostIsIpAddressboolean variable tofalse.
- If the above condition is met, sets the
Note: The purpose and behavior of the above method is explained based on the provided code snippet. Additional context or information about other parts of the code may be necessary for a comprehensive understanding.
The postConstruct method in the io.nats.client.support.NatsUri class is used to initialize the instance variables isSecure, isWebsocket, and hostIsIpAddress based on the values of the uri object.
First, it converts the scheme of the URI to lowercase and checks if it exists in the SECURE_PROTOCOLS collection. If it does, the isSecure variable is set to true.
Next, it checks if the scheme exists in the WSS_PROTOCOLS collection. If it does, the isWebsocket variable is set to true.
Lastly, it assigns the value of the host in the URI to the variable s. It uses regular expressions to determine if the host is an IP address or if it is surrounded by square brackets (for IPv6 addresses). If either condition is true, the hostIsIpAddress variable is set to true.

private Helper parse(String inUrl, boolean allowTryPrefixed, String prefix) throws URISyntaxException
private Helper parse(String inUrl, boolean allowTryPrefixed, String prefix) throws URISyntaxException {
Helper helper = new Helper();
try {
helper.url = inUrl.trim();
helper.uri = new URI(helper.url);
return helper;
} catch (URISyntaxException e) {
if (allowTryPrefixed && e.getMessage().contains(URI_E_ALLOW_TRY_PREFIXED)) {
// [4]
return tryPrefixed(helper, prefix);
} else {
// [5]
throw e;
}
}
}The parse method is defined in the NatsUri class and takes in three parameters: inUrl, allowTryPrefixed, and prefix. It also throws a URISyntaxException.
The purpose of this method is to parse a given URL string (inUrl) and create a Helper object containing the parsed URL (uri) and the original URL (url).
Here is a step-by-step description of what this method does based on its body:
-
Create a new
Helperobject calledhelper. -
Trim the input URL string (
inUrl) and assign it to theurlfield of thehelperobject. -
Create a new
URIobject by passing theurlfield of thehelperobject to theURIconstructor and assign it to theurifield of thehelperobject. -
Try to return the
helperobject. However, if anURISyntaxExceptionis caught and theallowTryPrefixedparameter istrueand the exception message contains a certain string (URI_E_ALLOW_TRY_PREFIXED), execute the following steps: a. Return the result of calling thetryPrefixedmethod with thehelperobject and theprefixparameter as arguments. This method will attempt to parse the URL again with a prefix. -
If step 4 did not execute (i.e., no exception was caught or the conditions were not met), throw the caught
URISyntaxException.
In summary, the parse method takes a URL string, trims it, parses it into a URI object, and returns a Helper object containing the parsed URL. If an exception is caught and certain conditions are met, it tries to parse the URL again with a prefix. Otherwise, it rethrows the caught exception.
The parse method in the NatsUri class is used to parse a given URL into a Helper object. The method takes the input URL as a parameter and performs the following steps:
- The input URL is trimmed and assigned to the
urlfield of theHelperobject. - The
inUrlis transformed into aURIobject and assigned to theurifield of theHelperobject. - The
Helperobject is returned.
If an exception of type URISyntaxException occurs during the parsing process, the method handles it as follows:
- If the
allowTryPrefixedflag is set totrueand the exception message contains a specific stringURI_E_ALLOW_TRY_PREFIXED, the method executes thetryPrefixedmethod, passing thehelperandprefixas parameters. The value returned by thetryPrefixedmethod is then returned by theparsemethod. - If the above condition is not met or the
allowTryPrefixedflag is set tofalse, the original exception is rethrown.
In summary, the parse method is responsible for parsing a URL and returning a Helper object. It also handles any exceptions that occur during the parsing process, allowing for optional additional parsing attempts based on certain conditions.

public static String join(String delimiter, List<NatsUri> uris) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < uris.size(); i++) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(uris.get(i).toString());
}
return sb.toString();
}This method is used to join a list of NatsUri objects into a single string, separated by a delimiter.
- delimiter : String - The delimiter to be used for separating the joined strings.
- uris : List - The list of NatsUri objects to be joined.
- String - The joined string.
- Create a StringBuilder object,
sb, to store the joined string. - Iterate through the
urislist using a for loop. - Inside the loop, check if the current index (
i) is greater than 0. - If
iis greater than 0, append thedelimiterto thesbStringBuilder object. - Append the NatsUri object at index
iof theurislist to thesbStringBuilder object. - Outside the loop, convert the
sbStringBuilder object to a string using thetoString()method and return the result.
List<NatsUri> uris = new ArrayList<>();
uris.add(new NatsUri("nats://localhost:4222"));
uris.add(new NatsUri("nats://localhost:5222"));
uris.add(new NatsUri("nats://localhost:6222"));
String joinedString = NatsUri.join(",", uris);
System.out.println(joinedString);Output:
nats://localhost:4222,nats://localhost:5222,nats://localhost:6222
The join method in the NatsUri class is a static method that takes a delimiter and a list of NatsUri objects as input parameters. It returns a string that represents the concatenation of the toString() representation of each NatsUri object in the list, separated by the delimiter.
To accomplish this, the method creates a StringBuilder object and iterates over the uris list. If the current index is greater than 0, the delimiter is appended to the StringBuilder. Then, the toString() representation of the NatsUri at the current index is appended to the StringBuilder. Finally, the method returns the string representation of the StringBuilder using toString() method.
In summary, the join method in the NatsUri class is used to join a list of NatsUri objects into a single string, separated by a specified delimiter.

JsonParseException
The JsonParseException class is a subclass of IOException. It is used to represent an exception that occurs when there is an error parsing a JSON (JavaScript Object Notation) document. This class provides additional information and methods specifically related to handling parse errors in JSON.
ConsumerUtils
The ConsumerUtils class is an abstract class that provides utility methods for consumers. It serves as a base class for other classes and cannot be instantiated directly. The class encapsulates various functionality related to consumer operations, allowing software engineers to streamline and enhance their code when working with consumers.
NatsRequestCompletableFuture
This NatsRequestCompletableFuture class is an internal class that extends the CompletableFuture class. It is only made public for access.
WebsocketFrameHeader
WebsocketFrameHeader is a public class that represents the header of a WebSocket frame. It provides the necessary information about the frame, such as the frame type, payload length, and masking key. The header is an integral component in the process of sending and receiving WebSocket frames, facilitating the communication between a client and a server.
public WebsocketFrameHeader withMask(int maskingKey) {
this.mask = true;
this.maskingKey = maskingKey;
this.maskingKeyOffset = 0;
return this;
}The method withMask in the WebsocketFrameHeader class is used to enable masking for a WebSocket frame and sets the masking key for the frame. Here is a step-by-step description of what the method does:
- It takes an integer parameter
maskingKeyas input. - It sets the
maskfield of theWebsocketFrameHeaderobject totrue, indicating that masking is enabled for the frame. - It assigns the value of the
maskingKeyparameter to themaskingKeyfield of theWebsocketFrameHeaderobject. - It sets the
maskingKeyOffsetfield of theWebsocketFrameHeaderobject to 0. - It returns the updated
WebsocketFrameHeaderobject.
The withMask method essentially enables masking for a WebSocket frame by setting the necessary fields in the WebsocketFrameHeader object. The masking key is used to encode the frame payload for security purposes.
The withMask method in the WebsocketFrameHeader class is used to set the masking key for a websocket frame header. When a websocket frame is sent, it can be optionally masked for security reasons. The withMask method allows the developer to specify the masking key to be used for masking the frame data. The method sets the mask flag to true, assigns the specified masking key to the maskingKey variable, and sets the maskingKeyOffset to 0. Finally, it returns the updated WebsocketFrameHeader object.

public int filterPayload(byte[] buffer, int offset, int length) {
length = Math.min(length, payloadLength > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) payloadLength);
payloadLength -= length;
if (mask) {
for (int i = 0; i < length; i++) {
int key = 0xFF & (maskingKey >> (8 * (7 - maskingKeyOffset)));
buffer[offset + i] ^= key;
maskingKeyOffset = (maskingKeyOffset + 1) % 8;
}
}
return length;
}The filterPayload method in the WebsocketFrameHeader class is responsible for filtering the payload data in a WebSocket frame.
Here is a step-by-step breakdown of what the method is doing:
-
The method takes in three parameters:
buffer,offset, andlength. These parameters represent the payload data, the starting offset position in the buffer, and the length of the payload data, respectively. -
The method calculates the actual length of the payload data to filter. It uses the
Math.minmethod to ensure that the length does not exceed the value ofpayloadLengthor the maximum value of anint. ThepayloadLengthvariable represents the total length of the payload data. -
The
payloadLengthis decremented by the filtered length to keep track of the remaining payload data. -
If the WebSocket frame is masked (i.e., the
maskflag is true), the method proceeds to unmask the payload data. It iterates over each byte in the payload data, applying a XOR operation with an individual byte from themaskingKey. ThemaskingKeyOffsetis used to determine which byte of themaskingKeyto use for each iteration. -
The method increments the
maskingKeyOffsetby 1, wrapping around to zero when it reaches the value of 7, to ensure that the bytes from themaskingKeyare applied in a sequential order. -
Finally, the method returns the filtered length of the payload data.
This method is typically called when processing WebSocket frames to extract the payload data while handling the frame-specific details such as masking.
The filterPayload method in io.nats.client.support.WebsocketFrameHeader class is used to filter the payload data by manipulating the provided input buffer.
The method takes in three parameters: buffer (the input byte array), offset (the starting position within the buffer), and length (the number of bytes to filter).
First, the method ensures that length does not exceed the remaining payload length by comparing it to payloadLength. If payloadLength is greater than Integer.MAX_VALUE, length is set to Integer.MAX_VALUE; otherwise, it is set to the value of payloadLength.
Next, if mask is true, the method iterates over each byte in the range of offset to offset + length - 1. It XORs each byte in the buffer with a corresponding mask key. The mask key is obtained by shifting the maskingKey (an 8-byte mask key) and applying bitwise AND with 0xFF. The maskingKeyOffset is updated to keep track of the current byte in the mask key.
Finally, the method returns the filtered length.
Overall, this method is responsible for filtering the payload data by applying a masking key (if applicable) to the input buffer.

public int size() {
int size = 2;
if (payloadLength > 0xFFFF) {
size += 8;
} else if (payloadLength > 125) {
size += 2;
}
if (mask) {
size += 4;
}
return size;
}The size method in the WebsocketFrameHeader class is responsible for determining the size of a websocket frame header based on the values specified in its BODY. Here is a step-by-step description of how the size method works:
-
The method initializes the
sizevariable with a value of 2. This is because a websocket frame header always has a minimum size of 2 bytes. -
The method checks if the
payloadLengthis greater than0xFFFF(65535 in decimal). This is the maximum length a payload can have without needing additional bytes to represent the length.a. If the
payloadLengthis greater than0xFFFF, it means that the payload length requires 8 additional bytes to be represented.b. In this case, the
sizevariable is incremented by 8. -
If the
payloadLengthis not greater than0xFFFF, the method checks if it is greater than 125.a. If the
payloadLengthis greater than 125, it means that the payload length requires 2 additional bytes to be represented.b. In this case, the
sizevariable is incremented by 2. -
The method then checks if the
maskflag is set. This flag indicates whether the payload is masked or not.a. If the
maskflag is set totrue, it means that the payload is masked and requires an additional 4 bytes to represent the masking key.b. In this case, the
sizevariable is incremented by 4. -
Finally, the
sizevariable is returned, which represents the total size of the websocket frame header based on the values specified in the BODY.
Note: The size method assumes that the payloadLength and mask variables have already been initialized with the correct values.
The size method in the io.nats.client.support.WebsocketFrameHeader class calculates the size of the WebSocket frame header based on the specified parameters in its body.
The method first initializes the size variable to 2. It then checks if the payloadLength is greater than 0xFFFF (65535). If it is, it increments the size by 8.
If the payloadLength is not greater than 0xFFFF, the method checks if it is greater than 125. If it is, the size is incremented by 2.
Next, the method checks if the mask flag is set. If it is, the size is further incremented by 4.
Finally, the method returns the calculated size.
This size method is used to determine the total size of the WebSocket frame header, which includes the length of the payload and any additional header fields such as the masking key.

public static int size(byte[] buffer, int offset) {
int size = 2;
if (0 != (buffer[offset + 1] & 0x80)) {
// mask adds 4 required bytes.
size += 4;
}
switch(buffer[offset + 1] & 0x7F) {
case 126:
size += 2;
break;
case 127:
size += 8;
break;
}
return size;
}The size(byte[] buffer, int offset) method in the WebsocketFrameHeader class is responsible for determining the size of the WebSocket frame based on the provided buffer and offset.
Here is a step-by-step description of how the method works:
-
The method starts by initializing the
sizevariable with a value of 2. This is because every WebSocket frame has a minimum size of 2 bytes. -
The method then checks if the most significant bit of the second byte in the
buffer(at the givenoffset) is set to 1. This bit is used to indicate whether the frame payload is masked or not. If the bit is set (i.e., not equal to 0), it means that the payload is masked and an additional 4 bytes are required. In this case, thesizeis incremented by 4. -
Next, the method examines the least significant 7 bits of the second byte in the
buffer(at the givenoffset). These bits represent the payload length. Based on the value of these bits, the method takes different actions:a. If the value is 126 (i.e., the payload length is encoded in the next two bytes), the
sizeis incremented by 2 to account for these additional bytes.b. If the value is 127 (i.e., the payload length is encoded in the next eight bytes), the
sizeis incremented by 8 to account for these additional bytes. -
Finally, the method returns the calculated
sizevalue, which represents the total size of the WebSocket frame.
By following this step-by-step process, the size(byte[] buffer, int offset) method accurately calculates the size of a WebSocket frame based on the provided buffer and offset.
The method size in class io.nats.client.support.WebsocketFrameHeader is responsible for determining the size of a WebSocket frame.
The method takes in a byte array buffer and an offset value.
First, it initializes the size variable to 2, which accounts for the initial 2 bytes of WebSocket frame header.
Then, it checks if the second byte in the buffer has the most significant bit (0x80) set. If it is set, it means that a masking key is present in the frame, and 4 additional bytes are required, so it increments the size by 4.
Next, it examines the value of the last 7 bits of the second byte to determine the payload length.
If the last 7 bits are equal to 126, it means that the payload length is stored in the next 2 bytes. In this case, the size is incremented by 2.
If the last 7 bits are equal to 127, it means that the payload length is stored in the next 8 bytes. In this case, the size is incremented by 8.
Finally, the method returns the calculated size.

public int read(byte[] buffer, int offset, int length) {
if (length < size()) {
return 0;
}
int startOffset = offset;
buffer[offset++] = byte0;
if (payloadLength > 0xFFFF) {
buffer[offset++] = (byte) (127 | (mask ? 0x80 : 0));
// 64 bit length
buffer[offset++] = (byte) ((payloadLength >> 56) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 48) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 40) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 32) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 24) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 16) & 0xFF);
buffer[offset++] = (byte) ((payloadLength >> 8) & 0xFF);
buffer[offset++] = (byte) (payloadLength & 0xFF);
} else if (payloadLength > 125) {
buffer[offset++] = (byte) (126 | (mask ? 0x80 : 0));
// 16 bit length
buffer[offset++] = (byte) (payloadLength >> 8);
buffer[offset++] = (byte) (payloadLength & 0xFF);
} else {
buffer[offset++] = (byte) (payloadLength | (mask ? 0x80 : 0));
}
if (mask) {
buffer[offset++] = (byte) ((maskingKey >> 24) & 0xFF);
buffer[offset++] = (byte) ((maskingKey >> 16) & 0xFF);
buffer[offset++] = (byte) ((maskingKey >> 8) & 0xFF);
buffer[offset++] = (byte) (maskingKey & 0xFF);
}
return offset - startOffset;
}The read() method in the WebsocketFrameHeader class is responsible for reading the WebSocket frame header data into a byte array buffer. Here is a step-by-step description of what this method does:
-
Check if the given length is less than the size of the WebSocket frame header. If it is, return 0 (indicating that no data was read).
-
Initialize the
startOffsetvariable with the value ofoffset. This will be used to calculate the number of bytes read. -
Write the
byte0value to thebufferat the position specified byoffset. Incrementoffsetby 1. -
Check if the
payloadLengthis greater than0xFFFF(65,535 in decimal). If it is, this indicates a payload length larger than can be represented in 16 bits. -
If the payload length is larger than 65,535, set the appropriate value in the
bufferatoffsetto indicate the extended payload length. Incrementoffsetby 1. -
Write the 64-bit payload length to the
bufferat positionsoffsettooffset + 8. The payload length is broken down into 8 bytes, each representing a different part of the 64-bit value. Incrementoffsetby 8. -
If the payload length is between 126 and 65,535 (inclusive), set the appropriate value in the
bufferat the position specified byoffset. Incrementoffsetby 1. -
If the payload length is less than or equal to 125, set the appropriate value in the
bufferat the position specified byoffset. Incrementoffsetby 1. -
If the
maskflag is set, write the 32-bit masking key to thebufferat positionsoffsettooffset + 3. The masking key is broken down into 4 bytes, each representing a different part of the 32-bit value. Incrementoffsetby 4. -
Calculate the number of bytes read by subtracting
startOffsetfrom the current value ofoffset. -
Return the calculated number of bytes read.
Note: The byte0, payloadLength, and maskingKey variables, which are used in the method, are not defined in the provided code snippet. They should be declared and initialized elsewhere in the class.
The read method in the WebsocketFrameHeader class is used to read and format the header of a WebSocket frame. The method takes in a byte array buffer, an offset value, and a length value. It fills the buffer array with the appropriate header values based on the size and payload length of the frame.
Here's a breakdown of what the method does:
-
It checks if the length provided is sufficient to accommodate the size of the frame. If not, it returns 0.
-
It sets the initial offset and stores the first byte of the frame header in the
buffer. -
If the payload length is greater than
0xFFFF(more than 65535 bytes), it sets the appropriate flag in the header and stores the payload length as a 64-bit value in thebuffer. The payload length is split into 8 bytes and stored in thebufferarray. -
If the payload length is between 126 and 65535 bytes, it sets the appropriate flag in the header and stores the payload length as a 16-bit value in the
buffer. The payload length is split into 2 bytes and stored in thebufferarray. -
If the payload length is less than or equal to 125 bytes, it sets the payload length directly in the header of the
buffer. -
If the masking flag is set, it stores the masking key (used for data masking during transmission) in the
buffer. The masking key is split into 4 bytes and stored in thebufferarray. -
Finally, it returns the difference between the final offset and the starting offset, indicating the number of bytes written to the
buffer.
The read method is responsible for populating the buffer array with the appropriate values to construct the header of a WebSocket frame.

public int write(byte[] buffer, int offset, int length) {
// Sufficient remainder?
if (length < 2) {
return 0;
}
int size = size(buffer, offset);
if (size > length) {
return 0;
}
byte0 = buffer[offset++];
mask = 0 != (buffer[offset] & 0x80);
payloadLength = buffer[offset] & 0x7F;
offset++;
if (126 == payloadLength) {
payloadLength = 0;
for (int i = 0; i < 2; i++) {
payloadLength <<= 8;
payloadLength |= buffer[offset++] & 0xFF;
}
} else if (127 == payloadLength) {
payloadLength = 0;
for (int i = 0; i < 8; i++) {
payloadLength <<= 8;
payloadLength |= buffer[offset++] & 0xFF;
}
}
if (mask) {
maskingKey = 0;
maskingKeyOffset = 0;
for (int i = 0; i < 4; i++) {
maskingKey <<= 8;
maskingKey |= buffer[offset++] & 0xFF;
}
}
return size;
}The write method described here is defined in the WebsocketFrameHeader class in the io.nats.client.support package.
Based on the provided body of the method, here is the step-by-step description of what it does:
- Check if the
lengthparameter is less than 2. If it is, return 0. - Calculate the size based on the
bufferandoffset. This is done by calling another method calledsize(not shown in the provided body). - Check if the calculated size is greater than the
length. If it is, return 0. - Assign the next byte in the
bufferatoffsettobyte0. - Check if the most significant bit (bit 7) of the next byte in the
bufferatoffsetis set (1). If it is, set themaskflag to true. - Set
payloadLengthto the least significant 7 bits of the next byte in thebufferatoffset. - Increment
offsetby 1. - If the
payloadLengthis 126:- Reset
payloadLengthto 0. - Iterate over the next 2 bytes in the
bufferstarting from the updatedoffset. - Concatenate the 8 bits from each byte to form a 16-bit value and assign it to
payloadLength. - Increment
offsetby 2.
- Reset
- If the
payloadLengthis 127:- Reset
payloadLengthto 0. - Iterate over the next 8 bytes in the
bufferstarting from the updatedoffset. - Concatenate the 8 bits from each byte to form a 64-bit value and assign it to
payloadLength. - Increment
offsetby 8.
- Reset
- If
maskis true:- Reset
maskingKeyandmaskingKeyOffsetto 0. - Iterate over the next 4 bytes in the
bufferstarting from the updatedoffset. - Concatenate the 8 bits from each byte to form a 32-bit value and assign it to
maskingKey. - Increment
offsetby 4.
- Reset
- Finally, return the calculated size.
Please note that there may be additional code in the WebsocketFrameHeader class that could affect the behavior and functionality of this method. The code provided here only describes the logic within the write method itself.
The method write in the WebsocketFrameHeader class is used to write a Websocket frame header into a byte array.
Here is a step-by-step breakdown of what the method does:
-
It first checks if the length of the buffer is less than 2. If it is, it returns 0, indicating that no frame header was written.
-
It calculates the size of the frame header using another method called
size. -
It checks if the calculated size is greater than the length provided. If it is, it returns 0, indicating that no frame header was written.
-
It reads the first byte from the buffer and assigns it to
byte0. -
It checks if the most significant bit (MSB) of the next byte (offset byte) is set. If it is, it sets the
maskflag to true, indicating that the payload is masked. -
It extracts the payload length from the offset byte by performing a bitwise AND operation with
0x7F. -
It increments the offset to move to the next byte in the buffer.
-
If the payload length is 126, it reads the next 2 bytes from the buffer and combines them to form the actual payload length.
-
If the payload length is 127, it reads the next 8 bytes from the buffer and combines them to form the actual payload length.
-
If the payload is masked (mask flag is true), it reads the next 4 bytes from the buffer and combines them to form the masking key.
-
Finally, it returns the size of the frame header.
Note: The method assumes that the buffer provided has enough space to accommodate the frame header.

JsonUtils
The JsonUtils class is an abstract class that provides internal helpers for parsing JSON. It includes read helpers that are deprecated and recommends using the JsonParser instead.
// ---------------------------------------------------------------------------------------------------- // BUILD A STRING OF JSON // ---------------------------------------------------------------------------------------------------- public static StringBuilder beginJson()
/* ensures cannot be constructed */
// ----------------------------------------------------------------------------------------------------
// BUILD A STRING OF JSON
// ----------------------------------------------------------------------------------------------------
public static StringBuilder beginJson() {
return new StringBuilder("{");
}The beginJson method is a static method defined in the JsonUtils class in the io.nats.client.support package. It takes no arguments and returns a StringBuilder object.
Here is the step-by-step description of what the beginJson method is doing based on its body:
-
The method starts with a comment stating that it ensures the method cannot be constructed. This means that the method is declared as private or a static utility and cannot be instantiated.
-
The method starts building a string of JSON by creating a new
StringBuilderobject. -
The
beginJsonmethod sets the initial character of the JSON string as an opening curly brace{. This indicates the start of a JSON object. -
Finally, the method returns the
StringBuilderobject that represents the beginning of the JSON string.
Note: The provided description is based solely on the information given in the body of the beginJson method. The actual functionality and purpose of the method may depend on its usage and other parts of the codebase.
The beginJson method in the JsonUtils class of the io.nats.client.support package returns a StringBuilder object initialized with a starting curly brace '{'. This method is used to build a string representation of JSON by appending elements to the StringBuilder.

public static StringBuilder endJson(StringBuilder sb) {
int lastIndex = sb.length() - 1;
if (sb.charAt(lastIndex) == ',') {
sb.setCharAt(lastIndex, '}');
return sb;
}
sb.append("}");
return sb;
}The endJson method in the JsonUtils class is used to complete the construction of a JSON string by adding the closing brace '}' at the end.
The method takes a StringBuilder object sb as input and modifies it as follows:
- It retrieves the index of the last character in the
StringBuilderusingsb.length() - 1. - It checks if the last character of the
StringBuilderis a comma ',' by usingsb.charAt(lastIndex) == ','. - If the last character is a comma, it replaces it with a closing brace '}' by using
sb.setCharAt(lastIndex, '}').- This is done to remove the trailing comma which is not valid in JSON syntax.
- If the last character is not a comma, it appends the closing brace '}' to the
StringBuilderusingsb.append("}").- This is done to add the closing brace at the end of the JSON string.
Finally, the method returns the modified StringBuilder object sb.
Overall, the purpose of the endJson method is to ensure that the JSON string being constructed is correctly and completely formatted by adding the closing brace '}' if it is missing, and by removing any trailing comma ',' if present.
The endJson method, defined in the JsonUtils class in the io.nats.client.support package, is used to correctly format the end of a JSON string.
The method takes a StringBuilder parameter sb and performs the following operations:
- It retrieves the index of the last character in the
sbstring. - If the last character is a comma (
,), it replaces it with a closing brace (}) to complete the JSON object structure, and returns the modifiedStringBuilderobject. - If the last character is not a comma, it appends a closing brace (
}) to thesbstring to complete the JSON object structure, and returns the modifiedStringBuilderobject.
Overall, the endJson method ensures that the end of a JSON string is properly formatted by adding a closing brace (}) if necessary.

public static StringBuilder endArray(StringBuilder sb) {
int lastIndex = sb.length() - 1;
if (sb.charAt(lastIndex) == ',') {
sb.setCharAt(lastIndex, ']');
return sb;
}
sb.append("]");
return sb;
}Method Name: endArray(StringBuilder sb)
Class: io.nats.client.support.JsonUtils
Description:
The endArray method is used to complete an array in a JSON string representation. It takes a StringBuilder as its parameter and returns the updated StringBuilder with the array closing bracket added.
Steps:
- Get the index of the last character in the
StringBuilderby subtracting 1 from the length of theStringBuilder. - Check if the last character in the
StringBuilderis a comma (',') by comparing it with ',' using thecharAtmethod on theStringBuilder. - If the last character is a comma, replace it with a closing bracket (']') using the
setCharAtmethod on theStringBuilder. - Return the updated
StringBuilder. - If the last character is not a comma, append a closing bracket (']') to the
StringBuilderusing theappendmethod. - Return the updated
StringBuilder.
The endArray method, defined in the io.nats.client.support.JsonUtils class, is used to properly close an array in a JSON string.
It takes a StringBuilder as input and checks if the last character of the StringBuilder is a comma (','), indicating that there are more items in the array. If it is a comma, the method replaces it with a closing bracket (']') to close the array and returns the StringBuilder.
If the last character is not a comma, the method appends a closing bracket to the StringBuilder and returns it.
Overall, the endArray method ensures that the JSON string is well-formed by closing the array properly.

public static void addRawJson(StringBuilder sb, String fname, String json) {
if (json != null && json.length() > 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON);
sb.append(json);
sb.append(COMMA);
}
}The addRawJson method is defined in the JsonUtils class, located in the io.nats.client.support package.
public static void addRawJson(StringBuilder sb, String fname, String json)The purpose of the addRawJson method is to add raw JSON data to a provided StringBuilder in a specific format. It takes three parameters:
-
sb: TheStringBuilderobject to which the JSON data is added. -
fname: A string representing the field name of the JSON data. -
json: A string containing the raw JSON data to be added.
The method performs the following steps:
- Checks if the
jsonparameter is not null and has a length greater than 0. - If the
jsonparameter meets the conditions from step 1, the following actions are performed:- Appends a double quotation mark (
") to thesbStringBuilder. - Encodes the
fnameparameter using a JSON encoding algorithm and appends it to thesbStringBuilder. - Appends a colon (
:) to thesbStringBuilder. - Appends the
jsonparameter to thesbStringBuilder. - Appends a comma (
,) to thesbStringBuilder.
- Appends a double quotation mark (
- If the
jsonparameter does not meet the conditions from step 1, no action is taken.
Once the addRawJson method has finished execution, the provided StringBuilder will contain the added raw JSON data in the specified format.
The addRawJson method defined in the JsonUtils class in the io.nats.client.support package is responsible for adding raw JSON data to a StringBuilder object.
The method takes three parameters: sb (the StringBuilder object to append the JSON data to), fname (the name of the field/key in the JSON object), and json (the raw JSON data as a string).
The method first checks if the json parameter is not null and has a length greater than 0. If this condition is true, it adds the field/key name (fname) and the colon character (:) to the sb StringBuilder object. Then, it appends the raw JSON data (json) to the sb object, followed by a comma character (,). This allows for the creation of a properly formatted JSON object.
The purpose of this method is to facilitate the building of JSON messages or payloads by allowing the addition of raw JSON data to a StringBuilder object, which can then be used to construct a complete JSON message.

public static void addField(StringBuilder sb, String fname, String value) {
if (value != null && value.length() > 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLONQ);
jsonEncode(sb, value);
sb.append(QCOMMA);
}
}The addField method is defined in the JsonUtils class in the io.nats.client.support package. It takes in three parameters: sb of type StringBuilder, fname of type String, and value of type String.
This method is responsible for adding a field to a JSON string representation in a step-by-step manner.
Here is a breakdown of the steps performed by this method:
-
Check if the
valueparameter is not null and its length is greater than 0:- If the condition is not met, the method exits without performing any further steps.
-
If the condition is met, the method performs the following steps:
- Append an opening quote to the
StringBuilder(sb) using theappendmethod:sb.append(Q). - Call the
jsonEncodemethod, passingsbandfnameas arguments to encode the field name as JSON. This method encodes special characters and escapes them if necessary. - Append a colon and a trailing quote to
sbusing theappendmethod:sb.append(QCOLONQ). - Call the
jsonEncodemethod, passingsbandvalueas arguments to encode the field value as JSON. - Append a comma to
sbusing theappendmethod:sb.append(QCOMMA).
- Append an opening quote to the
This method assumes that the jsonEncode method is available and properly implemented.
The addField method in class JsonUtils is used to add a field to a JSON string.
It takes in a StringBuilder object (sb), the name of the field (fname), and the value of the field (value) as parameters.
The method checks if the value is not null and has a length greater than 0. If it meets this condition, it encodes the field name and value as JSON strings and appends them to the StringBuilder object with specific JSON formatting.

public static void addFieldEvenEmpty(StringBuilder sb, String fname, String value) {
if (value == null) {
value = "";
}
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLONQ);
jsonEncode(sb, value);
sb.append(QCOMMA);
}The addFieldEvenEmpty method in the JsonUtils class is used to add a field to a JSON object represented as a StringBuilder. The method takes three parameters: sb, fname, and value.
Here is a step-by-step description of what the method does:
- Check if the
valueparameter isnull. - If the
valueisnull, assign an empty string ("") to thevaluevariable. - Append a double quote (
") to theStringBuilder(sb) to denote the beginning of the field. - Encode the
fnameusing thejsonEncodemethod and append it to theStringBuilder(sb). - Append a colon (
:) and a double quote (") to theStringBuilder(sb) to separate the field name and value. - Encode the
valueusing thejsonEncodemethod and append it to theStringBuilder(sb). - Append a comma (
,) to theStringBuilder(sb) to separate multiple fields in a JSON object.
The addFieldEvenEmpty method is a static method defined in the JsonUtils class.
This method takes in three parameters: StringBuilder sb, String fname, and String value.
The purpose of this method is to add a key-value pair field to a JSON string, even if the value is empty or null.
Here's a breakdown of what the method does:
- It first checks if the
valueparameter is null. If it is, it sets thevalueto an empty string. - It then appends a double quotation mark (
") to theStringBuildersbobject. - It encodes the
fnameparameter using thejsonEncodemethod and appends it to thesb. - It appends a colon (
:) and another double quotation mark to thesb. - It encodes the
valueparameter using thejsonEncodemethod and appends it to thesb. - Finally, it appends a comma (
,) to thesbto separate multiple key-value pairs in the JSON string.
Overall, the method ensures that even if the value is empty or null, the key-value pair will still be added to the JSON string.

public static void addField(StringBuilder sb, String fname, Boolean value) {
if (value != null) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value ? "true" : "false").append(COMMA);
}
}The addField method in the class io.nats.client.support.JsonUtils is used to add a Boolean field to a JSON object represented by a StringBuilder object.
Here is a step-by-step description of how the addField method works:
-
Accepts three parameters:
sb,fname, andvalue.-
sbis aStringBuilderobject representing the JSON object. -
fnameis aStringrepresenting the name of the field to be added. -
valueis aBooleanrepresenting the value of the field to be added.
-
-
Checks if the
valueis notnull.- If the
valueisnull, nothing will be done. The method will return without modifying the JSON.
- If the
-
If the
valueis notnull, the following steps are performed:- Appends a quotation mark (
") to thesbto start the field definition. - Encodes the
fnameusing thejsonEncodemethod and appends it to thesb. - Appends a colon (
:) to separate the field name and its value. - Appends the string representation of the
valueto thesbbased on whether it istrueorfalse. - Appends a comma (
,) to thesbto indicate that there are more fields to be added.
- Appends a quotation mark (
-
The method execution ends, and the modified
sbcan be used to represent the updated JSON object.
Note that the method assumes that the jsonEncode and constants (Q, QCOLON, and COMMA) are defined elsewhere in the class or imported from another package. The specific implementations of these dependencies are not mentioned in the given code snippet.
The addField method in JsonUtils class allows you to add a new field with a Boolean value to a JSON string.
The method takes three parameters:
-
sb- aStringBuilderobject representing the JSON string to which the field will be added. -
fname- aStringindicating the name of the field. -
value- aBooleanvalue that will be assigned to the field.
Inside the method, it first checks if the value parameter is not null. If the value is not null, it appends the field to the sb string. The field is enclosed in quotes ("), the field name is encoded using the jsonEncode method, followed by a colon (:), and then the boolean value ("true" or "false") is appended. Finally, a comma (,) is added to separate this field from other fields in the JSON string.

public static void addField(StringBuilder sb, String fname, Integer value) {
if (value != null && value >= 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value).append(COMMA);
}
}This method is defined in the io.nats.client.support.JsonUtils class and is used to add a field to a StringBuilder object based on the provided fname (field name) and value parameters.
-
sb(StringBuilder): TheStringBuilderobject to which the field is added. -
fname(String): The name of the field to be added. -
value(Integer): The value of the field to be added.
- Check if the
valueparameter is not null and greater than or equal to 0. - If the condition is satisfied, perform the following sub-steps:
- Append the double quotation mark (
") to thesb(StringBuilder) object. - Perform JSON encoding of the
fnameusing thejsonEncodemethod and append the result to thesbobject. - Append the colon (
:) character to thesbobject. - Append the
valueparameter to thesbobject. - Append a comma (
,) to thesbobject.
- Append the double quotation mark (
- Continue with the execution of the remaining code.
The addField method in the JsonUtils class is a static method that adds a field to a StringBuilder object in JSON format. The method takes three parameters - a StringBuilder object sb, a String fname for the field name, and an Integer value for the field value.
The method first checks if the value is not null and if it is greater than or equal to zero. If both conditions are true, the method appends the field name in double quotes (using the jsonEncode method), followed by a colon, the value, and a comma to separate it from other fields in the JSON object.

public static void addFieldWhenGtZero(StringBuilder sb, String fname, Integer value) {
if (value != null && value > 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value).append(COMMA);
}
}Class: io.nats.client.support.JsonUtils
This method is used to add a field to a StringBuilder object if the given value is not null and greater than zero.
-
sb:StringBuilder- theStringBuilderobject to which the field is appended. -
fname:String- the name of the field. -
value:Integer- the value of the field.
- Check if the value is not null and greater than zero.
- If the above condition is true, perform the following steps:
- Append a quotation mark (
") to theStringBuilderobject. - Encode the field name using the
jsonEncodemethod and append it to theStringBuilderobject. - Append
":value,"to theStringBuilderobject, wherevalueis the value of the field.
- Append a quotation mark (
The addFieldWhenGtZero method in the JsonUtils class is a utility method used for adding a field to a JSON string if the provided value is greater than zero. It takes three parameters: a StringBuilder object sb, a String fname representing the field name, and an Integer value representing the field value.
Inside the method, it checks if the value is not null and greater than zero. If both conditions are true, it appends the field name, encoded in JSON format, followed by a colon and the value to the sb. The field is then separated from other fields by a comma.
This method helps in constructing a JSON string by adding a field only when its value is greater than zero.

public static void addField(StringBuilder sb, String fname, Long value) {
if (value != null && value >= 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value).append(COMMA);
}
}The addField method is a static method defined in the class io.nats.client.support.JsonUtils. It is used to add a field to a JSON string representation in a step-by-step manner.
public static void addField(StringBuilder sb, String fname, Long value)
-
sb(StringBuilder): TheStringBuilderobject representing the JSON string. -
fname(String): The name of the field to be added. -
value(Long): The value of the field to be added.
- Check if the value is not null and is greater than or equal to 0.
- If the condition is true, perform the following sub-steps:
a. Append a quotation mark (
") to theStringBuilder(sb) to start the field. b. Perform JSON encode on the field name (fname) using thejsonEncodemethod and append it to theStringBuilder(sb). c. Append a colon (:) to theStringBuilder(sb). d. Append the value (value) to theStringBuilder(sb). e. Append a comma (,) to theStringBuilder(sb).
Note: The Q, QCOLON, and COMMA constants are not provided in the code snippet, but they are assumed to represent the respective characters: ", :, and ,.
The addField method in the io.nats.client.support.JsonUtils class is used to add a field to a JSON formatted string. The method takes three parameters: a StringBuilder object sb, a String parameter fname representing the name of the field, and a Long parameter value representing the value of the field.
The method first checks if the value is not null and greater than or equal to 0. If this condition is true, the method appends the field name in JSON format to the StringBuilder using the jsonEncode method, and then appends the colon symbol and the value to the StringBuilder. Finally, it adds a comma at the end to separate this field from the next field, if any.

public static void addFieldWhenGtZero(StringBuilder sb, String fname, Long value) {
if (value != null && value > 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value).append(COMMA);
}
}This method is defined in the class io.nats.client.support.JsonUtils and is used to add a field to a StringBuilder object when the value of the field is greater than zero.
public static void addFieldWhenGtZero(StringBuilder sb, String fname, Long value)-
sb(StringBuilder): A StringBuilder object to which the field will be added. -
fname(String): The name of the field being added. -
value(Long): The value of the field being added.
- Check if the value is not null and is greater than zero.
- If the above condition is true, perform the following steps:
- Append a quotation mark (
") to the StringBuilder objectsb. - Encode the field name (
fname) using thejsonEncode()method and append it tosb. - Append a colon (
:) character, followed by the value of the field (value), and a comma (,).
- Append a quotation mark (
- If the above condition is false, do nothing.
Note: The method assumes the existence of a jsonEncode() method which is not defined in the provided information.
StringBuilder sb = new StringBuilder();
String fname = "count";
Long value = 10L;
addFieldWhenGtZero(sb, fname, value);
// The StringBuilder object sb would contain the following:
// "count":10,The addFieldWhenGtZero method in the JsonUtils class is a utility method that adds a field to a JSON string if the given value is greater than zero.
The method takes in a StringBuilder object sb, which represents the JSON string being built, a String object fname, which represents the name of the field being added, and a Long object value, which represents the value of the field.
The method checks if the value is not null and is greater than zero. If this condition is true, the method encodes the fname as a JSON string, appends it to the sb with a colon and the value, and adds a comma to separate it from other fields.
This method is useful when constructing a JSON object where certain fields should only be included if their values meet a certain condition, specifically if they are greater than zero in this case.

public static void addFieldWhenGteMinusOne(StringBuilder sb, String fname, Long value) {
if (value != null && value >= -1) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value).append(COMMA);
}
}The addFieldWhenGteMinusOne method in the JsonUtils class is used to add a field (in JSON format) to a StringBuilder object if the provided value is not null and is greater than or equal to -1.
Here is a step-by-step description of how this method works:
-
Check if the
valueparameter is not null and is greater than or equal to -1.- If the condition is false, the method will simply return without making any changes.
-
If the condition is true, the method continues to add the field to the
StringBuilderobject:- The JSON key
fnameis appended to theStringBuilderobject, passed as thesbparameter. - The key is enclosed within double quotes by first appending
Q(which represents the double quote character) to theStringBuilderobject, and then invoking thejsonEncodemethod to encode thefnamevalue and append it to theStringBuilder. This ensures that the key is properly formatted for JSON. - A colon character (
:) is appended to theStringBuilderobject usingQCOLON. - The
valueparameter is appended to theStringBuilderobject. - Finally, a comma character (
,) is appended to theStringBuilderobject, which allows for adding multiple fields within the same JSON object.
- The JSON key
Please note that the variables Q, QCOLON, and COMMA are assumed to be predefined constants representing the respective characters. The jsonEncode method is not provided in the code snippet, but it is expected to handle the encoding of the fname value to ensure it is properly escaped for JSON.
The addFieldWhenGteMinusOne method in JsonUtils class is used to add a field to a StringBuilder object if the provided value is not null and greater than or equal to -1.
The method checks if the value is valid and appends the field name, the value itself, and a comma to the StringBuilder object in a JSON format. The field name is JSON-encoded using the jsonEncode method.

public static void addFieldAsNanos(StringBuilder sb, String fname, Duration value) {
if (value != null && value != Duration.ZERO) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value.toNanos()).append(COMMA);
}
}The addFieldAsNanos method in the JsonUtils class is used to add a field with a Duration value in nanoseconds to a StringBuilder object, based on the provided parameters.
Here is a step-by-step description of what the method does:
-
Check if the
valueis notnulland not equal toDuration.ZERO.if (value != null && value != Duration.ZERO)
-
If the above condition is
true, then continue with the following steps.- This check is used to ignore the
nullor zero duration values and prevent adding unnecessary fields to theStringBuilder.
- This check is used to ignore the
-
Append the opening quotation mark to the
StringBuilder.sb.append(Q)
-
Encode the
fname(field name) using thejsonEncodemethod and append it to theStringBuilder.jsonEncode(sb, fname)
-
Append the closing quotation mark and a colon to the
StringBuilder.sb.append(QCOLON)
-
Append the
valueof theDurationobject converted to nanoseconds to theStringBuilder.sb.append(value.toNanos())
-
Append a comma to the end of the field and its value in the
StringBuilder.sb.append(COMMA)
The resulting StringBuilder object will contain the appended field and value in the format:
"fname":valueInNanoseconds,
Note: The variables Q, QCOLON, and COMMA are assumed to be constants representing the quotation mark, colon, and comma characters respectively.
The addFieldAsNanos method in the JsonUtils class is used to add a field to a StringBuilder object in the format of key-value pair, where the value is a Duration object represented in nanoseconds.
If the value parameter is not null and not equal to Duration.ZERO, then the method encodes the field name (fname) and appends it to the StringBuilder using JSON encoding. It then appends the value of the Duration object converted to nanoseconds, followed by a comma.

public static void addField(StringBuilder sb, String fname, JsonSerializable value) {
if (value != null) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLON).append(value.toJson()).append(COMMA);
}
}The addField method in the JsonUtils class is used to add a field to a StringBuilder object based on the provided parameters. Here is a step-by-step description of how the method works:
-
The method takes three parameters:
-
sb, which is a StringBuilder object representing the string to which the field will be added. -
fname, which is a String representing the name of the field. -
value, which is aJsonSerializableobject representing the value of the field.
-
-
The method first checks if the
valueparameter is not null using the if statement. -
If the value is not null, the method proceeds to the next steps. Otherwise, it does nothing.
-
The method appends a double quotation mark (
") to thesbStringBuilder object using theappendmethod. -
The method then encodes the
fnameparameter as a JSON string using thejsonEncodemethod, and appends it to thesbStringBuilder object using theappendmethod. -
The method appends a colon (
:) character to thesbStringBuilder object using theappendmethod. -
The method converts the
valueparameter to its JSON representation by calling thetoJsonmethod on thevalueobject. The resulting JSON string is then appended to thesbStringBuilder object using theappendmethod. -
Finally, the method appends a comma (
,) character to thesbStringBuilder object using theappendmethod.
Note: The method does not perform any error checking or exception handling. It assumes that the provided parameters are valid and do not cause any issues during the method execution.
The addField method in the io.nats.client.support.JsonUtils class is used to add a new field to a JSON string.
The method takes three parameters:
-
sb(StringBuilder): The StringBuilder object used to build the JSON string. -
fname(String): The name of the field to be added. -
value(JsonSerializable): The value of the field.
The method first checks if the value parameter is not null. If it is not null, the method proceeds to add the field to the JSON string.
The field is added in the following format: "fname":value.toJson(),.
fname is the name of the field, value.toJson() is the serialized representation of the value, and , is the comma used to separate multiple fields in the JSON string.
Note that the method uses the jsonEncode method to encode the field name before appending it to the StringBuilder object.

public static <T> void _addList(StringBuilder sb, String fname, List<T> list, ListAdder<T> adder) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append("\":[");
for (int i = 0; i < list.size(); i++) {
if (i > 0) {
sb.append(COMMA);
}
adder.append(sb, list.get(i));
}
sb.append("],");
}
```### private static void _addStrings(StringBuilder sb, String fname, List<String> strings)
```java
private static void _addStrings(StringBuilder sb, String fname, List<String> strings) {
_addList(sb, fname, strings, (sbs, s) -> {
sb.append(Q);
jsonEncode(sb, s);
sb.append(Q);
});
}The method _addStrings in class io.nats.client.support.JsonUtils is used to add a list of strings to a StringBuilder with JSON encoding.
Here is a step-by-step description of what the method does based on its body:
- Define the method
_addStringsas private and static. - Pass a
StringBuilder(sb), a field name (fname), and a list of strings (strings) as arguments to the method. - Call the
_addListmethod, passingsb,fname, andstringsas arguments to it. The_addListmethod is another method in the class. - In the
_addListmethod, a lambda expression is used to define a function for encoding each string in the list. The lambda takes two arguments: aStringBuilder(sbs) and a string (s). - Inside the lambda, append the character Q (which is likely a constant or variable representing a quote character) to the
StringBuildersb. - Call the
jsonEncodemethod, passingsband the stringsas arguments to it. ThejsonEncodemethod likely encodes the string using some JSON encoding rules. - Append the character Q to the
StringBuildersbagain, completing the encoding of the string. - The
_addListmethod takes care of adding the encoded strings tosbin a list format. - Once the
_addListmethod returns, the_addStringsmethod is complete and returns.
The _addStrings method is a private static method defined in the io.nats.client.support.JsonUtils class. It takes three parameters: a StringBuilder object (sb), a string (fname), and a list of strings (strings).
The purpose of this method is to add a list of strings as a JSON array to the StringBuilder object. It achieves this by using the _addList method (not shown in the provided code snippet) to iterate through each string in the strings list.
For each string, the method appends a double quotation mark (") to the StringBuilder (sb), then encodes the string using the jsonEncode method (not shown in the provided code snippet), and finally appends another double quotation mark (") to the StringBuilder.
Overall, the _addStrings method is responsible for adding a list of strings as a JSON array to a StringBuilder object by properly formatting each string within double quotation marks.

public static void addField(StringBuilder sb, String fname, ZonedDateTime zonedDateTime) {
if (zonedDateTime != null && !DEFAULT_TIME.equals(zonedDateTime)) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append(QCOLONQ).append(DateTimeUtils.toRfc3339(zonedDateTime)).append(QCOMMA);
}
}The addField method is defined in the io.nats.client.support.JsonUtils class. It takes three parameters: sb of type StringBuilder, fname of type String, and zonedDateTime of type ZonedDateTime. The method is used to add a field to the JSON object represented by the StringBuilder sb.
First, the method checks if the zonedDateTime parameter is not null and is not equal to DEFAULT_TIME.
If the condition in Step 1 is true, the method proceeds to add the field to the JSON object.
The method appends a double quote (") character to the sb StringBuilder.
The jsonEncode method is called to encode the fname parameter and append the encoded value to the sb StringBuilder.
The method appends a double quote (") character, a colon (:) character, and another double quote (") character to the sb StringBuilder.
The DateTimeUtils.toRfc3339 method is called to convert the zonedDateTime parameter to the RFC 3339 format. The resulting string is appended to the sb StringBuilder.
The method appends a double quote (") character, a comma (,), and a newline character to the sb StringBuilder.
The addField method is complete. The updated sb StringBuilder now contains the JSON object with the new field added.
The addField method in the JsonUtils class is used to add a field to a JSON string. It takes in a StringBuilder object sb, a field name fname, and a ZonedDateTime object zonedDateTime.
If the zonedDateTime is not null and is not equal to the default time, it encodes the field name and appends it, along with the serialized representation of the zonedDateTime in RFC 3339 format, to the StringBuilder sb followed by a comma.

public static void addField(StringBuilder sb, String fname, Headers headers) {
if (headers != null && headers.size() > 0) {
sb.append(Q);
jsonEncode(sb, fname);
sb.append("\":{");
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
addStrings(sb, entry.getKey(), entry.getValue());
}
endJson(sb);
sb.append(",");
}
}
```### // ----------------------------------------------------------------------------------------------------
// PRINT UTILS
// ----------------------------------------------------------------------------------------------------
@Deprecated
public static String normalize(String s)
```java
// ----------------------------------------------------------------------------------------------------
// PRINT UTILS
// ----------------------------------------------------------------------------------------------------
@Deprecated
public static String normalize(String s) {
return Character.toString(s.charAt(0)).toUpperCase() + s.substring(1).toLowerCase();
}The normalize method is a static method in the JsonUtils class. It is used to normalize a given string based on the following steps:
- Convert the first character of the input string to uppercase.
- Convert all subsequent characters in the input string to lowercase.
public static String normalize(String s)-
s- The string to be normalized.
- The normalized string.
- Convert the first character of the input string to uppercase using the
toUpperCasemethod of theCharacterclass. This can be achieved by callingCharacter.toString(s.charAt(0)).toUpperCase(). - Convert all subsequent characters in the input string to lowercase using the
toLowerCasemethod of theStringclass. This can be achieved by callings.substring(1).toLowerCase(). - Concatenate the uppercase first character and the lowercase subsequent characters using the
+operator. - Return the normalized string.
-
Note: This method is marked as
@Deprecated, indicating that it is no longer recommended to be used. Consider using an alternative method or approach.
String input = "hELlo";
String normalized = JsonUtils.normalize(input);
System.out.println(normalized); // Output: HelloThe normalize method, defined in the JsonUtils class in the io.nats.client.support package, is used to normalize a given string. The method takes a single argument, s, which is a string.
The method begins by retrieving the first character of the string using the charAt method. It then converts this character to uppercase using the toUpperCase method.
Next, the method extracts a substring from the original string starting from the second character using the substring method. This substring is then converted to lowercase using the toLowerCase method.
Finally, the method concatenates the uppercase first character with the lowercase substring and returns the resulting normalized string.
Note: This method has been marked as deprecated, which means it is no longer recommended to be used in new code.

public static String objectString(String name, Object o)
@Deprecated
public static String objectString(String name, Object o) {
if (o == null) {
return name + "=null";
}
return o.toString();
}This method is defined in the class io.nats.client.support.JsonUtils. It is a deprecated method that is used to convert an object into a string representation.
@Deprecated
public static String objectString(String name, Object o)-
name(type: String): The name of the object. -
o(type: Object): The object to be converted into a string representation.
- The method returns a string representation of the object.
if (o == null) {
return name + "=null";
}
return o.toString();The method first checks if the object o is null. If it is, it returns a string in the format "name=null", where name is the name of the object passed to the method.
If the object is not null, it calls the toString() method on the object and returns the resulting string representation.
This method is marked as @Deprecated, which means it is no longer recommended for use and may be removed in future versions. It is advised to use an alternative method or approach.
The objectString method, defined in the JsonUtils class in the io.nats.client.support package, takes in a name and an object as parameters. It returns a string representation of the object.
If the object is null, the method returns a string in the format name=null. Otherwise, it returns the result of calling the toString() method on the object.
Please note that this method is deprecated, which means it should not be used in new code and may be removed in future versions.

// ----------------------------------------------------------------------------------------------------
// SAFE NUMBER PARSING HELPERS // ---------------------------------------------------------------------------------------------------- public static Long safeParseLong(String s)
// ----------------------------------------------------------------------------------------------------
// SAFE NUMBER PARSING HELPERS
// ----------------------------------------------------------------------------------------------------
public static Long safeParseLong(String s) {
try {
return Long.parseLong(s);
} catch (Exception e1) {
try {
return Long.parseUnsignedLong(s);
} catch (Exception e2) {
return null;
}
}
}-
The method takes a
Stringsas input. -
First, it tries to parse the input
sas aLongusingLong.parseLong(s). -
If the parsing is successful and no exception is thrown, the method returns the parsed
Longvalue. -
If an exception occurs while parsing the input
sas aLong, the method catches the exception and moves to the next step. -
In the catch block, the method tries to parse the input
sas an unsignedLongusingLong.parseUnsignedLong(s). -
If the parsing is successful and no exception is thrown, the method returns the parsed unsigned
Longvalue. -
If an exception occurs while parsing the input
sas an unsignedLong, the method catches the exception and moves to the next step. -
In the second catch block, the method returns
null, indicating that the inputscannot be parsed as either aLongor an unsignedLong.
This method is designed to handle safe parsing of strings into Long values, providing fallbacks if the first parsing attempt fails.
The safeParseLong method is a helper method defined in the io.nats.client.support.JsonUtils class. It is used to safely parse a string into a Long value without throwing an exception.
The method first attempts to parse the string using the Long.parseLong() method. If this throws an exception, indicating that the string cannot be parsed as a signed long value, the method then tries to parse the string using the Long.parseUnsignedLong() method. If this also throws an exception, the method returns null, indicating that the string could not be parsed as a long value.
This method is particularly useful when dealing with JSON data, where numeric values are often represented as strings. By using the safeParseLong method, software engineers can avoid potential exceptions and handle parsing errors more gracefully.

public static String removeObject(String json, String objectName)
@Deprecated
public static String removeObject(String json, String objectName) {
int[] indexes = getBracketIndexes(objectName, json, '{', '}', 0);
if (indexes != null) {
// remove the entire object replacing it with a dummy field b/c getBracketIndexes doesn't consider
// if there is or isn't another object after it, so I don't have to worry about it being/not being the last object
json = json.substring(0, indexes[0]) + "\"rmvd" + objectName.hashCode() + "\":\"\"" + json.substring(indexes[1] + 1);
}
return json;
}
```### private static List<String> toList(String arrayString)
```java
private static List<String> toList(String arrayString) {
List<String> list = new ArrayList<>();
String[] raw = arrayString.split(",");
for (String s : raw) {
String cleaned = s.trim().replace("\"", "");
if (cleaned.length() > 0) {
list.add(jsonDecode(cleaned));
}
}
return list;
}
```### @Deprecated
public static String readStringMayHaveQuotes(String json, String field, String dflt)
```java
@Deprecated
public static String readStringMayHaveQuotes(String json, String field, String dflt) {
String jfield = "\"" + field + "\"";
int at = json.indexOf(jfield);
if (at != -1) {
at = json.indexOf('"', at + jfield.length());
StringBuilder sb = new StringBuilder();
while (true) {
char c = json.charAt(++at);
if (c == '\\') {
char c2 = json.charAt(++at);
if (c2 == '"') {
sb.append('"');
} else {
sb.append(c);
sb.append(c2);
}
} else if (c == '"') {
break;
} else {
sb.append(c);
}
}
return jsonDecode(sb.toString());
}
return dflt;
}
```### @Deprecated
public static byte[] readBase64(String json, Pattern pattern)
```java
@Deprecated
public static byte[] readBase64(String json, Pattern pattern) {
Matcher m = pattern.matcher(json);
String b64 = m.find() ? m.group(1) : null;
return b64 == null ? null : Base64.getDecoder().decode(b64);
}The readBase64 method is defined in the io.nats.client.support.JsonUtils class. It is used to decode a Base64 encoded string from a JSON string using a provided pattern.
-
json(String): The JSON string from which to extract the Base64 encoded string. -
pattern(Pattern): A regular expression pattern used to match the Base64 encoded string within the JSON.
- If a match is found, the method returns the decoded byte array.
- If no match is found, the method returns
null.
This method is marked as deprecated, indicating that it is no longer recommended to use. It is recommended to check for an alternative method or approach for achieving the desired functionality.
- The method starts by creating a Matcher object using the provided pattern and the input JSON string.
- It then attempts to find a match within the JSON string using the Matcher's
findmethod. - If a match is found, the method extracts the matched substring (Base64 encoded string) using the Matcher's
groupmethod with a group index of 1. - If no match is found (or if the extracted Base64 encoded string is null), the method returns
null. - If a Base64 encoded string is extracted, the method uses the
Base64.getDecoder().decodemethod to decode the string into a byte array. - The decoded byte array is then returned by the method.
The deprecation of this method suggests that there might be a better or more efficient way to achieve the same result. It is recommended to consult the documentation or seek further guidance to determine the replacement or alternative method for the deprecated functionality.
The readBase64 method in the JsonUtils class is used to read and decode a Base64 string from a JSON string. It takes two parameters: json - the JSON string, and pattern - a regex pattern used to extract the Base64 string from the JSON.
First, it uses the provided regex pattern to find a match in the JSON string. If a match is found, the Base64 string is extracted from the captured group. Then, it checks if the extracted Base64 string is null. If it is null, indicating no match was found, the method returns null. Otherwise, the method uses the Base64.getDecoder() method to decode the Base64 string into a byte array, which it returns.
The @Deprecated annotation indicates that this method is no longer recommended to be used and may be removed in future versions.

public static Boolean readBoolean(String json, Pattern pattern, Boolean dflt)
@Deprecated
public static Boolean readBoolean(String json, Pattern pattern, Boolean dflt) {
Matcher m = pattern.matcher(json);
if (m.find()) {
return Boolean.parseBoolean(m.group(1));
}
return dflt;
}The readBoolean method is a static method defined in the io.nats.client.support.JsonUtils class. It is used to read a boolean value from a JSON string based on a provided pattern.
@Deprecated
public static Boolean readBoolean(String json, Pattern pattern, Boolean dflt)-
json(String): The JSON string from which to read the boolean value. -
pattern(Pattern): The regular expression pattern used to match the boolean value in the JSON string. -
dflt(Boolean): The default boolean value returned if no match is found in the JSON string.
-
Boolean: The boolean value read from the JSON string, or the default value if no match is found.
- Create a
Matcherobject by applying the provided pattern to the JSON string. - If the matcher finds a match in the JSON string:
- Get the matched substring group (group 1).
- Parse the matched substring as a boolean value using the
Boolean.parseBooleanmethod. - Return the parsed boolean value.
- If no match is found in the JSON string, return the default boolean value provided.
Note: This method is marked as @Deprecated, so it is recommended to use alternative methods for reading boolean values from JSON.
The readBoolean method in the JsonUtils class, defined in the io.nats.client.support package, is used to read a boolean value from a given JSON string.
The method takes three parameters:
-
json- The JSON string from which the boolean value is to be extracted. -
pattern- A regular expression pattern that defines the format of the boolean value in the JSON string. -
dflt- A default boolean value to be returned if the pattern is not matched in the JSON string.
The method uses the Pattern class to create a matcher object and applies it to the JSON string. If the pattern is found in the JSON string, then the method extracts the boolean value and returns it. If the pattern is not found, the method returns the default value.
Note that this method is marked as @Deprecated, which means it is no longer recommended for use and may be removed in future versions.

public static void readInt(String json, Pattern pattern, IntConsumer c)
@Deprecated
public static void readInt(String json, Pattern pattern, IntConsumer c) {
Matcher m = pattern.matcher(json);
if (m.find()) {
c.accept(Integer.parseInt(m.group(1)));
}
}The readInt method in JsonUtils class, defined in the io.nats.client.support package, is used to extract an integer value from a JSON string based on a given regular expression pattern.
Here is a step-by-step description of what the readInt method does:
- The method is marked with the
@Deprecatedannotation, which means that it is considered outdated and should not be used in new code. However, it is still functional and can be used for backward compatibility. - The method takes three parameters:
-
json- aStringrepresenting the JSON object from which the integer value needs to be extracted. -
pattern- aPatternobject representing the regular expression pattern to be matched against the JSON string. -
c- anIntConsumerfunctional interface implementation that will consume the extracted integer value.
-
- Inside the method, a
Matcherobject is created by calling thematchermethod on thepatternobject, passing thejsonstring as the input to be matched. - The
findmethod is called on theMatcherobject to search for the first occurrence of the pattern in thejsonstring. If a match is found, the next steps are executed; otherwise, the method returns without performing any further action. - The
group(1)method is called on theMatcherobject to extract the matched portion of thejsonstring corresponding to the first capturing group in the pattern. This assumes that the pattern contains a capturing group (i.e., parentheses) around the integer value. - The extracted string is then converted to an integer using the
parseIntmethod of theIntegerclass. - Finally, the extracted integer value is passed to the
acceptmethod of theIntConsumerfunctional interface implementationc. This allows the consumer to perform any necessary actions with the extracted value.
Note: The method does not return any result, as the extracted integer value is passed to the IntConsumer consumer.

public static void readLong(String json, Pattern pattern, LongConsumer c)
@Deprecated
public static void readLong(String json, Pattern pattern, LongConsumer c) {
Matcher m = pattern.matcher(json);
if (m.find()) {
Long l = safeParseLong(m.group(1));
if (l != null) {
c.accept(l);
}
}
}This method is defined in the class io.nats.client.support.JsonUtils and is used to extract a Long value from a JSON string based on a given pattern. Here is a step-by-step description of what the method does:
-
Annotation: The method is annotated with
@Deprecated, which indicates that it is no longer recommended for use. It is likely that this method has been replaced by a newer or better alternative. -
Parameters: The method takes three parameters:
json(a string),pattern(aPatternobject), andc(aLongConsumerinterface). -
Pattern Matching: The method creates a
Matcherobject by invoking thematcher()method on thepatternobject and passing thejsonstring as an argument. TheMatcherobject is used for pattern matching on the input JSON string. -
Pattern Matching Result: The method checks if the
Matcherobject finds a match in the input JSON string by invoking thefind()method. If a match is found, the method proceeds to the next step; otherwise, it exits and does nothing. -
Extract Number: If a match is found, the method uses the
group()method of theMatcherobject to extract the matched substring. In this case, it extracts the substring captured in the first group (specified by the parentheses in the pattern). This substring should represent a numerical value that can be parsed as aLongtype. -
Parse Long: The method calls the
safeParseLong()method (not shown in the provided code) to parse the extracted substring as aLongvalue. The result is stored in aLongvariablel. ThesafeParseLong()method likely handles cases where the parsing fails and returnsnull. -
Consuming Long: If the parsed
Longvaluelis notnull, the method invokes theaccept()method of theLongConsumerinterface, passing thelas an argument. This allows the caller of the method to consume the extractedLongvalue.
That's the step-by-step description of the readLong method. It is important to note that the implementation of the safeParseLong() method and the actual usage of the readLong() method in your code may influence the behavior and purpose of this method further.
The readLong method is a deprecated method defined in the JsonUtils class from the io.nats.client.support package.
It takes three parameters:
-
json- a string representing a JSON object or JSON data -
pattern- a regular expression pattern to search for a specific value in the JSON string -
c- aLongConsumerfunctional interface that allows the method to accept and process aLongvalue
The method uses the provided regular expression pattern to create a Matcher object and applies it to the json string. If a match is found, it extracts the matched value and attempts to parse it into a Long object using the safeParseLong helper method.
If the parsing is successful and a valid Long object is obtained, the method invokes the accept method of the LongConsumer interface with the parsed Long value as the argument. This allows the caller to provide custom logic to handle the extracted Long value.
Note that the method is marked as deprecated, which means it is no longer recommended to be used in new code and may be removed in future versions of the library.

public static void readNanos(String json, Pattern pattern, Consumer c)
@Deprecated
public static void readNanos(String json, Pattern pattern, Consumer<Duration> c) {
Matcher m = pattern.matcher(json);
if (m.find()) {
c.accept(Duration.ofNanos(Long.parseLong(m.group(1))));
}
}The method readNanos in the class io.nats.client.support.JsonUtils is used to extract a Duration value from a JSON string, using a specified regex pattern. This method performs the following steps:
-
The method is marked as
@Deprecated, indicating that it is no longer recommended to use this method. Users should consider using an alternative method instead. -
The method takes three parameters:
-
json(String): The JSON string from which the Duration value needs to be extracted. -
pattern(Pattern): The regular expression pattern used to match and extract the Duration value from the JSON string. -
c(Consumer): A consumer function that accepts aDurationobject. This function will be called with the extracted Duration value.
-
-
Inside the method, it creates a
Matcherobject by applying the regex pattern to the provided JSON string.Matcher m = pattern.matcher(json); -
It then checks if the Matcher object finds a match in the JSON string.
if (m.find()) { ... } -
If a match is found, it uses the
groupmethod of the Matcher object to retrieve the captured group with index 1 (assuming the pattern has at least one capturing group).Long.parseLong(m.group(1)) -
It then creates a
Durationobject by calling theofNanosmethod and passing the parsed long value. ThisDurationobject represents the extracted Duration value in nanoseconds.Duration.ofNanos(Long.parseLong(m.group(1))) -
Finally, it calls the
acceptmethod of theConsumerobject (c) and passes the createdDurationobject as the argument. This allows users of the method to process the extracted Duration value according to their needs.c.accept(Duration.ofNanos(Long.parseLong(m.group(1))));
This method facilitates the extraction of a Duration value from a JSON string using a provided regex pattern, and provides a way to consume and process the extracted value using a callback function.
The readNanos method in the io.nats.client.support.JsonUtils class is used to parse a JSON string and extract a duration in nanoseconds based on a given regular expression pattern. The method takes three parameters: json (the JSON string to parse), pattern (the regular expression pattern to match against the JSON string), and c (a consumer function that accepts a Duration object).
The method firstly creates a Matcher object by applying the pattern to the JSON string. If a match is found, the method extracts the matched group (assumed to be a number representing nanoseconds) and parses it into a long value. Finally, the method constructs a Duration object using the parsed value and passes it to the consumer function c for further processing.
Please note that this method is marked as deprecated, suggesting that it may be outdated or should be used with caution. It is recommended to refer to the API documentation or consult the code maintainers for more information on the deprecation and possible alternatives.

public static <T> boolean listEquals(List<T> l1, List<T> l2) {
if (l1 == null) {
return l2 == null;
}
if (l2 == null) {
return false;
}
return l1.equals(l2);
}The listEquals method is defined in the io.nats.client.support.JsonUtils class. It is a public static method that takes two generic List objects, l1 and l2, as parameters. It returns a boolean value indicating whether the two lists are equal.
- If the
l1parameter is null, proceed to step 2. - If
l1is null andl2is also null, return true. This means that if both lists are null, then they are considered equal. Return true and end the method execution.
- If the
l1parameter is not null and thel2parameter is null, proceed to step 3. - If
l1is not null andl2is null, return false. This means that if one list is null and the other is not, they are not considered equal. Return false and end the method execution.
- If both
l1andl2are not null, compare their contents for equality using theequalsmethod of theListclass. - If the contents of
l1are equal to the contents ofl2, return true. This means that if the two lists have the same elements in the same order, they are considered equal. - If the contents of
l1are not equal to the contents ofl2, return false. This means that if the two lists have different elements or the elements are in a different order, they are not considered equal.
Note: The equals method being used is the one defined by the List interface, which compares the elements of the lists for equality. The behavior of this method may depend on the implementation of the concrete List class being used.
End of method execution.
The method listEquals in the class JsonUtils compares two lists (l1 and l2) to check if they are equal. It follows the following logic:
- If
l1isnull, it returnstrueif and only ifl2is alsonull. - If
l2isnull, it returnsfalse. - Otherwise, it uses the
equalsmethod to compare the two lists and returns the result.
Overall, this method helps to determine whether two lists are equal by considering both their contents and order.

public static boolean mapEquals(Map<String, String> map1, Map<String, String> map2) {
if (map1 == null) {
return map2 == null;
}
if (map2 == null || map1.size() != map2.size()) {
return false;
}
for (String key : map1.keySet()) {
if (!Objects.equals(map1.get(key), map2.get(key))) {
return false;
}
}
return true;
}The mapEquals method in the JsonUtils class is used to compare two Map objects of type Map<String, String> and determine if they are equal. Here's a step-by-step description of what the method does:
- Check if
map1isnull. If it is, returntrueif and only ifmap2is alsonull. - Check if
map2isnullor if the size ofmap1is different from the size ofmap2. If either of these conditions is true, returnfalse. - Iterate over each key in
map1using a for-each loop. - For each key, compare the corresponding values in
map1andmap2using theObjects.equalsmethod. If the values are not equal, returnfalse. - If all key-value pairs in
map1are equal to their corresponding pairs inmap2, returntrue.
In summary, the mapEquals method checks if two Map objects are equal by comparing their keys and values. It returns true if both maps are null, have the same size, and contain the same key-value pairs; otherwise, it returns false.
The mapEquals method in the JsonUtils class is a static method that compares two Map<String, String> objects.
This method checks if either of the maps is null and returns true only if both are null. If only one map is null or if both maps have different sizes, it returns false.
Next, the method iterates over the keys in map1 and checks if the values of each key in map1 and map2 are equal using the Objects.equals method. If any key-value pair is not equal, it returns false.
If all key-value pairs are equal, it returns true, indicating that both maps are equal.

HttpRequest
The HttpRequest class encapsulates an HttpRequest. It is used to support older JVMs where the Java 11 java.net.http.HttpRequest class is not available.
public HttpRequest method(String method) {
if (null == method) {
throw new IllegalArgumentException("HttpRequest method must be non-null");
}
this.method = method.trim().toUpperCase();
return this;
}The method(String method) method in the io.nats.client.support.HttpRequest class is used to set the HTTP request method.
Here is a step-by-step description of what this method does based on its body:
- Check if the
methodparameter is null. - If the method is null, throw an
IllegalArgumentExceptionwith the message "HttpRequest method must be non-null". - Trim the leading and trailing spaces of the
methodparameter. - Convert the
methodparameter to uppercase using thetoUpperCase()method. - Set the value of the
methodinstance variable in the class to the trimmed and uppercasemethodparameter. - Return the current instance of the
HttpRequestobject.
In summary, this method ensures that the HTTP request method is set correctly by checking for null values, trimming leading and trailing spaces, converting the method to uppercase, and setting it as the value of the method instance variable in the class.
The method method in the HttpRequest class is responsible for setting the HTTP method for the request.
It takes a String parameter called method, which represents the desired HTTP method (e.g., GET, POST, etc.).
If the method parameter is null, it throws an IllegalArgumentException with the message "HttpRequest method must be non-null".
Otherwise, it trims and converts the method parameter to uppercase and assigns it to the this.method variable. Finally, it returns the modified HttpRequest object.

public HttpRequest uri(String uri) {
if (null == uri) {
throw new IllegalArgumentException("HttpRequest uri must be non-null");
}
this.uri = uri;
return this;
}The uri method in the HttpRequest class is used to set the URI (Uniform Resource Identifier) for the HTTP request. The URI is a string that identifies a resource on the internet.
Here is a step-by-step description of what this method does based on its BODY:
-
The method takes a single parameter,
uri, which represents the URI for the HTTP request. -
It checks if the
uriparameter isnull. If it isnull, anIllegalArgumentExceptionis thrown with the message "HttpRequest uri must be non-null". -
If the
uriparameter is notnull, it assigns the value ofurito thethis.urifield of theHttpRequestobject. -
Finally, it returns the current
HttpRequestobject. This is done to support method chaining, allowing for a fluent API where multiple method calls can be chained together in a single line.
Overall, this method ensures that a non-null URI is provided for the HTTP request and stores it in the HttpRequest object for later use.
The uri method in the io.nats.client.support.HttpRequest class is used to set the URI of the HTTP request. It takes a string parameter uri and validates that it is not null. If the uri parameter is null, it throws an IllegalArgumentException. The method then sets the uri field of the HttpRequest object and returns the updated object.

public HttpRequest version(String version) {
if (null == version) {
throw new IllegalArgumentException("HttpRequest version must be non-null");
}
this.version = version;
return this;
}The version method in the HttpRequest class is used to set the version of the HTTP request. It takes a String parameter version and returns an instance of HttpRequest.
The method has the following steps:
-
Check if the
versionparameter isnull. If it isnull, throw anIllegalArgumentExceptionwith the message "HttpRequest version must be non-null". -
Set the
versionfield of theHttpRequestinstance to the value of theversionparameter. -
Return the modified
HttpRequestinstance.
This method is useful when you want to set the version of the HTTP request being made using the HttpRequest class. It ensures that the version is not null and throws an exception if it is, preventing null pointer exceptions or invalid values.
The version method in the io.nats.client.support.HttpRequest class is used to set the version of the HTTP request. It takes a String parameter version and assigns it to the this.version field of the HttpRequest object.
If the version parameter is null, an IllegalArgumentException is thrown to indicate that the HTTP request version must be non-null.
The method then returns the updated HttpRequest object, allowing for method chaining if desired.

JsonValueUtils
The JsonValueUtils class is an abstract class that provides internal helper methods for dealing with JSON values.
public static Map<String, String> readStringStringMap(JsonValue jv, String key) {
JsonValue o = readObject(jv, key);
if (o.type == Type.MAP && o.map.size() > 0) {
Map<String, String> temp = new HashMap<>();
for (String k : o.map.keySet()) {
String value = readString(o, k);
if (value != null) {
temp.put(k, value);
}
}
return temp.isEmpty() ? null : temp;
}
return null;
}This method is defined in the class io.nats.client.support.JsonValueUtils. It takes in two parameters: jv of type JsonValue and key of type String. The method returns a Map<String, String>, which is a mapping of string keys to string values.
public static Map<String, String> readStringStringMap(JsonValue jv, String key)-
jv: AJsonValueobject that represents the body of the JSON response. -
key: AStringparameter that represents the key to be used for retrieving a specific value from the JSON response.
- Retrieve the object specified by the provided
keyfrom thejvJSON response using thereadObjectmethod. - Check if the retrieved object
ois of typeMAPand has a size greater than 0. - If the above condition is true, create a new
HashMapobject calledtempto store the mapping of keys to values. - Iterate over each key in the
o.mapset:- Retrieve the string value associated with the current key using the
readStringmethod from theoobject. - If the retrieved value is not null, add the key-value pair to the
tempmap using theputmethod.
- Retrieve the string value associated with the current key using the
- Check if the
tempmap is empty. If it is, return null; otherwise, return thetempmap. - If the condition in step 2 is false, return null.
The readStringStringMap method is a static method defined in the class io.nats.client.support.JsonValueUtils.
This method takes in two parameters: JsonValue jv and String key.
The purpose of this method is to read a JSON object (jv) and retrieve a nested JSON map under a specific key (key).
If the nested JSON object exists and is not empty, the method creates a new HashMap<String, String> called temp. It loops through each key in the nested JSON map and retrieves the corresponding value as a string using the readString method.
If the value is not null, it adds the key-value pair to the temp map.
Finally, the method checks if the temp map is empty. If it is, it returns null; otherwise, it returns the temp map.

public static int readInteger(JsonValue jsonValue, String key, int dflt) {
return read(jsonValue, key, v -> {
if (v != null) {
Integer i = getInteger(v);
if (i != null) {
return i;
}
}
return dflt;
});
}The method readInteger is defined in the class io.nats.client.support.JsonValueUtils. It takes three parameters: jsonValue, key, and dflt.
The purpose of this method is to read an integer value from a JsonValue object based on a given key. If the key is not found or the value is not an integer, a default value (dflt) is returned.
Here is a step-by-step description of what the method is doing:
-
It calls the
readmethod passing thejsonValue,key, and a lambda function as arguments. The lambda function takes aJsonValueparametervand returns an integer value. -
In the lambda function, it checks if the
vis not null. If it is not null, it proceeds to the next step. -
Inside the if condition, it calls the
getIntegermethod passing thevas an argument. ThegetIntegermethod returns anIntegerobject representing the value ofvif it can be converted to an integer, otherwise, it returns null. -
If the
i(Integer) object is not null (vcan be converted to an integer), it returnsi(the converted integer). -
If the
vis null or cannot be converted to an integer, it returns the default valuedflt.

public static long readLong(JsonValue jsonValue, String key, long dflt) {
return read(jsonValue, key, v -> {
if (v != null) {
Long l = getLong(v);
if (l != null) {
return l;
}
}
return dflt;
});
}The method readLong defined in class io.nats.client.support.JsonValueUtils is used to read a long value from a JsonValue object by specifying a key. Below is a step-by-step description of how the method works:
-
The method
readLongtakes three parameters:jsonValueof typeJsonValue,keyof typeString, anddfltof typelong.-
jsonValueis the inputJsonValueobject from which the value is to be read. -
keyis the key to identify the value within thejsonValueobject. -
dfltis the default value to be returned if the requested key is not found or the value is not along.
-
-
The method utilizes the
readmethod of the same class to perform the actual read operation.- The
readmethod takes aJsonValueobject, a key, and a callback function as parameters. - The callback function is implemented internally and evaluates the value associated with the specified key.
- The
-
The callback function checks if the value associated with the key is not null:
- If the value is not null, it tries to convert it to a
Longusing thegetLongmethod. - The
getLongmethod is also implemented internally and attempts to parse the value as along. - If the conversion is successful, the parsed
Longvalue is returned. - If the value cannot be parsed as a
long, the method returns the default valuedflt.
- If the value is not null, it tries to convert it to a
-
If the value associated with the key is null or cannot be parsed as a
long, the method returns the default valuedflt.
In summary, the readLong method reads a long value from a JsonValue object by specifying a key. If the specified key is found and the associated value can be parsed as a long, that value is returned. Otherwise, the default value dflt is returned.
The readLong method in the io.nats.client.support.JsonValueUtils class is used to read a long value from a JsonValue object using a specified key.
Here's what the method does:
-
It takes in three parameters: a
JsonValueobject, aStringkey, and a default value (dflt) to be returned if the value is not found or cannot be parsed as along. -
The method calls the
readmethod passing theJsonValue, key, and a lambda expression. -
Within the lambda expression, it first checks if the
JsonValueis not null and if it can be parsed as aLongtype. -
If the value is a valid
Long, it returns the parsedlongvalue. -
If any of the above conditions are not met, it returns the default value specified (
dflt).
In summary, the readLong method reads a long value from a JsonValue object using a specified key and returns either the parsed value or a default value if the value is not found or cannot be parsed.

public static <T> List<T> listOf(JsonValue v, Function<JsonValue, T> provider) {
List<T> list = new ArrayList<>();
if (v != null && v.array != null) {
for (JsonValue jv : v.array) {
T t = provider.apply(jv);
if (t != null) {
list.add(t);
}
}
}
return list;
}This method is defined in the class io.nats.client.support.JsonValueUtils and returns a list of objects of type T. The purpose of this method is to extract objects from a JsonValue object and populate a list using a provided function.
-
v(type:JsonValue): The inputJsonValueobject from which objects will be extracted. -
provider(type:Function<JsonValue, T>): A function that takes aJsonValueobject as input and produces an object of typeT.
- A list of objects of type
T.
- Create an empty
ArrayListcalledlistto store the extracted objects. - Check if the input
JsonValueobjectvis not null and itsarrayproperty is not null. - If the above condition is satisfied, iterate over each
JsonValueobjectjvin thearrayproperty ofv. - Using the provided function
provider, obtain an object of typeTby applying it on the currentjv. - Check if the obtained object
tis not null. - If the above condition is satisfied, add
tto thelist. - After looping through all the
JsonValueobjects in the array, return the populatedlist.
Note: This method is used to efficiently extract objects from a JsonValue array, and skip any null objects in the process. The provided function allows customization on how the JsonValue objects should be transformed into objects of type T.
The listOf method in the JsonValueUtils class is a utility method that takes in a JsonValue object and a Function that converts a JsonValue to a desired type T. It returns a List containing the converted JsonValue objects.
Here is a breakdown of what the method does:
- It initializes an empty
ArrayListcalledlist. - It checks if the input
JsonValueobject (v) is not null and if itsarrayattribute is not null. - If both conditions are met, it iterates over each
JsonValue(jv) in thearrayattribute of the inputJsonValueobject. - It applies the provided
providerfunction to eachJsonValueand returns the resulting value of typeT. - If the returned value (
t) is not null, it adds it to thelist. - Finally, it returns the populated
listcontaining the convertedJsonValueobjects.
This method is useful for converting an array of JsonValue objects into a list of objects of a specific type.

public static List<String> readStringListIgnoreEmpty(JsonValue jsonValue, String key) {
return read(jsonValue, key, v -> listOf(v, jv -> {
if (jv.string != null) {
String s = jv.string.trim();
if (s.length() > 0) {
return s;
}
}
return null;
}));
}The readStringListIgnoreEmpty method is a public static method defined in the io.nats.client.support.JsonValueUtils class. It takes two parameters: jsonValue of type JsonValue and key of type String. It returns a List<String>.
Here is a step-by-step description of what this method does:
-
It calls the
readmethod, passing in thejsonValue,key, and a lambda expression as arguments. The lambda expression is responsible for transforming the input value to a list of strings. -
Inside the lambda expression, it uses the
listOfmethod to create a list containing the input value (v) and another lambda expression. -
The nested lambda expression checks if the input value has a non-null string value.
-
If the string value is not null, it trims the string and checks if its length is greater than zero.
-
If the trimmed string has a length greater than zero, it returns the string as a valid value for the list.
-
If the trimmed string has a length of zero (i.e., it was empty after being trimmed), it returns
null. -
If the string value is null or the trimmed string has a length of zero, it returns
null. -
The
readmethod finally returns the list of valid string values, excluding any empty strings. -
The
readStringListIgnoreEmptymethod returns the list of valid string values obtained from thereadmethod.
Note: The provided code snippet is missing the definition of the read and listOf methods, so the exact behavior of those methods is not clear from the given information.
The readStringListIgnoreEmpty method, defined in the io.nats.client.support.JsonValueUtils class, is used to read a list of strings from a JsonValue object, ignoring any empty or whitespace-only strings.
The method takes two parameters: jsonValue, which is the JsonValue object to read from, and key, which is the key to retrieve the list of strings from within the JsonValue.
Inside the method, the read method is called, passing in the jsonValue, key, and a lambda function that specifies how to transform each element of the list.
The lambda function checks if each element is a non-null string and trims it to remove any leading or trailing whitespace. If the resulting string has a length greater than 0, it is returned; otherwise, null is returned.
The read method returns a list of transformed elements, and that list is returned from the readStringListIgnoreEmpty method.

public static List<Duration> readNanosList(JsonValue jsonValue, String key, boolean nullIfEmpty) {
List<Duration> list = read(jsonValue, key, v -> listOf(v, vv -> {
Long l = getLong(vv);
return l == null ? null : Duration.ofNanos(l);
}));
return list.size() == 0 && nullIfEmpty ? null : list;
}The method readNanosList in the class io.nats.client.support.JsonValueUtils is responsible for reading a list of Duration objects from a JsonValue based on a specified key. The method takes three parameters: jsonValue, key, and nullIfEmpty.
Here is a step-by-step description of what the method does:
- The method initializes an empty
List<Duration>object calledlist. - It calls the
readmethod of the JsonValueUtils class, passing in thejsonValue,key, and a lambda expression as parameters. - The lambda expression defines a conversion function that takes a
JsonValueparametervand returns a list ofDurationobjects. This conversion function is responsible for extracting aLongvalue from theJsonValueand converting it into aDurationobject. - Inside the conversion function, the
listOfmethod is called, passing in theJsonValueparametervand another lambda expression as parameters. - The nested lambda expression defines a conversion function that takes a
JsonValueparametervvand returns aDurationobject. This conversion function extracts aLongvalue from theJsonValueand checks if it isnull. If theLongvalue isnull, the conversion function returnsnull. Otherwise, it creates aDurationobject using theDuration.ofNanosmethod and returns it. - The
readmethod returns aList<Duration>, which is assigned to thelistvariable. - The method checks if the size of the
listis 0 andnullIfEmptyistrue. If both conditions are true, the method returnsnull. Otherwise, it returns thelist.
The readNanosList method is a utility method in the JsonValueUtils class that is used to read a list of Duration values from a JSON object.
The method takes three parameters:
-
jsonValue: The input JSON object from which to read the list. -
key: The key in the JSON object that corresponds to the list. -
nullIfEmpty: A boolean flag indicating whether to returnnullif the list is empty.
Inside the method, it uses another utility method called read to read the list of JsonValue objects from the input JSON object. Then, it performs a conversion on each element of the list using a lambda expression.
The lambda expression checks if the value is a Long, and if so, converts it to a Duration object representing the number of nanoseconds. If the value is not a Long, it returns null.
Finally, the method checks if the resulting list is empty and nullIfEmpty is true, it returns null. Otherwise, it returns the list of Duration objects.
In summary, the readNanosList method reads a list of durations in nanoseconds from a JSON object and returns it as a List<Duration>. If the list is empty and the nullIfEmpty parameter is true, it returns null.

public static JsonValue instance(Collection list)
@SuppressWarnings("rawtypes")
public static JsonValue instance(Collection list) {
JsonValue v = new JsonValue(new ArrayList<>());
for (Object o : list) {
v.array.add(toJsonValue(o));
}
return v;
}The instance method in class io.nats.client.support.JsonValueUtils takes a Collection as a parameter and returns a JsonValue instance. Here is a step-by-step description of what the method does:
- Creates a new
JsonValueinstance:
JsonValue v = new JsonValue(new ArrayList<>());
- This line creates a new
JsonValueobject and initializes itsarrayfield with an emptyArrayList.
- Iterates over the elements in the input
Collection:
for (Object o : list) {
v.array.add(toJsonValue(o));
}
- This
forloop iterates over each element of thelistparameter. - For each element, the method calls the
toJsonValuemethod, passing in the element as a parameter. - The result of
toJsonValueis then added to thearrayfield of theJsonValueobject. - This loop continues until all elements in the
listhave been processed.
- Returns the
JsonValueinstance:
return v;
- After the loop completes, the method returns the
JsonValueobject that was created at the beginning.
Note: The method uses @SuppressWarnings("rawtypes") annotation to suppress warnings related to the use of raw types in the method signature.
The method instance in the JsonValueUtils class is responsible for creating a JsonValue object based on a given collection of elements.
It takes a collection as input and creates a new instance of JsonValue with an empty ArrayList. Then, it iterates through each element in the collection, converts it to a JSON value using the toJsonValue method, and adds it to the array in the JsonValue object.
Finally, the method returns the created JsonValue object.

public static JsonValue instance(Map map)
@SuppressWarnings("rawtypes")
public static JsonValue instance(Map map) {
JsonValue v = new JsonValue(new HashMap<>());
for (Object key : map.keySet()) {
v.map.put(key.toString(), toJsonValue(map.get(key)));
}
return v;
}This method is defined in the io.nats.client.support.JsonValueUtils class. It returns a JsonValue object based on the provided Map object.
@SuppressWarnings("rawtypes")
public static JsonValue instance(Map map) {
JsonValue v = new JsonValue(new HashMap<>());
for (Object key : map.keySet()) {
v.map.put(key.toString(), toJsonValue(map.get(key)));
}
return v;
}- Create a new instance of
JsonValueusing an emptyHashMapobject:JsonValue v = new JsonValue(new HashMap<>());
- Iterate over each key in the provided
Mapobject:for (Object key : map.keySet()) {
- Convert the value of the current key in the
Mapto aJsonValueobject using thetoJsonValuemethod (not shown in the provided code snippet):v.map.put(key.toString(), toJsonValue(map.get(key)));
- Add the converted
JsonValueobject to themapfield of theJsonValueinstance, using the key from theMapas the key in themapfield:v.map.put(key.toString(), toJsonValue(map.get(key)));
- Repeat steps 3 and 4 for each key-value pair in the
Map. - Return the created
JsonValueinstance:return v;
The method instance from the class io.nats.client.support.JsonValueUtils takes a Map as a parameter and returns a JsonValue. It creates a new JsonValue object with an empty HashMap.
It then iterates through each key in the input map. For each key, it retrieves the corresponding value from the map using map.get(key) and converts it into a JsonValue using the toJsonValue method. It then puts the key-value pair into the map of the newly created JsonValue object.
Finally, it returns the JsonValue object with the populated map.

public static JsonValue toJsonValue(Object o) {
if (o == null) {
return JsonValue.NULL;
}
if (o instanceof JsonValue) {
return (JsonValue) o;
}
if (o instanceof JsonSerializable) {
return ((JsonSerializable) o).toJsonValue();
}
if (o instanceof Map) {
//noinspection unchecked,rawtypes
return new JsonValue((Map) o);
}
if (o instanceof List) {
//noinspection unchecked,rawtypes
return new JsonValue((List) o);
}
if (o instanceof Set) {
//noinspection unchecked,rawtypes
return new JsonValue(new ArrayList<>((Set) o));
}
if (o instanceof String) {
String s = ((String) o).trim();
return s.length() == 0 ? new JsonValue() : new JsonValue(s);
}
if (o instanceof Boolean) {
return new JsonValue((Boolean) o);
}
if (o instanceof Integer) {
return new JsonValue((Integer) o);
}
if (o instanceof Long) {
return new JsonValue((Long) o);
}
if (o instanceof Double) {
return new JsonValue((Double) o);
}
if (o instanceof Float) {
return new JsonValue((Float) o);
}
if (o instanceof BigDecimal) {
return new JsonValue((BigDecimal) o);
}
if (o instanceof BigInteger) {
return new JsonValue((BigInteger) o);
}
return new JsonValue(o.toString());
}The toJsonValue method in class io.nats.client.support.JsonValueUtils is used to convert an object into a JsonValue object. Here is a step-by-step description of what this method does:
- Check if the input object
ois null. If it is, return aJsonValueobject with valuenull. - Check if the input object
ois already an instance ofJsonValue. If it is, cast it toJsonValueand return it. - Check if the input object
ois an instance ofJsonSerializable. If it is, call thetoJsonValuemethod of the object and return the result. - Check if the input object
ois an instance ofMap. If it is, create a newJsonValueobject using theMapconstructor and return it. - Check if the input object
ois an instance ofList. If it is, create a newJsonValueobject using theListconstructor and return it. - Check if the input object
ois an instance ofSet. If it is, create a newArrayListwith the elements of theSet, then create a newJsonValueobject using theArrayListconstructor and return it. - Check if the input object
ois an instance ofString. If it is, trim the string and check if it is empty. If it is empty, create a new emptyJsonValueobject, otherwise create a newJsonValueobject with the trimmed string and return it. - Check if the input object
ois an instance ofBoolean,Integer,Long,Double,Float,BigDecimal, orBigInteger. If it is, create a newJsonValueobject with the value of the object and return it. - If none of the above conditions are met, convert the object to a string using the
toStringmethod and create a newJsonValueobject with the string and return it.
The toJsonValue method in io.nats.client.support.JsonValueUtils is a static method that converts an object into a JsonValue object.
Here's a breakdown of the logic in the method:
- If the input object is
null, it returns aJsonValue.NULL. - If the input object is already an instance of
JsonValue, it simply returns the object. - If the input object implements the
JsonSerializableinterface, it calls thetoJsonValue()method on that object and returns the result. - If the input object is a
Map, it creates a newJsonValueobject using the constructor that accepts aMap. - If the input object is a
List, it creates a newJsonValueobject using the constructor that accepts aList. - If the input object is a
Set, it creates a newJsonValueobject by converting theSetto anArrayListand passing it to theJsonValueconstructor that accepts aList. - If the input object is a
String, it trims the string and checks its length. If the length is 0, it returns a new emptyJsonValueobject; otherwise, it returns aJsonValueobject containing the trimmed string. - If the input object is a
Boolean,Integer,Long,Double,Float,BigDecimal, orBigInteger, it creates a newJsonValueobject by passing the object to the corresponding constructor. - If none of the above conditions are met, it converts the object to a string and creates a new
JsonValueobject containing that string.
Overall, the toJsonValue method is responsible for converting various types of objects into their corresponding JsonValue representations.
ByteArrayPrimitiveBuilder
The ByteArrayPrimitiveBuilder class extends the BuilderBase class. This class allows for the construction of byte array primitives.
public byte[] toByteArray()
@Override
public byte[] toByteArray() {
byte[] bytes = new byte[position];
System.arraycopy(buffer, 0, bytes, 0, position);
return bytes;
}The toByteArray method in the ByteArrayPrimitiveBuilder class is used to convert the buffer used by the builder to a byte array. The method follows the below step-by-step description:
- Create a new
bytearray calledbyteswith a length equal to the current position of the buffer. - Use the
System.arraycopymethod to copy the contents of thebufferto thebytesarray, starting from index 0 and copyingpositionnumber of elements. - Return the
bytesarray, which now contains the contents of the buffer up to the current position.
The toByteArray() method in the ByteArrayPrimitiveBuilder class, located in the io.nats.client.support package, generates a new byte array containing the data stored in the underlying buffer of the builder.
Internally, the method first creates a new byte array called bytes, with a size equal to the current position of the buffer. It then uses the System.arraycopy() method to copy the content of the buffer into the newly created bytes array, starting from index 0 and ending at the current position. Finally, it returns the bytes array containing the copied data.
In summary, this method is responsible for converting the data stored in the builder's buffer into a byte array for further processing or transmission.

public void ensureCapacity(int bytesNeeded) {
int bytesAvailable = buffer.length - position;
if (bytesAvailable < bytesNeeded) {
byte[] newBuffer = new byte[bufferAllocSize(position + bytesNeeded, allocationSize)];
System.arraycopy(buffer, 0, newBuffer, 0, position);
buffer = newBuffer;
}
}The ensureCapacity method in the ByteArrayPrimitiveBuilder class is responsible for ensuring that the underlying buffer has enough capacity to store the specified number of bytes. Here is a step-by-step description of what the method does:
-
Calculate the number of bytes available in the current buffer. This is done by subtracting the current position from the length of the buffer. This will give us the number of bytes that can be added to the buffer without exceeding its capacity.
-
Check if the number of bytes available is less than the number of bytes needed. If this condition is true, it means that the current buffer does not have enough capacity to store the required number of bytes.
-
If the buffer capacity is insufficient, allocate a new buffer with an increased size. The new buffer size is determined by calling the
bufferAllocSizemethod, passing in the sum of the current position and the number of bytes needed, as well as the allocationSize value. This method calculates the appropriate buffer size based on the given parameters. -
Copy the contents of the current buffer to the new buffer. This is done using the
System.arraycopymethod. The contents are copied from the starting position 0 in the old buffer to the starting position 0 in the new buffer, up to the current position. -
Update the reference to the buffer with the new buffer. This ensures that future operations on the
ByteArrayPrimitiveBuilderuse the increased capacity buffer.
By following these steps, the ensureCapacity method in the ByteArrayPrimitiveBuilder class guarantees that the underlying buffer will have enough capacity to accommodate the specified number of bytes. This is achieved by increasing the buffer size if necessary and copying the existing data to the new buffer.
The ensureCapacity method in the ByteArrayPrimitiveBuilder class is used to check if the existing buffer has enough capacity to accommodate a specified number of bytes. If the available capacity is less than the required number of bytes, the method will allocate a new buffer with an adjusted size and copy the existing data into it. This method ensures that the buffer has sufficient space to hold the desired data without causing any overflow or memory allocation issues.

public ByteArrayPrimitiveBuilder append(CharBuffer src, Charset charset) {
if (src == null) {
append(NULL, 0, 4);
} else {
append(src.toString().getBytes(charset));
}
return this;
}The append method in the ByteArrayPrimitiveBuilder class is used to add data to the byte array being built. Here is a step-by-step description of what the method is doing based on its body:
-
It takes two parameters:
src, which is aCharBuffer, andcharset, which is the character set to be used for encoding theCharBufferinto bytes. -
It checks if the
srcparameter isnull. If it isnull, it means that there is no data to append. In this case, it calls theappendmethod of theByteArrayPrimitiveBuilderclass with the following parameters:NULL, which is a predefined byte array representing null,0, which is the starting index of theNULLbyte array, and4, which is the length of theNULLbyte array. -
If the
srcparameter is notnull, it means that there is data to append. In this case, it converts theCharBufferto a string by calling thetoString()method on it and then encodes the string into bytes using the specifiedcharset. -
It then calls the
appendmethod of theByteArrayPrimitiveBuilderclass with the byte array obtained from the string encoding. -
Finally, it returns a reference to the
ByteArrayPrimitiveBuilderobject itself, allowing for method chaining.
Note: The exact behavior of the append method may depend on the implementation of the ByteArrayPrimitiveBuilder class. This description is based on the provided code snippet.
The append method in the ByteArrayPrimitiveBuilder class appends data to the byte array built by the builder.
This specific append method takes a CharBuffer and a Charset as parameters. It first checks if the CharBuffer is null. If it is null, it appends a null value indicator to the byte array.
If the CharBuffer is not null, it converts the CharBuffer to a String, gets the byte array representation of the string using the specified Charset, and appends it to the byte array.
Finally, it returns the builder instance to allow for method chaining.

public ByteArrayPrimitiveBuilder append(byte[] src, int len) {
if (len > 0) {
ensureCapacity(len);
System.arraycopy(src, 0, buffer, position, len);
position += len;
}
return this;
}This method is used to append a byte array src to the internal buffer within the ByteArrayPrimitiveBuilder class.
-
src: The byte array to be appended -
len: The length of the byte array to append
- Check if the length (
len) is greater than 0. - If the length is greater than 0, proceed to the next step. Otherwise, the method will do nothing and return the current instance of
ByteArrayPrimitiveBuilder. - Ensure that the internal buffer has sufficient capacity to accommodate the byte array by invoking the
ensureCapacitymethod. - Use
System.arraycopyto copy thesrcbyte array starting from index 0 to thebufferarray, starting at the currentpositionwithin the buffer. - Increase the
positionby the length of the appended byte array to maintain the correct position within the buffer. - Return the current instance of
ByteArrayPrimitiveBuilder, allowing for method chaining.
The append method in the ByteArrayPrimitiveBuilder class of the io.nats.client.support package is used to append a given byte array to the internal buffer.
The method takes two parameters: src, which is the byte array to be appended, and len, which specifies the number of bytes from the src array to be appended.
First, the method checks if the length len is greater than zero. If it is, the method ensures that the internal buffer has enough capacity to accommodate the additional bytes. Then, it performs a system-level array copy operation (System.arraycopy) to copy the bytes from src array starting from index 0, to the internal buffer at the current position. Finally, it updates the position variable to account for the added bytes.
The method returns the current instance of ByteArrayPrimitiveBuilder to allow for method chaining.
In summary, the append method is responsible for appending a given byte array to the internal buffer, updating the position of the buffer accordingly, and returning the updated instance of the ByteArrayPrimitiveBuilder.

public ByteArrayPrimitiveBuilder append(byte[] src, int index, int len) {
if (len > 0) {
ensureCapacity(len);
System.arraycopy(src, index, buffer, position, len);
position += len;
}
return this;
}The append method in the ByteArrayPrimitiveBuilder class is used to append a portion of a byte array to the current buffer. Here's a step-by-step description of what the method does based on its body:
- It takes three parameters:
src(the sourcebytearray),index(the starting index in the source array), andlen(the length of the portion to be appended). - It checks if the length provided is greater than 0.
- If the length is greater than 0, it proceeds to the next steps.
- It ensures that the current buffer has enough capacity to accommodate the portion being appended. If not, it allocates more space to the buffer.
- It then uses the
System.arraycopymethod to copy the specified portion of the source array (src) starting from the provided index (index) to the current position in the buffer. - Finally, it updates the current position in the buffer by adding the length of the portion that was appended.
- It returns the current instance of
ByteArrayPrimitiveBuilder, allowing method chaining.
Note: The append method assumes that the buffer, position, and ensureCapacity variables are defined and accessible within the ByteArrayPrimitiveBuilder class.
The append method in the ByteArrayPrimitiveBuilder class is used to add a portion of a byte array to a buffer.
The method takes three parameters: src, index, and len. src is the source array from which the byte data will be copied. index is the starting index in the source array from where the data will be copied. len is the length of the portion of the source array that will be copied.
Inside the method, the len parameter is checked to ensure that it is greater than zero. If it is, the method ensures that the buffer has enough capacity to accommodate the data being copied. Then, the System.arraycopy method is used to copy the specified portion of the source array (src) into the buffer, starting from the current position in the buffer. Finally, the position is incremented by the length of the data copied.
The method returns an instance of the ByteArrayPrimitiveBuilder class, allowing for chaining of method calls.

public ByteArrayPrimitiveBuilder append(ByteArrayPrimitiveBuilder bab) {
if (bab != null) {
append(bab.buffer, bab.length());
}
return this;
}The append method is defined in the io.nats.client.support.ByteArrayPrimitiveBuilder class. It takes a parameter bab of type ByteArrayPrimitiveBuilder and appends the contents of bab to the current ByteArrayPrimitiveBuilder object.
- Check if
babis notnull. - If
babis notnull, call theappendmethod on the currentByteArrayPrimitiveBuilderobject, passingbab.bufferandbab.length()as parameters. - Return the current
ByteArrayPrimitiveBuilderobject after appending the contents ofbab.
The append method defined in the ByteArrayPrimitiveBuilder class allows for appending the contents of another ByteArrayPrimitiveBuilder object to the current object.
The method first checks if the provided ByteArrayPrimitiveBuilder object is not null. If it isn't null, it then proceeds to append the contents of the bab object's buffer and its length to the current object's buffer using the append method defined in the same class.
Finally, the method returns a reference to the current ByteArrayPrimitiveBuilder object, allowing for method chaining and further manipulation if desired.

public int appendUnchecked(byte[] src, int srcPos, int len)
@Override
public int appendUnchecked(byte[] src, int srcPos, int len) {
System.arraycopy(src, srcPos, buffer, position, len);
position += len;
return len;
}The appendUnchecked method in class io.nats.client.support.ByteArrayPrimitiveBuilder is a method that appends a specified number of bytes from a source array to a buffer array. Here is a step-by-step description of what the method does:
-
The method receives three parameters:
src,srcPos, andlen.-
srcis the source array from which the bytes will be copied. -
srcPosis the starting position of the bytes in the source array. -
lenis the number of bytes to be copied from the source array.
-
-
The method uses the
System.arraycopymethod to copy the specified number of bytes from the source array (src) to the buffer array at the current position (position).- The
srcPosparameter is used as the starting point in the source array. - The
bufferarray is the destination array. - The
positionis the current position/index in the buffer array at which the bytes will be copied. - The
lenparameter specifies the number of bytes to be copied from the source array.
- The
-
After copying the bytes, the
positionis incremented by the value oflen. This ensures that subsequent calls to theappendUncheckedmethod will append to the correct position in the buffer array. -
The method returns the value of
len, which represents the number of bytes that were successfully appended to the buffer array.
Overall, the appendUnchecked method allows for appending a specific number of bytes from a source array to a buffer array, keeping track of the current position in the buffer array for subsequent appends.
The appendUnchecked method, defined in the ByteArrayPrimitiveBuilder class of the io.nats.client.support package, is used to append a portion of a byte array to the existing buffer.
The method takes in three parameters: src, srcPos, and len.
-
srcis the source byte array from which the data will be copied. -
srcPosis the starting index in the source array from where the copy operation will begin. -
lenis the number of bytes to be copied.
Inside the method, the System.arraycopy() function is used to copy the specified portion of the source array (src) to the current position in the internal buffer. The position is then updated accordingly by incrementing it by the length of the copied data.
Finally, the method returns the length of the copied data (len).

BuilderBase
BuilderBase is an abstract class that serves as the base for builders in software engineering. It provides a framework for creating and manipulating objects in a flexible and modular manner. This class enables the implementation of builder patterns, allowing developers to construct complex objects step by step. The abstract nature of BuilderBase encourages extensibility and customization, making it a valuable tool for creating robust and maintainable software systems.
protected void _setAllocationSize(int allocationSizeSuggestion) {
int dcas = _defaultCharsetAllocationSize();
if (allocationSizeSuggestion <= dcas) {
allocationSize = dcas;
} else {
allocationSize = bufferAllocSize(allocationSizeSuggestion, ALLOCATION_BOUNDARY);
}
}The _setAllocationSize method in the class io.nats.client.support.BuilderBase is used to set the allocation size for a buffer.
The method takes an integer argument allocationSizeSuggestion, which represents the suggested allocation size.
Inside the method, it first calculates the default allocation size (dcas) using the _defaultCharsetAllocationSize method.
If the allocationSizeSuggestion is less than or equal to dcas, then the allocationSize is set to dcas. Otherwise, it calculates the buffer allocation size using the bufferAllocSize method, passing the allocationSizeSuggestion and ALLOCATION_BOUNDARY as arguments. The result is then assigned to the allocationSize variable.
