diff --git a/README.md b/README.md index a2cadff..73868ef 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,8 @@ # record-net -Simple, performant message library for Java, using records. +Simple, performant message library for Java, using records. It allows you to +serialize and deserialize records and their contents for use in network or +filesystem IO. -record-net gives you the advantages of reflection, without the runtime costs. By registering message types before starting your work, record-net is able to generate custom serializers and deserializers for all registered message types, which translates to read and write speeds that are nearly equivalent to directly writing bytes to a stream. -Here's an example of how you can use record-net: -```java -import com.andrewlalis.record_net.Message; -import com.andrewlalis.record_net.impl.TypeMappedSerializer; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.Socket; - -class Example { - record ChatMessage( - long timestamp, - String username, - String msg - ) implements Message { - } - - public static void main(String[] args) throws IOException { - var ser = new TypeMappedSerializer(); - ser.registerType(1, ChatMessage.class); - var socket = new Socket("127.0.0.1", 8081); - var bOut = new ByteArrayOutputStream(); - var msg = new ChatMessage( - System.currentTimeMillis(), - "andrew", - "Hello world!" - ); - ser.writeMessage(msg, socket.getOutputStream()); - ChatMessage response = (ChatMessage) ser.readMessage(socket.getInputStream()); - } -} -``` - -## Get record-net -This project is published as a package on GitHub. You can view available packages [here](https://github.com/andrewlalis/record-net/packages). Alternatively, [you can get this project on jitpack.io](https://jitpack.io/#andrewlalis/record-net). +## Example diff --git a/pom.xml b/pom.xml index 82f833d..fe646b9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.andrewlalis record-net - 2.0.0 + 1.0.0-SNAPSHOT Record-Net A simple library for reading and writing records deterministically and efficiently. https://github.com/andrewlalis/record-net @@ -35,24 +35,121 @@ - - - - github - Github record-net Apache Maven Packages - https://maven.pkg.github.com/andrewlalis/record-net - - + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.1.0 + + + sign-artifacts + verify + + sign + + + + + + net.ju-n.maven.plugins + checksum-maven-plugin + 1.4 + + + checksum-maven-plugin-files + verify + + files + + + + + + + ${project.build.directory} + + *.pom + *.jar + + + + + SHA-1 + MD5 + SHA-256 + SHA-512 + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://s01.oss.sonatype.org + false + + + + https://github.com/andrewlalis/record-net + scm:git:git://github.com/andrewlalis/record-net.git + scm:git:ssh://github.com:andrewlalis/record-net.git MIT License - https://github.com/andrewlalis/record-net/blob/main/LICENSE - repo + https://www.opensource.org/licenses/mit-license.php + + + + Andrew Lalis + andrewlalisofficial@gmail.com + + + + + + ossrh + https://s01.oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + \ No newline at end of file diff --git a/src/main/java/com/andrewlalis/record_net/IOUtil.java b/src/main/java/com/andrewlalis/record_net/IOUtil.java index 38c7225..6d43513 100644 --- a/src/main/java/com/andrewlalis/record_net/IOUtil.java +++ b/src/main/java/com/andrewlalis/record_net/IOUtil.java @@ -6,6 +6,10 @@ import java.io.IOException; import java.lang.reflect.Array; import java.util.UUID; +/** + * A utility class that contains functions for IO operations on certain data + * types. It cannot be instantiated; use its static methods only. + */ public final class IOUtil { private IOUtil() {} diff --git a/src/main/java/com/andrewlalis/record_net/RecordInfo.java b/src/main/java/com/andrewlalis/record_net/RecordInfo.java index 5af4af0..67d6e4b 100644 --- a/src/main/java/com/andrewlalis/record_net/RecordInfo.java +++ b/src/main/java/com/andrewlalis/record_net/RecordInfo.java @@ -3,7 +3,20 @@ package com.andrewlalis.record_net; import java.lang.reflect.Constructor; import java.lang.reflect.RecordComponent; +/** + * A collection of the information that's needed about a record in order to + * serialize and deserialize it at runtime. + * @param components The record's ordered array of components. + * @param constructor The canonical constructor for the record. + * @param The type of the record. + */ record RecordInfo(RecordComponent[] components, Constructor constructor) { + /** + * Prepares an instance of RecordInfo for a given record class. + * @param type The record class. + * @return The RecordInfo object. + * @param The type of the record. + */ public static RecordInfo forType(Class type) { if (!type.isRecord()) throw new IllegalArgumentException(type + " is not a record."); RecordComponent[] c = type.getRecordComponents(); @@ -18,6 +31,4 @@ record RecordInfo(RecordComponent[] components, Constructor constructor) { throw new RuntimeException(e); } } - - } diff --git a/src/main/java/com/andrewlalis/record_net/RecordMappedSerializer.java b/src/main/java/com/andrewlalis/record_net/RecordMappedSerializer.java index 8dbbcb0..b40917c 100644 --- a/src/main/java/com/andrewlalis/record_net/RecordMappedSerializer.java +++ b/src/main/java/com/andrewlalis/record_net/RecordMappedSerializer.java @@ -6,11 +6,21 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +/** + * The default {@link RecordSerializer} implementation that performs + * serialization and deserialization using a set of pre-registered, known + * record types. + */ public class RecordMappedSerializer implements RecordSerializer { private final Map> messageTypes = new HashMap<>(); private final Map, Integer> messageTypeIds = new HashMap<>(); private final Map, RecordInfo> messageRecordInfo = new HashMap<>(); + /** + * Registers a new record class to this serializer. + * @param id The id to assign to this type. + * @param type The record class. + */ public void registerType(int id, Class type) { if (!type.isRecord()) throw new IllegalArgumentException("Only records are permitted."); this.messageTypes.put(id, type); @@ -18,6 +28,20 @@ public class RecordMappedSerializer implements RecordSerializer { this.messageRecordInfo.put(type, RecordInfo.forType(type)); } + /** + * Registers a new record class to this serializer, using the class' hash + * code as its id. + * @param type The record class. + */ + public void registerType(Class type) { + this.registerType(type.hashCode(), type); + } + + /** + * Checks if a certain class has been registered for use with this serializer. + * @param type The type to check. + * @return True if the type is registered and may be used, or false otherwise. + */ public boolean isTypeSupported(Class type) { return messageTypeIds.containsKey(type); } @@ -62,7 +86,10 @@ public class RecordMappedSerializer implements RecordSerializer { if (type.equals(UUID.class)) { return IOUtil.readUUID(dIn); } - return IOUtil.readPrimitive(type, dIn); + if (type.isPrimitive()) { + return IOUtil.readPrimitive(type, dIn); + } + throw new UnsupportedMessageTypeException(type); } @Override diff --git a/src/main/java/com/andrewlalis/record_net/RecordSerializer.java b/src/main/java/com/andrewlalis/record_net/RecordSerializer.java index f91b1fe..a1db825 100644 --- a/src/main/java/com/andrewlalis/record_net/RecordSerializer.java +++ b/src/main/java/com/andrewlalis/record_net/RecordSerializer.java @@ -4,7 +4,25 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +/** + * Defines the basic interface for serialization and deserialization of + * messages to and from streams. + * @see RecordMappedSerializer + */ public interface RecordSerializer { + /** + * Reads a message from an input stream. + * @param in The input stream to read from. + * @return The object that was read. + * @throws IOException If an error occurs. + */ Object readMessage(InputStream in) throws IOException; + + /** + * Writes a message to an output stream. + * @param msg The message to write. + * @param out The output stream to write to. + * @throws IOException If an error occurs. + */ void writeMessage(Object msg, OutputStream out) throws IOException; } diff --git a/src/main/java/com/andrewlalis/record_net/UnknownMessageIdException.java b/src/main/java/com/andrewlalis/record_net/UnknownMessageIdException.java index d155d22..9ffa68c 100644 --- a/src/main/java/com/andrewlalis/record_net/UnknownMessageIdException.java +++ b/src/main/java/com/andrewlalis/record_net/UnknownMessageIdException.java @@ -1,8 +1,19 @@ package com.andrewlalis.record_net; +/** + * An exception that's thrown when a {@link RecordSerializer} reads a message + * whose id is unknown (not previously registered with the serializer). + */ public class UnknownMessageIdException extends RuntimeException { + /** + * The id of the message as it was received. + */ public final int messageId; + /** + * Constructs the exception with a given id. + * @param messageId The id of the message. + */ public UnknownMessageIdException(int messageId) { super("Unknown record-net message id " + messageId); this.messageId = messageId; diff --git a/src/main/java/com/andrewlalis/record_net/UnsupportedMessageTypeException.java b/src/main/java/com/andrewlalis/record_net/UnsupportedMessageTypeException.java index 459c5d0..a23f81e 100644 --- a/src/main/java/com/andrewlalis/record_net/UnsupportedMessageTypeException.java +++ b/src/main/java/com/andrewlalis/record_net/UnsupportedMessageTypeException.java @@ -1,16 +1,22 @@ package com.andrewlalis.record_net; +/** + * An exception that's thrown when attempting to serialize or deserialize an + * unsupported type. Unsupported types are any complex types not registered + * with a serializer, or unsupported by {@link IOUtil}. + */ public class UnsupportedMessageTypeException extends RuntimeException { + /** + * The type that's not supported. + */ public Class messageType; - public int messageId; + /** + * Constructs a new exception with the given type. + * @param messageType The unsupported type. + */ public UnsupportedMessageTypeException(Class messageType) { super("The message type " + messageType.getSimpleName() + " is not supported."); this.messageType = messageType; } - - public UnsupportedMessageTypeException(int messageId) { - super("The message with id " + messageId + " is not supported."); - this.messageId = messageId; - } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 3a4b7f8..0260626 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,3 +1,6 @@ +/** + * The record_net module definition. + */ module com.andrewlalis.record_net { exports com.andrewlalis.record_net; } \ No newline at end of file