1 /*
2  * Copyright 2023 Code Intelligence GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.code_intelligence.jazzer.mutation.api;
18 
19 import static com.code_intelligence.jazzer.mutation.support.ExceptionSupport.asUnchecked;
20 
21 import com.google.errorprone.annotations.ForOverride;
22 import java.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 
26 /**
27  * Combines an {@link InPlaceMutator} with a {@link Serializer} for objects of type {@code T}.
28  *
29  * <p>If {@code T} can't be mutated in place, implement {@link SerializingMutator} instead.
30  *
31  * <p>Implementing classes SHOULD be declared final.
32  */
33 public abstract class SerializingInPlaceMutator<T>
34     extends SerializingMutator<T> implements InPlaceMutator<T> {
35   // ByteArrayInputStream#close is documented as being a no-op, so it is safe to reuse an instance
36   // here.
37   // TODO: Introduce a dedicated empty InputStream implementation.
38   private static final InputStream emptyInputStream = new ByteArrayInputStream(new byte[0]);
39 
40   /**
41    * Constructs a default instance of {@code T}.
42    *
43    * <p>The returned value is immediately passed to {@link #initInPlace(Object, PseudoRandom)}.
44    *
45    * <p>Implementing classes SHOULD provide a more efficient implementation.
46    *
47    * @return a default instance of {@code T}
48    */
49   @ForOverride
makeDefaultInstance()50   protected T makeDefaultInstance() {
51     try {
52       return readExclusive(emptyInputStream);
53     } catch (IOException e) {
54       throw asUnchecked(e);
55     }
56   }
57 
58   @Override
init(PseudoRandom prng)59   public final T init(PseudoRandom prng) {
60     T value = makeDefaultInstance();
61     initInPlace(value, prng);
62     return value;
63   }
64 
65   @Override
mutate(T value, PseudoRandom prng)66   public final T mutate(T value, PseudoRandom prng) {
67     mutateInPlace(value, prng);
68     return value;
69   }
70 
71   @Override
crossOver(T value, T otherValue, PseudoRandom prng)72   public final T crossOver(T value, T otherValue, PseudoRandom prng) {
73     crossOverInPlace(value, otherValue, prng);
74     return value;
75   }
76 }
77