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.Preconditions.require; 20 import static com.code_intelligence.jazzer.mutation.support.TypeSupport.asAnnotatedType; 21 import static java.lang.String.format; 22 23 import com.google.errorprone.annotations.CheckReturnValue; 24 import java.lang.reflect.AnnotatedType; 25 import java.util.Optional; 26 27 /** 28 * Instances of this class are not required to be thread safe, but are generally lightweight and can 29 * thus be created as needed. 30 */ 31 public abstract class MutatorFactory { canMutate(AnnotatedType type)32 public final boolean canMutate(AnnotatedType type) { 33 return tryCreate(type).isPresent(); 34 } 35 createOrThrow(Class<T> clazz)36 public final <T> SerializingMutator<T> createOrThrow(Class<T> clazz) { 37 return (SerializingMutator<T>) createOrThrow(asAnnotatedType(clazz)); 38 } 39 createOrThrow(AnnotatedType type)40 public final SerializingMutator<?> createOrThrow(AnnotatedType type) { 41 Optional<SerializingMutator<?>> maybeMutator = tryCreate(type); 42 require(maybeMutator.isPresent(), "Failed to create mutator for " + type); 43 return maybeMutator.get(); 44 } 45 createInPlaceOrThrow(AnnotatedType type)46 public final SerializingInPlaceMutator<?> createInPlaceOrThrow(AnnotatedType type) { 47 Optional<SerializingInPlaceMutator<?>> maybeMutator = tryCreateInPlace(type); 48 require(maybeMutator.isPresent(), "Failed to create mutator for " + type); 49 return maybeMutator.get(); 50 } 51 52 /** 53 * Tries to create a mutator for {@code type} and, if successful, asserts that it is an instance 54 * of {@link SerializingInPlaceMutator}. 55 */ tryCreateInPlace(AnnotatedType type)56 public final Optional<SerializingInPlaceMutator<?>> tryCreateInPlace(AnnotatedType type) { 57 return tryCreate(type).map(mutator -> { 58 require(mutator instanceof InPlaceMutator<?>, 59 format("Mutator for %s is not in-place: %s", type, mutator.getClass())); 60 return (SerializingInPlaceMutator<?>) mutator; 61 }); 62 } 63 64 @CheckReturnValue tryCreate(AnnotatedType type)65 public final Optional<SerializingMutator<?>> tryCreate(AnnotatedType type) { 66 return tryCreate(type, this); 67 } 68 69 /** 70 * Attempt to create a {@link SerializingMutator} for the given type. 71 * 72 * @param type the type to mutate 73 * @param factory the factory to use when creating submutators 74 * @return a {@link SerializingMutator} for the given {@code type}, or {@link Optional#empty()} 75 * if this factory can't create such mutators 76 */ 77 @CheckReturnValue tryCreate( AnnotatedType type, MutatorFactory factory)78 public abstract Optional<SerializingMutator<?>> tryCreate( 79 AnnotatedType type, MutatorFactory factory); 80 } 81