| /* |
| * Copyright 2023 Code Intelligence GmbH |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.code_intelligence.jazzer.mutation.api; |
| |
| import static com.code_intelligence.jazzer.mutation.support.InputStreamSupport.extendWithZeros; |
| |
| import com.google.errorprone.annotations.CheckReturnValue; |
| import java.io.DataInputStream; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| |
| /** |
| * Serializes and deserializes values of type {@code T>} to and from (in-memory or on disk) corpus |
| * entries. |
| * |
| * <p>Binary representations must by default be self-delimiting. For variable-length types, the |
| * {@link #readExclusive(InputStream)} and {@link #writeExclusive(Object, OutputStream)} methods can |
| * optionally be overriden to implement more compact representations that align with existing binary |
| * corpus entries. For example, a {@code Serializer<byte[]>} could implement these optional methods |
| * to read and write the raw bytes without preceding length information whenever it is used in an |
| * already delimited context. |
| */ |
| public interface Serializer<T> extends Detacher<T> { |
| /** |
| * Reads a {@code T} from an endless stream that is eventually 0. |
| * |
| * <p>Implementations |
| * <ul> |
| * <li>MUST not attempt to consume the entire stream; |
| * <li>MUST return a valid {@code T} and not throw for any (even garbage) stream; |
| * <li>SHOULD short-circuit the creation of nested structures upon reading null bytes. |
| * </ul> |
| * |
| * @param in an endless stream that eventually only reads null bytes |
| * @return a {@code T} constructed from the bytes read |
| * @throws IOException declared, but must not be thrown by implementations unless methods called |
| * on {@code in} do |
| */ |
| @CheckReturnValue T read(DataInputStream in) throws IOException; |
| |
| /** |
| * Writes a {@code T} to a stream in such a way that an equal object can be recovered from the |
| * written bytes via {@link #read(DataInputStream)}. |
| * |
| * <p>Since {@link #read(DataInputStream)} is called with an endless stream, the binary |
| * representation MUST be self-delimiting. For example, when writing out a list, first write its |
| * length. |
| * |
| * @param value the value to write |
| * @param out the stream to write to |
| * @throws IOException declared, but must not be thrown by implementations unless methods called |
| * on {@code out} do |
| */ |
| void write(T value, DataOutputStream out) throws IOException; |
| |
| /** |
| * Reads a {@code T} from a finite stream, potentially using a simpler representation than that |
| * read by {@link #read(DataInputStream)}. |
| * |
| * <p>The default implementations call extends the stream with null bytes and then calls |
| * {@link #read(DataInputStream)}. |
| * |
| * <p>Implementations |
| * <ul> |
| * <li>MUST return a valid {@code T} and not throw for any (even garbage) stream; |
| * <li>SHOULD short-circuit the creation of nested structures upon reading null bytes; |
| * <li>SHOULD naturally consume the entire stream. |
| * </ul> |
| * |
| * @param in a finite stream |
| * @return a {@code T} constructed from the bytes read |
| * @throws IOException declared, but must not be thrown by implementations unless methods called |
| * on {@code in} do |
| */ |
| @CheckReturnValue |
| default T readExclusive(InputStream in) throws IOException { |
| return read(new DataInputStream(extendWithZeros(in))); |
| } |
| |
| /** |
| * Writes a {@code T} to a stream in such a way that an equal object can be recovered from the |
| * written bytes via {@link #readExclusive(InputStream)}. |
| * |
| * <p>The default implementations calls through to {@link #read(DataInputStream)} and should only |
| * be overriden if {@link #readExclusive(InputStream)} is. |
| * |
| * <p>As opposed to {@link #read(DataInputStream)}, {@link #readExclusive(InputStream)} is called |
| * with a finite stream. The binary representation of a {@code T} value thus does not have to be |
| * self-delimiting, which can allow for simpler representations. For example, a {@code byte[]} can |
| * be written to the stream without prepending its length. |
| * |
| * @param value the value to write |
| * @param out the stream to write to |
| * @throws IOException declared, but must not be thrown by implementations unless methods called |
| * on {@code out} do |
| */ |
| default void writeExclusive(T value, OutputStream out) throws IOException { |
| write(value, new DataOutputStream(out)); |
| } |
| } |