package com.fasterxml.jackson.databind.ser.impl;
import java.util.Map;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ser.SerializerCache.TypeKey;
/**
* Specialized read-only map used for storing and accessing serializers by type.
*/
public class JsonSerializerMap
{
private final Bucket[] _buckets;
private final int _size;
public JsonSerializerMap(Map<TypeKey,JsonSerializer<Object>> serializers)
{
int size = findSize(serializers.size());
_size = size;
int hashMask = (size-1);
Bucket[] buckets = new Bucket[size];
for (Map.Entry<TypeKey,JsonSerializer<Object>> entry : serializers.entrySet()) {
TypeKey key = entry.getKey();
int index = key.hashCode() & hashMask;
buckets[index] = new Bucket(buckets[index], key, entry.getValue());
}
_buckets = buckets;
}
private final static int findSize(int size)
{
// For small enough results (64 or less), we'll require <= 50% fill rate; otherwise 80%
int needed = (size <= 64) ? (size + size) : (size + (size >> 2));
int result = 8;
while (result < needed) {
result += result;
}
return result;
}
/*
/**********************************************************
/* Public API
/**********************************************************
*/
public int size() { return _size; }
public JsonSerializer<Object> find(TypeKey key)
{
int index = key.hashCode() & (_buckets.length-1);
Bucket bucket = _buckets[index];
/* Ok let's actually try unrolling loop slightly as this shows up in profiler;
* and also because in vast majority of cases first entry is either null
* or matches.
*/
if (bucket == null) {
return null;
}
if (key.equals(bucket.key)) {
return bucket.value;
}
while ((bucket = bucket.next) != null) {
if (key.equals(bucket.key)) {
return bucket.value;
}
}
return null;
}
/*
/**********************************************************
/* Helper beans
/**********************************************************
*/
private final static class Bucket
{
public final TypeKey key;
public final JsonSerializer<Object> value;
public final Bucket next;
public Bucket(Bucket next, TypeKey key, JsonSerializer<Object> value)
{
this.next = next;
this.key = key;
this.value = value;
}
}
}