package net.scapeemulator.cache;
import java.nio.ByteBuffer;
import net.scapeemulator.cache.util.ByteBufferUtils;
/**
* A {@link Sector} contains a header and data. The header contains information
* used to verify the integrity of the cache like the current file id, type and
* chunk. It also contains a pointer to the next sector such that the sectors
* form a singly-linked list. The data is simply up to 512 bytes of the file.
* @author Graham
* @author `Discardedx2
*/
public final class Sector {
/**
* The size of the header within a sector in bytes.
*/
public static final int HEADER_SIZE = 8;
/**
* The size of the data within a sector in bytes.
*/
public static final int DATA_SIZE = 512;
/**
* The total size of a sector in bytes.
*/
public static final int SIZE = HEADER_SIZE + DATA_SIZE;
/**
* Decodes the specified {@link ByteBuffer} into a {@link Sector} object.
* @param buf The buffer.
* @return The sector.
*/
public static Sector decode(ByteBuffer buf) {
if (buf.remaining() != SIZE)
throw new IllegalArgumentException();
int id = buf.getShort() & 0xFFFF;
int chunk = buf.getShort() & 0xFFFF;
int nextSector = ByteBufferUtils.getTriByte(buf);
int type = buf.get() & 0xFF;
byte[] data = new byte[DATA_SIZE];
buf.get(data);
return new Sector(type, id, chunk, nextSector, data);
}
/**
* The type of file this sector contains.
*/
private final int type;
/**
* The id of the file this sector contains.
*/
private final int id;
/**
* The chunk within the file that this sector contains.
*/
private final int chunk;
/**
* The next sector.
*/
private final int nextSector;
/**
* The data in this sector.
*/
private final byte[] data;
/**
* Creates a new sector.
* @param type The type of the file.
* @param id The file's id.
* @param chunk The chunk of the file this sector contains.
* @param nextSector The sector containing the next chunk.
* @param data The data in this sector.
*/
public Sector(int type, int id, int chunk, int nextSector, byte[] data) {
this.type = type;
this.id = id;
this.chunk = chunk;
this.nextSector = nextSector;
this.data = data;
}
/**
* Gets the type of file in this sector.
* @return The type of file in this sector.
*/
public int getType() {
return type;
}
/**
* Gets the id of the file within this sector.
* @return The id of the file in this sector.
*/
public int getId() {
return id;
}
/**
* Gets the chunk of the file this sector contains.
* @return The chunk of the file this sector contains.
*/
public int getChunk() {
return chunk;
}
/**
* Gets the next sector.
* @return The next sector.
*/
public int getNextSector() {
return nextSector;
}
/**
* Gets this sector's data.
* @return The data within this sector.
*/
public byte[] getData() {
return data;
}
/**
* Encodes this sector into a {@link ByteBuffer}.
* @return The encoded buffer.
*/
public ByteBuffer encode() {
ByteBuffer buf = ByteBuffer.allocate(SIZE);
buf.putShort((short) id);
buf.putShort((short) chunk);
ByteBufferUtils.putTriByte(buf, nextSector);
buf.put((byte) type);
buf.put(data);
return (ByteBuffer) buf.flip();
}
}