com.fasterxml.jackson.databind.deser.std.UUIDDeserializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jersey-all Show documentation
Show all versions of jersey-all Show documentation
jersey-all is a rebundled verison of Jersey as one OSGi bundle.
package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.Arrays;
import java.util.UUID;
import com.fasterxml.jackson.core.Base64Variants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
public class UUIDDeserializer
extends FromStringDeserializer
{
private static final long serialVersionUID = 1L;
final static int[] HEX_DIGITS = new int[127];
static {
Arrays.fill(HEX_DIGITS, -1);
for (int i = 0; i < 10; ++i) {
HEX_DIGITS['0' + i] = i;
}
for (int i = 0; i < 6; ++i) {
HEX_DIGITS['a' + i] = 10 + i;
HEX_DIGITS['A' + i] = 10 + i;
}
}
public final static UUIDDeserializer instance = new UUIDDeserializer();
public UUIDDeserializer() { super(UUID.class); }
@Override
protected UUID _deserialize(String id, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Adapted from java-uuid-generator (https://github.com/cowtowncoder/java-uuid-generator)
// which is 5x faster than UUID.fromString(value), as oper "ManualReadPerfWithUUID"
if (id.length() != 36) {
/* 14-Sep-2013, tatu: One trick we do allow, Base64-encoding, since we know
* length it must have...
*/
if (id.length() == 24) {
byte[] stuff = Base64Variants.getDefaultVariant().decode(id);
return _fromBytes(stuff, ctxt);
}
_badFormat(id);
}
// verify hyphens first:
if ((id.charAt(8) != '-') || (id.charAt(13) != '-')
|| (id.charAt(18) != '-') || (id.charAt(23) != '-')) {
_badFormat(id);
}
long l1 = intFromChars(id, 0);
l1 <<= 32;
long l2 = ((long) shortFromChars(id, 9)) << 16;
l2 |= shortFromChars(id, 14);
long hi = l1 + l2;
int i1 = (shortFromChars(id, 19) << 16) | shortFromChars(id, 24);
l1 = i1;
l1 <<= 32;
l2 = intFromChars(id, 28);
l2 = (l2 << 32) >>> 32; // sign removal, Java-style. Ugh.
long lo = l1 | l2;
return new UUID(hi, lo);
}
@Override
protected UUID _deserializeEmbedded(Object ob, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (ob instanceof byte[]) {
return _fromBytes((byte[]) ob, ctxt);
}
super._deserializeEmbedded(ob, ctxt);
return null; // never gets here
}
private void _badFormat(String uuidStr) {
throw new NumberFormatException("UUID has to be represented by the standard 36-char representation");
}
static int intFromChars(String str, int index) {
return (byteFromChars(str, index) << 24)
+(byteFromChars(str, index+2) << 16)
+(byteFromChars(str, index+4) << 8)
+ byteFromChars(str, index+6);
}
static int shortFromChars(String str, int index) {
return (byteFromChars(str, index) << 8) + byteFromChars(str, index+2);
}
static int byteFromChars(String str, int index)
{
final char c1 = str.charAt(index);
final char c2 = str.charAt(index+1);
if (c1 <= 127 && c2 <= 127) {
int hex = (HEX_DIGITS[c1] << 4) | HEX_DIGITS[c2];
if (hex >= 0) {
return hex;
}
}
if (c1 > 127 || HEX_DIGITS[c1] < 0) {
return _badChar(str, index, c1);
}
return _badChar(str, index+1, c2);
}
static int _badChar(String uuidStr, int index, char c) {
throw new NumberFormatException("Non-hex character '"+c+"', not valid character for a UUID String"
+"' (value 0x"+Integer.toHexString(c)+") for UUID String \""+uuidStr+"\"");
}
private UUID _fromBytes(byte[] bytes, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (bytes.length != 16) {
ctxt.mappingException("Can only construct UUIDs from byte[16]; got "+bytes.length+" bytes");
}
return new UUID(_long(bytes, 0), _long(bytes, 8));
}
private static long _long(byte[] b, int offset)
{
long l1 = ((long) _int(b, offset)) << 32;
long l2 = _int(b, offset+4);
// faster to just do it than check if it has sign
l2 = (l2 << 32) >>> 32; // to get rid of sign
return l1 | l2;
}
private static int _int(byte[] b, int offset)
{
return (b[offset] << 24)
| ((b[offset+1] & 0xFF) << 16)
| ((b[offset+2] & 0xFF) << 8)
| (b[offset+3] & 0xFF)
;
}
}