package de.take_weiland.mods.commons.serialize;
import de.take_weiland.mods.commons.SerializationMethod;
import de.take_weiland.mods.commons.internal.AnnotationNull;
import de.take_weiland.mods.commons.net.MCDataInput;
import de.take_weiland.mods.commons.net.MCDataOutput;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>A serializer that can serialize values of type {@code T} to a byte stream.</p>
*
* @author diesieben07
*/
public interface ByteStreamSerializer<T> {
/**
* <p>Serialize the given instance to the OutputStream.</p>
* @param instance the instance
* @param out the OutputStream
*/
void write(T instance, MCDataOutput out);
/**
* <p>Read an instance of type T from the InputStream.</p>
* @param in the IntputStream
* @return the instance
*/
T read(MCDataInput in);
/**
* <p>A serializer that can serialize the contents of objects of type {@code T} to a byte stream.
* As opposed to {@link de.take_weiland.mods.commons.serialize.ByteStreamSerializer}
* such a serializer never touches the instance being passed in but directly modifies it's contents.</p>
* <p>This is used for e.g. FluidTanks.</p>
*
*/
interface Contents<T> {
/**
* <p>Serialize the contents of the given instance to the OutputStream.</p>
* @param instance the instance
* @param out the OutputStream
*/
void write(T instance, MCDataOutput out);
/**
* <p>Deserialize the the contents of the given instance from the InputStream.</p>
* @param instance the instance
* @param in the InputStream
*/
void read(T instance, MCDataInput in);
}
/**
* <p>A Provider for ByteStreamSerializers.</p>
* <p>When applied to a method, this method must be static and accept a single parameter of type
* {@link Property}. It's return type must be any non-primitive type.</p>
*
* <p>When applied to a field, this field must be static and final. It's type must be assignable to {@code ByteStreamSerializer}
* resp. {@code ByteStreamSerializer.Contents}. The {@linkplain #method() SerializationMethod filter} must be set when applied
* to fields.</p>
*
* <p>The TypeSpecification dictates what this provider must provide. The TypeSpecification will only ever report
* the concrete SerializationMethods {@code VALUE} or {@code CONTENTS}. The provider must then return an instance of
* {@code ByteStreamSerializer} or {@code ByteStreamSerializer.Contents} respectively. If this provider cannot provide a
* serializer for the given TypeSpecification, {@code null} must be returned.</p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
@interface Provider {
/**
* <p>The base type that this provider can provide serializers for. This provider will only be queried for that
* type or subtypes. In other words: if this attribute reports {@code T.class}, this provider will only be queried
* for TypeSpecifications of type {@code TypeSpecification<? extends T>}.</p>
*
* <p>If this method is left at default, the class declaring the provider will be used.</p>
*
* @return the base type
*/
// if name is changed, need to update SerializerRegistry as well!
Class<?> forType() default AnnotationNull.class;
/**
* <p>A filter for the SerializationMethod that this provider supports. If {@code VALUE} or {@code CONTENTS}
* are specified, this provider will only be queried for types that demand that SerializationMethod.</p>
*
* <p>A filter is mandatory for fields.</p>
*
* @return a filter
*/
SerializationMethod.Method method() default SerializationMethod.Method.DEFAULT;
}
}