Package com.esotericsoftware.kryo.serializers

Source Code of com.esotericsoftware.kryo.serializers.TaggedFieldSerializer

package com.esotericsoftware.kryo.serializers;

import static com.esotericsoftware.minlog.Log.*;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

/** Serializes objects using direct field assignment for fields that have been {@link Tag tagged}. Fields without the {@link Tag}
* annotation are not serialized. New tagged fields can be added without invalidating previously serialized bytes. If any tagged
* field is removed, previously serialized bytes are invalidated. Instead of removing fields, apply the {@link Deprecated}
* annotation and they will still be deserialized but won't be serialized. If fields are public, bytecode generation will be used
* instead of reflection.
* @author Nathan Sweet <misc@n4te.com> */
public class TaggedFieldSerializer<T> extends FieldSerializer<T> {
  private int[] tags;
  private int writeFieldCount;
  private boolean[] deprecated;

  public TaggedFieldSerializer (Kryo kryo, Class type) {
    super(kryo, type);
  }

  protected void initializeCachedFields () {
    CachedField[] fields = getFields();
    // Remove untagged fields.
    for (int i = 0, n = fields.length; i < n; i++) {
      Field field = fields[i].getField();
      if (field.getAnnotation(Tag.class) == null) {
        if (TRACE) trace("kryo", "Ignoring field without tag: " + fields[i]);
        super.removeField(field.getName());
      }
    }
    // Cache tag values.
    fields = getFields();
    tags = new int[fields.length];
    deprecated = new boolean[fields.length];
    writeFieldCount = fields.length;
    for (int i = 0, n = fields.length; i < n; i++) {
      Field field = fields[i].getField();
      tags[i] = field.getAnnotation(Tag.class).value();
      if (field.getAnnotation(Deprecated.class) != null) {
        deprecated[i] = true;
        writeFieldCount--;
      }
    }
  }

  public void removeField (String fieldName) {
    super.removeField(fieldName);
    initializeCachedFields();
  }

  public void write (Kryo kryo, Output output, T object) {
    CachedField[] fields = getFields();
    output.writeVarInt(writeFieldCount, true); // Can be used for null.
    for (int i = 0, n = fields.length; i < n; i++) {
      if (deprecated[i]) continue;
      output.writeVarInt(tags[i], true);
      fields[i].write(output, object);
    }
  }

  public T read (Kryo kryo, Input input, Class<T> type) {
    T object = create(kryo, input, type);
    kryo.reference(object);
    int fieldCount = input.readVarInt(true);
    int[] tags = this.tags;
    CachedField[] fields = getFields();
    for (int i = 0, n = fieldCount; i < n; i++) {
      int tag = input.readVarInt(true);

      CachedField cachedField = null;
      for (int ii = 0, nn = tags.length; ii < nn; ii++) {
        if (tags[ii] == tag) {
          cachedField = fields[ii];
          break;
        }
      }
      if (cachedField == null) throw new KryoException("Unknown field tag: " + tag + " (" + getType().getName() + ")");
      cachedField.read(input, object);
    }
    return object;
  }

  /** If true, this field will not be serialized. */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public @interface Tag {
    int value();
  }
}
TOP

Related Classes of com.esotericsoftware.kryo.serializers.TaggedFieldSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.