org.gwtproject.rpc.serialization.api.impl.AbstractSerializationStream Maven / Gradle / Ivy
package org.gwtproject.rpc.serialization.api.impl;
/**
* Base class for the client and server serialization streams. This class
* handles the basic serialization and deserialization formatting for primitive
* types since these are common between the client and the server.
*/
public abstract class AbstractSerializationStream {
/**
* The default flags to be used by serialization streams.
*/
public static final int DEFAULT_FLAGS = 0;
/**
* The character used to separate fields in client->server RPC messages.
*/
public static final char RPC_SEPARATOR_CHAR = '|';
/**
* The newest supported RPC protocol version.
*/
public static final int SERIALIZATION_STREAM_MAX_VERSION = 8;
/**
* The current RPC protocol version.
*/
public static final int SERIALIZATION_STREAM_VERSION = 7;
/**
* The oldest supported RPC protocol version.
*/
public static final int SERIALIZATION_STREAM_MIN_VERSION = 5;
/**
* First version to support valid JSON formatted payload responses
*/
public static final int SERIALIZATION_STREAM_JSON_VERSION = 8;
/**
* Indicates that obfuscated type names should be used in the RPC payload.
*/
public static final int FLAG_ELIDE_TYPE_NAMES = 0x1;
/**
* Indicates that RPC token is included in the RPC payload.
*/
public static final int FLAG_RPC_TOKEN_INCLUDED = 0x2;
/**
* Bit mask representing all valid flags.
*/
public static final int VALID_FLAGS_MASK = 0x3;
private int flags = DEFAULT_FLAGS;
private int version = SERIALIZATION_STREAM_VERSION;
public final void addFlags(int flags) {
this.flags |= flags;
}
/**
* Checks if flags are valid.
*
* @return true
if flags are valid and false
* otherwise.
*/
public final boolean areFlagsValid() {
return (((flags | VALID_FLAGS_MASK) ^ VALID_FLAGS_MASK) == 0);
}
public final int getFlags() {
return flags;
}
public final int getVersion() {
return version;
}
public final boolean hasFlags(int flags) {
return (getFlags() & flags) == flags;
}
public final void setFlags(int flags) {
this.flags = flags;
}
protected final void setVersion(int version) {
this.version = version;
}
/**
* Parse a string containing a base-64 encoded version of a long value.
*
* Keep this synchronized with the version in Base64Utils.
*/
protected static long longFromBase64(String value) {
int pos = 0;
long longVal = base64Value(value.charAt(pos++));
int len = value.length();
while (pos < len) {
longVal <<= 6;
longVal |= base64Value(value.charAt(pos++));
}
return longVal;
}
/**
* Return an optionally single-quoted string containing a base-64 encoded
* version of the given long value.
*
* Keep this synchronized with the version in Base64Utils.
*/
protected static String longToBase64(long value) {
// Convert to ints early to avoid need for long ops
int low = (int) (value & 0xffffffff);
int high = (int) (value >> 32);
StringBuilder sb = new StringBuilder();
boolean haveNonZero = base64Append(sb, (high >> 28) & 0xf, false);
haveNonZero = base64Append(sb, (high >> 22) & 0x3f, haveNonZero);
haveNonZero = base64Append(sb, (high >> 16) & 0x3f, haveNonZero);
haveNonZero = base64Append(sb, (high >> 10) & 0x3f, haveNonZero);
haveNonZero = base64Append(sb, (high >> 4) & 0x3f, haveNonZero);
int v = ((high & 0xf) << 2) | ((low >> 30) & 0x3);
haveNonZero = base64Append(sb, v, haveNonZero);
haveNonZero = base64Append(sb, (low >> 24) & 0x3f, haveNonZero);
haveNonZero = base64Append(sb, (low >> 18) & 0x3f, haveNonZero);
haveNonZero = base64Append(sb, (low >> 12) & 0x3f, haveNonZero);
base64Append(sb, (low >> 6) & 0x3f, haveNonZero);
base64Append(sb, low & 0x3f, true);
return sb.toString();
}
private static boolean base64Append(StringBuilder sb, int digit, boolean haveNonZero) {
if (digit > 0) {
haveNonZero = true;
}
if (haveNonZero) {
int c;
if (digit < 26) {
c = 'A' + digit;
} else if (digit < 52) {
c = 'a' + digit - 26;
} else if (digit < 62) {
c = '0' + digit - 52;
} else if (digit == 62) {
c = '$';
} else {
c = '_';
}
sb.append((char) c);
}
return haveNonZero;
}
// Assume digit is one of [A-Za-z0-9$_]
private static int base64Value(char digit) {
if (digit >= 'A' && digit <= 'Z') {
return digit - 'A';
}
// No need to check digit <= 'z'
if (digit >= 'a') {
return digit - 'a' + 26;
}
if (digit >= '0' && digit <= '9') {
return digit - '0' + 52;
}
if (digit == '$') {
return 62;
}
// digit == '_'
return 63;
}
}