initial commit

This commit is contained in:
MrLetsplay 2024-08-01 18:44:59 +02:00
commit dcee1e4f22
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
21 changed files with 1094 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/bin/
/target/
/dependency-reduced-pom.xml
/.settings/
/.classpath

23
.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SimpleNIO</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

73
pom.xml Normal file
View File

@ -0,0 +1,73 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.mrletsplay</groupId>
<artifactId>SimpleNIO</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>11</release>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<source>11</source>
<encoding>UTF-8</encoding>
<sourcepath>src/main/java</sourcepath>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>Graphite-Official</id>
<url>https://maven.graphite-official.com/releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>me.mrletsplay</groupId>
<artifactId>MrCore</artifactId>
<version>4.5</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,5 @@
package me.mrletsplay.simplenio._test;
public class SimpleNIOMain {
}

View File

@ -0,0 +1,17 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.util.function.Supplier;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IORunnable;
public interface Expectation {
public void orElseRun(IOConsumer<ReaderInstance<?>> run);
public void orElseRun(IORunnable run);
public void orElseThrow(Supplier<? extends IOException> exception);
}

View File

@ -0,0 +1,33 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.util.function.Supplier;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IORunnable;
public class ExpectationImpl implements Expectation {
private IOConsumer<ReaderInstance<?>> run;
@Override
public void orElseRun(IOConsumer<ReaderInstance<?>> run) {
this.run = run;
}
@Override
public void orElseRun(IORunnable run) {
this.run = instance -> run.run();
}
@Override
public void orElseThrow(Supplier<? extends IOException> exception) {
this.run = instance -> { throw exception.get(); };
}
public void fail(ReaderInstance<?> instance) throws IOException {
if(run == null) throw new IOException("Expectation failed");
run.accept(instance);
}
}

View File

@ -0,0 +1,46 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.nio.ByteBuffer;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IORunnable;
public interface Operation extends OperationCallback {
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException;
public Operation copy();
public void reset();
public default Operation then(Operation other) {
return Operations.allOf(this, other);
}
/**
* API Note: {@code other} must be a stateless runnable, because it might be called from multiple threads.
* @param other The action to run
* @return An Operation
*/
public default Operation thenRun(IORunnable other) {
return then(Operations.stateless((instance, buf) -> {
other.run();
return true;
}));
}
/**
* API Note: {@code other} must be a stateless runnable, because it might be called from multiple threads.
* @param other The action to run
* @return An Operation
*/
public default Operation thenRun(IOConsumer<ReaderInstance<?>> other) {
return then(Operations.stateless((instance, buf) -> {
other.accept(instance);
return true;
}));
}
}

View File

@ -0,0 +1,10 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.nio.ByteBuffer;
public interface OperationCallback {
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException;
}

View File

@ -0,0 +1,370 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IORunnable;
public class Operations {
public static Operation stateless(OperationCallback callback) {
return new Operation() {
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
return callback.read(instance, buf);
}
@Override
public Operation copy() {
return this;
}
@Override
public void reset() {
}
};
}
public static Operation run(IORunnable run) {
return stateless((instance, buf) -> {
run.run();
return true;
});
}
public static Operation run(IOConsumer<ReaderInstance<?>> run) {
return stateless((instance, buf) -> {
run.accept(instance);
return true;
});
}
public static Operation allOf(Operation... operations) {
return new CombinedOperation(operations);
}
public static Operation readByte(SimpleRef<Byte> ref) {
return stateless((instance, buf) -> {
if(!buf.hasRemaining()) return false;
ref.set(instance, buf.get());
return true;
});
}
public static Operation readInt(SimpleRef<Integer> ref) {
return new ReadIntOperation(ref);
}
public static Operation readNBytes(SimpleRef<byte[]> ref, int n) {
return new ReadBytesOperation(ref, n);
}
public static Operation readUntilBytes(SimpleRef<byte[]> ref, byte[] delimiter, int limit) {
return new ReadBytesUntilOperation(ref, delimiter, limit);
}
public static Operation lazy(Ref<Operation> lazy) {
return new LazyOperation(lazy);
}
public static Operation branch(Ref<Integer> value, Operation... branches) {
return new BranchOperation(value, branches);
}
public static Operation loopUntil(Ref<Boolean> condition, Operation body) {
return new LoopUntilOperation(condition, body);
}
public static <T> Operation read(SimpleRef<T> ref, Reader<? extends T> reader) {
return new ReaderOperation<>(ref, reader);
}
private static class CombinedOperation implements Operation {
private Operation[] operations;
private int i;
public CombinedOperation(Operation... operations) {
this.operations = operations;
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
while(i < operations.length) {
if(operations[i].read(instance, buf)) {
i++;
}else if(!buf.hasRemaining()) break;
}
return i == operations.length;
}
@Override
public Operation copy() {
return new CombinedOperation(Arrays.stream(operations).map(Operation::copy).toArray(Operation[]::new));
}
@Override
public void reset() {
for(Operation op : operations) op.reset();
i = 0;
}
}
private static class ReadIntOperation implements Operation {
private SimpleRef<Integer> ref;
private int value;
private int i;
public ReadIntOperation(SimpleRef<Integer> ref) {
this.ref = ref;
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
while(buf.hasRemaining() && i > 0) {
i--;
value |= (buf.get() & 0xFF) << i;
}
if(i == 0) {
ref.set(instance, value);
return true;
}
return false;
}
@Override
public Operation copy() {
return new ReadIntOperation(ref);
}
@Override
public void reset() {
this.value = 0;
this.i = 4;
}
}
private static class ReadBytesOperation implements Operation {
private SimpleRef<byte[]> ref;
private byte[] bytes;
private int i;
public ReadBytesOperation(SimpleRef<byte[]> ref, int n) {
this.ref = ref;
this.bytes = new byte[n];
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
while(buf.hasRemaining() && i < bytes.length) {
bytes[i++] = buf.get();
}
if(i == bytes.length) {
ref.set(instance, bytes);
return true;
}
return false;
}
@Override
public Operation copy() {
return new ReadBytesOperation(ref, bytes.length);
}
@Override
public void reset() {
i = 0;
}
}
private static class ReadBytesUntilOperation implements Operation {
private SimpleRef<byte[]> ref;
private byte[] delimiter;
private byte[] bytes;
private int i;
public ReadBytesUntilOperation(SimpleRef<byte[]> ref, byte[] delimiter, int limit) {
this.ref = ref;
this.delimiter = delimiter;
this.bytes = new byte[limit];
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
while(buf.hasRemaining() && i < bytes.length) {
bytes[i++] = buf.get();
if(i >= delimiter.length && Arrays.equals(bytes, i - delimiter.length, i, delimiter, 0, delimiter.length)) {
ref.set(instance, Arrays.copyOfRange(bytes, 0, i));
return true;
}
}
if(i == bytes.length) throw new IOException("Buffer limit reached");
return false;
}
@Override
public Operation copy() {
return new ReadBytesUntilOperation(ref, delimiter, bytes.length);
}
@Override
public void reset() {
i = 0;
}
}
private static class LazyOperation implements Operation {
private Ref<Operation> operationSupplier;
private Operation operation;
public LazyOperation(Ref<Operation> operationSupplier) {
this.operationSupplier = operationSupplier;
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
if(operation == null) operation = operationSupplier.get(instance);
return operation.read(instance, buf);
}
@Override
public Operation copy() {
return new LazyOperation(operationSupplier);
}
@Override
public void reset() {
this.operation = null;
}
}
private static class BranchOperation implements Operation {
private Ref<Integer> value;
private Operation[] branches;
private int i;
public BranchOperation(Ref<Integer> value, Operation... branches) {
this.value = value;
this.branches = branches;
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
if(i == -1) i = value.get(instance);
if(branches[i] == null) return true;
return branches[i].read(instance, buf);
}
@Override
public Operation copy() {
return new BranchOperation(value, Arrays.stream(branches).map(op -> op == null ? null : op.copy()).toArray(Operation[]::new));
}
@Override
public void reset() {
for(Operation op : branches) {
if(op != null) op.reset();
}
this.i = -1;
}
}
private static class LoopUntilOperation implements Operation {
private Ref<Boolean> condition;
private Operation body;
public LoopUntilOperation(Ref<Boolean> condition, Operation body) {
this.condition = condition;
this.body = body;
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
if(body.read(instance, buf)) {
body.reset();
if(condition.get(instance)) return true;
}
return false;
}
@Override
public Operation copy() {
return new LoopUntilOperation(condition, body.copy());
}
@Override
public void reset() {
body.reset();
}
}
private static class ReaderOperation<T> implements Operation {
private SimpleRef<T> ref;
private Reader<? extends T> reader;
private ReaderInstance<? extends T> readerInstance;
public ReaderOperation(SimpleRef<T> ref, Reader<? extends T> reader) {
this.ref = ref;
this.reader = reader;
this.readerInstance = reader.createInstance();
reset();
}
@Override
public boolean read(ReaderInstance<?> instance, ByteBuffer buf) throws IOException {
if(readerInstance.read(buf)) {
ref.set(instance, readerInstance.get());
return true;
}
return false;
}
@Override
public Operation copy() {
return new ReaderOperation<>(ref, reader);
}
@Override
public void reset() {
readerInstance.reset();
}
}
}

View File

@ -0,0 +1,61 @@
package me.mrletsplay.simplenio.reader;
import java.util.List;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IOFunction;
import me.mrletsplay.simplenio.util.IORunnable;
public interface Reader<T> {
public Ref<Byte> readByte();
public Ref<Integer> readInt();
public Ref<byte[]> readNBytes(int n);
public Ref<byte[]> readNBytes(Ref<Integer> n);
public Ref<byte[]> readUntilByte(byte delimiter, int limit);
public Ref<byte[]> readUntilByte(Ref<Byte> delimiter, int limit);
public Ref<byte[]> readUntilBytes(byte[] delimiter, int limit);
public Ref<byte[]> readUntilBytes(Ref<byte[]> delimiter, int limit);
public void read(Operation operation);
public <O> Ref<O> read(Reader<O> reader);
public void branch(Ref<Boolean> condition, Operation ifTrue, Operation ifFalse);
public void branch(Ref<Integer> value, Operation... branches);
public <O> Ref<O> branch(Ref<Boolean> condition, Reader<? extends O> ifTrue, Reader<? extends O> ifFalse);
public <O> Ref<O> branch(Ref<Integer> value, @SuppressWarnings("unchecked") Reader<? extends O>... branches);
public void loopUntil(Ref<Boolean> condition, Operation body);
public <O> Ref<List<O>> loopUntil(Ref<Boolean> condition, Reader<O> body);
public void run(IORunnable action);
public void run(IOConsumer<ReaderInstance<?>> action);
public Expectation expect(Ref<Boolean> condition);
public Expectation expectByte(byte b);
public Expectation expectByte(Ref<Byte> b);
public Expectation expectBytes(byte[] bytes);
public Expectation expectBytes(Ref<byte[]> b);
public void setConverter(IOFunction<ReaderInstance<T>, T> converter);
public ReaderInstance<T> createInstance();
}

View File

@ -0,0 +1,5 @@
package me.mrletsplay.simplenio.reader;
public class ReaderException {
}

View File

@ -0,0 +1,286 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import me.mrletsplay.simplenio.util.IOConsumer;
import me.mrletsplay.simplenio.util.IOFunction;
import me.mrletsplay.simplenio.util.IORunnable;
public class ReaderImpl<T> implements Reader<T> {
private List<Operation> operations;
private Map<Operation, StackTraceElement[]> stackTraces;
private IOFunction<ReaderInstance<T>, T> converter;
public ReaderImpl() {
this.operations = new ArrayList<>();
this.stackTraces = new HashMap<>();
}
private void addOperation(Operation operation) {
operations.add(operation);
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
stackTraces.put(operation, Arrays.copyOfRange(stackTrace, 1, stackTrace.length));
}
@Override
public Ref<Byte> readByte() {
SimpleRef<Byte> ref = SimpleRef.create();
addOperation(Operations.readByte(ref));
return ref;
}
@Override
public Ref<Integer> readInt() {
SimpleRef<Integer> valueRef = SimpleRef.create();
addOperation(Operations.readInt(valueRef));
return valueRef;
}
@Override
public Ref<byte[]> readNBytes(int n) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.readNBytes(ref, n));
return ref;
}
@Override
public Ref<byte[]> readNBytes(Ref<Integer> n) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.lazy(instance -> Operations.readNBytes(ref, n.get(instance))));
return ref;
}
@Override
public Ref<byte[]> readUntilByte(byte delimiter, int limit) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.readUntilBytes(ref, new byte[] {delimiter}, limit));
return ref;
}
@Override
public Ref<byte[]> readUntilByte(Ref<Byte> delimiter, int limit) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.lazy(instance -> Operations.readUntilBytes(ref, new byte[] {delimiter.get(instance)}, limit)));
return ref;
}
@Override
public Ref<byte[]> readUntilBytes(byte[] delimiter, int limit) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.readUntilBytes(ref, delimiter, limit));
return ref;
}
@Override
public Ref<byte[]> readUntilBytes(Ref<byte[]> delimiter, int limit) {
SimpleRef<byte[]> ref = SimpleRef.create();
addOperation(Operations.lazy(instance -> Operations.readUntilBytes(ref, delimiter.get(instance), limit)));
return ref;
}
@Override
public void read(Operation operation) {
addOperation(operation);
}
@Override
public <O> Ref<O> read(Reader<O> reader) {
SimpleRef<O> ref = SimpleRef.create();
addOperation(Operations.read(ref, reader));
return ref;
}
@Override
public void branch(Ref<Boolean> condition, Operation ifTrue, Operation ifFalse) {
addOperation(Operations.branch(condition.map(c -> c ? 0 : 1), ifTrue, ifFalse));
}
@Override
public void branch(Ref<Integer> value, Operation... branches) {
addOperation(Operations.branch(value, branches));
}
@Override
public <O> Ref<O> branch(Ref<Boolean> condition, Reader<? extends O> ifTrue, Reader<? extends O> ifFalse) {
SimpleRef<O> ref = SimpleRef.create();
addOperation(Operations.branch(condition.map(c -> c ? 0 : 1), ifTrue == null ? null : Operations.read(ref, ifTrue), ifFalse == null ? null : Operations.read(ref, ifFalse)));
return ref;
}
@Override
public <O> Ref<O> branch(Ref<Integer> value, @SuppressWarnings("unchecked") Reader<? extends O>... branches) {
SimpleRef<O> ref = SimpleRef.create();
addOperation(Operations.branch(value, Arrays.stream(branches).map(b -> b == null ? null : Operations.read(ref, b)).toArray(Operation[]::new)));
return ref;
}
@Override
public void loopUntil(Ref<Boolean> condition, Operation body) {
addOperation(Operations.loopUntil(condition, body));
}
@Override
public <O> Ref<List<O>> loopUntil(Ref<Boolean> condition, Reader<O> body) {
SimpleRef<O> current = SimpleRef.create();
SimpleRef<List<O>> ref = SimpleRef.create();
addOperation(Operations.run(instance -> ref.set(instance, new ArrayList<>())).then(Operations.loopUntil(condition, Operations.read(current, body).thenRun(instance -> ref.get(instance).add(current.get(instance))))));
return ref;
}
@Override
public void run(IORunnable action) {
addOperation(Operations.run(action));
}
@Override
public void run(IOConsumer<ReaderInstance<?>> action) {
addOperation(Operations.run(action));
}
@Override
public Expectation expect(Ref<Boolean> condition) {
ExpectationImpl expectation = new ExpectationImpl();
addOperation(Operations.stateless((instance, buf) -> {
if(!condition.get(instance)) expectation.fail(instance);
return true;
}));
return expectation;
}
@Override
public Expectation expectByte(byte b) {
Ref<Byte> read = readByte();
return expect(instance -> read.get(instance) == b);
}
@Override
public Expectation expectByte(Ref<Byte> b) {
Ref<Byte> read = readByte();
return expect(instance -> read.get(instance) == b.get(instance));
}
@Override
public Expectation expectBytes(byte[] bytes) {
Ref<byte[]> read = readNBytes(bytes.length);
return expect(instance -> Arrays.equals(read.get(instance), bytes));
}
@Override
public Expectation expectBytes(Ref<byte[]> bytes) {
SimpleRef<byte[]> read = SimpleRef.create();
addOperation(Operations.lazy(instance -> Operations.readNBytes(read, bytes.get(instance).length)));
return expect(instance -> Arrays.equals(read.get(instance), bytes.get(instance)));
}
@Override
public void setConverter(IOFunction<ReaderInstance<T>, T> converter) {
this.converter = converter;
}
@Override
public ReaderInstance<T> createInstance() {
return new Instance();
}
protected class Instance implements ReaderInstance<T> {
private List<Operation> operations;
private Map<Operation, StackTraceElement[]> stackTraces;
private int idx;
private Map<Ref<?>, Object> refValues;
private boolean finished;
private T value;
private Consumer<T> onFinished;
public Instance() {
this.stackTraces = new HashMap<>();
this.operations = new ArrayList<>(ReaderImpl.this.operations.size());
for(Operation op : ReaderImpl.this.operations) {
Operation copy = op.copy();
this.operations.add(copy);
this.stackTraces.put(copy, ReaderImpl.this.stackTraces.get(op));
}
this.refValues = new HashMap<>();
reset();
}
@Override
public boolean read(ByteBuffer buffer) throws IOException {
if(idx >= operations.size()) throw new IllegalStateException("Read after finished");
while(idx < operations.size()) {
try {
Operation operation = operations.get(idx);
if(operation.read(this, buffer)) {
idx++;
}else if(!buffer.hasRemaining()) break;
}catch(Exception e) {
IOException ex = new IOException("Operation at index " + idx + " failed", e);
ex.setStackTrace(stackTraces.get(operations.get(idx)));
throw ex;
}
}
if(idx == operations.size()) {
finished();
return true;
}
return false;
}
@Override
public ReaderInstance<T> onFinished(Consumer<T> consumer) {
this.onFinished = consumer;
return this;
}
private void finished() throws IOException {
finished = true;
value = converter.apply(this);
if(onFinished != null) onFinished.accept(value);
}
@Override
public T get() throws IllegalStateException {
if(!finished) throw new IllegalStateException("Reader is not finished");
return value;
}
@Override
public <R> void setRef(SimpleRef<R> ref, R value) {
refValues.put(ref, value);
}
@SuppressWarnings("unchecked")
@Override
public <R> R getRef(SimpleRef<R> ref) throws IllegalStateException {
if(!refValues.containsKey(ref)) throw new IllegalStateException("Tried to access ref before it was set (make sure you only call get() in a callback)");
return (R) refValues.get(ref);
}
@Override
public boolean isRefSet(SimpleRef<?> ref) {
return refValues.containsKey(ref);
}
@Override
public void reset() {
for(Operation op : operations) op.reset();
this.idx = 0;
this.refValues.clear();
this.finished = false;
this.value = null;
}
}
}

View File

@ -0,0 +1,23 @@
package me.mrletsplay.simplenio.reader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.function.Consumer;
public interface ReaderInstance<T> {
public boolean read(ByteBuffer buf) throws IOException;
public ReaderInstance<T> onFinished(Consumer<T> consumer);
public T get() throws IllegalStateException;
public <R> void setRef(SimpleRef<R> ref, R value);
public <R> R getRef(SimpleRef<R> ref) throws IllegalStateException;
public boolean isRefSet(SimpleRef<?> ref);
public void reset();
}

View File

@ -0,0 +1,52 @@
package me.mrletsplay.simplenio.reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
/**
* Readonly representation of a reference.
* @param <T> The referenced type
*/
public interface Ref<T> {
public T get(ReaderInstance<?> instance) throws IllegalStateException;
public default <O> Ref<O> map(Function<T, O> map) {
return instance -> map.apply(get(instance));
}
public default boolean isSet(ReaderInstance<?> instance) {
try {
get(instance);
return true;
}catch(IllegalStateException e) {
return false;
}
}
public default T getOrElse(ReaderInstance<?> instance, T other) {
try {
return get(instance);
}catch(IllegalStateException e) {
return other;
}
}
public static Ref<String> asString(Ref<byte[]> bytes, Charset charset) {
return bytes.map(b -> new String(b, charset));
}
public static Ref<String> asString(Ref<byte[]> bytes) {
return asString(bytes, StandardCharsets.UTF_8);
}
public static Ref<byte[]> asBytes(Ref<String> string, Charset charset) {
return string.map(s -> s.getBytes(charset));
}
public static Ref<byte[]> asBytes(Ref<String> string) {
return asBytes(string, StandardCharsets.UTF_8);
}
}

View File

@ -0,0 +1,31 @@
package me.mrletsplay.simplenio.reader;
public class SimpleRef<T> implements Ref<T> {
private SimpleRef() {}
public void set(ReaderInstance<?> instance, T value) {
instance.setRef(this, value);
}
@Override
public boolean isSet(ReaderInstance<?> instance) {
return instance.isRefSet(this);
}
@Override
public T get(ReaderInstance<?> instance) throws IllegalStateException {
return instance.getRef(this);
}
@Override
public T getOrElse(ReaderInstance<?> instance, T other) {
if(!instance.isRefSet(this)) return other;
return get(instance);
}
public static <T> SimpleRef<T> create() {
return new SimpleRef<>();
}
}

View File

@ -0,0 +1,9 @@
package me.mrletsplay.simplenio.util;
import java.io.IOException;
public interface IOConsumer<T> {
public void accept(T value) throws IOException;
}

View File

@ -0,0 +1,9 @@
package me.mrletsplay.simplenio.util;
import java.io.IOException;
public interface IOFunction<I, O> {
public O apply(I i) throws IOException;
}

View File

@ -0,0 +1,9 @@
package me.mrletsplay.simplenio.util;
import java.io.IOException;
public interface IORunnable {
public void run() throws IOException;
}

View File

@ -0,0 +1,9 @@
package me.mrletsplay.simplenio.util;
import java.io.IOException;
public interface IOSupplier<T> {
public T get() throws IOException;
}

View File

@ -0,0 +1,6 @@
module me.mrletsplay.simplenio {
exports me.mrletsplay.simplenio.reader;
exports me.mrletsplay.simplenio.util;
requires transitive me.mrletsplay.mrcore;
}

View File

@ -0,0 +1,12 @@
package me.mrletsplay.simplenio;
import org.junit.jupiter.api.Test;
public class ReaderTest {
@Test
public void testReader() {
}
}