All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bloodshura.ignitium.ntv.struct.MappedStruct Maven / Gradle / Ivy

The newest version!
package com.github.bloodshura.ignitium.ntv.struct;

import com.github.bloodshura.ignitium.collection.list.XList;
import com.github.bloodshura.ignitium.collection.list.impl.XArrayList;
import com.github.bloodshura.ignitium.collection.view.XBasicView;
import com.github.bloodshura.ignitium.collection.view.XView;
import com.github.bloodshura.ignitium.ntv.NativeException;
import com.github.bloodshura.ignitium.ntv.source.DataSource;
import com.sun.jna.Pointer;

import javax.annotation.Nonnull;
import java.util.function.Supplier;

public class MappedStruct {
	final XList fields;
	private final boolean cacheable;
	private DataSource source;

	public MappedStruct() {
		this.cacheable = getClass().isAnnotationPresent(Cacheable.class);
		this.fields = new XArrayList<>();
	}

	@Nonnull
	public final XView getFields() {
		return new XBasicView<>(fields);
	}

	@Nonnull
	public final DataSource getSource() throws NativeException {
		if (source == null) {
			throw new NativeException("Cannot access the source of an unmapped struct (use MappedStruct::map)");
		}

		return source;
	}

	public final boolean isCacheable() {
		return cacheable;
	}

	public final void map(@Nonnull DataSource source) {
		unmap();

		this.source = source;
	}

	public final void map(@Nonnull DataSource source, long offset) {
		unmap();

		this.source = source.withOffset(offset);
	}

	public final void map(@Nonnull DataSource source, @Nonnull Pointer offset) {
		unmap();

		this.source = source.withOffset(offset);
	}

	public final void unmap() {
		getFields().forEach(field -> field.cachedValue = null);

		this.source = null;
	}

	// Can't use method references here (like getSource()::readBoolean) because 'getSource()' will be called
	// at the moment of instantiation/xxxField invocation, and not at getValue/setValue invocation, thus
	// throwing a NativeException since this struct is not mapped yet.

	@Nonnull
	protected final MutableStructField addressField(int offset) {
		// TODO 32-bit?
		return new CommonStructField<>(this, offset, Long.BYTES, o -> getSource().readPointerAddress(o), (o, value) -> getSource().writePointerAddress(o, value));
	}

	@Nonnull
	protected final MutableStructField boolField(int offset) {
		return new CommonStructField<>(this, offset, Byte.BYTES, o -> getSource().readBoolean(o), (o, value) -> getSource().writeBoolean(o, value));
	}

	@Nonnull
	protected final MutableStructField charField(int offset) {
		return new CommonStructField<>(this, offset, Character.BYTES, o -> getSource().readChar(o), (o, value) -> getSource().writeChar(o, value));
	}

	@Nonnull
	protected final MutableStructField doubleField(int offset) {
		return new CommonStructField<>(this, offset, Double.BYTES, o -> getSource().readDouble(o), (o, value) -> getSource().writeDouble(o, value));
	}

	@Nonnull
	protected final MutableStructField field(int offset, int size) {
		return new CommonStructField<>(this, offset, size, o -> {
			byte[] array = new byte[size];

			getSource().read(o, array);

			return array;
		}, (o, value) -> {
			getSource().write(o, value, 0, Math.min(value.length, size));
		});
	}

	@Nonnull
	protected final MutableStructField floatField(int offset) {
		return new CommonStructField<>(this, offset, Float.BYTES, o -> getSource().readFloat(o), (o, value) -> getSource().writeFloat(o, value));
	}

	@Nonnull
	protected final MutableStructField intField(int offset) {
		return new CommonStructField<>(this, offset, Integer.BYTES, o -> getSource().readInt(o), (o, value) -> getSource().writeInt(o, value));
	}

	@Nonnull
	protected final MutableStructField longField(int offset) {
		return new CommonStructField<>(this, offset, Long.BYTES, o -> getSource().readLong(o), (o, value) -> getSource().writeLong(o, value));
	}

	@Nonnull
	protected final MutableStructField pointerField(int offset) {
		// TODO 32-bit?
		return new CommonStructField<>(this, offset, Long.BYTES, o -> {
			Pointer pointer = getSource().readPointer(o);

			return pointer != null ? pointer : new Pointer(0L);
		}, (o, value) -> getSource().writePointer(o, value));
	}

	@Nonnull
	protected final MutableStructField shortField(int offset) {
		return new CommonStructField<>(this, offset, Short.BYTES, o -> getSource().readShort(o), (o, value) -> getSource().writeShort(o, value));
	}

	@Nonnull
	protected final  StructField structField(@Nonnull E instance, int offset) throws NativeException {
		return structField((Supplier) () -> instance, offset);
	}

	@Nonnull
	protected final  StructField structField(@Nonnull Supplier generator, int offset) throws NativeException {
		E initialInstance = generator.get();

		return new ForeignStructField<>(this, offset, initialInstance.getSize(), generator);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy