001/* 002 * Copyright 2022-2026 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet; 018 019import org.jspecify.annotations.NonNull; 020import org.jspecify.annotations.Nullable; 021 022import javax.annotation.concurrent.NotThreadSafe; 023import javax.annotation.concurrent.ThreadSafe; 024 025import static java.util.Objects.requireNonNull; 026 027/** 028 * Options for non-network {@link Simulator} execution. 029 * 030 * @author <a href="https://www.revetkn.com">Mark Allen</a> 031 */ 032@ThreadSafe 033public final class SimulatorOptions { 034 @NonNull 035 private static final Integer DEFAULT_STREAMING_RESPONSE_BODY_LIMIT_IN_BYTES; 036 @NonNull 037 private static final SimulatorOptions DEFAULT_INSTANCE; 038 039 static { 040 DEFAULT_STREAMING_RESPONSE_BODY_LIMIT_IN_BYTES = 1_024 * 1_024 * 10; 041 DEFAULT_INSTANCE = builder().build(); 042 } 043 044 @NonNull 045 private final Integer streamingResponseBodyLimitInBytes; 046 047 /** 048 * Acquires a builder for {@link SimulatorOptions}. 049 * 050 * @return the builder 051 */ 052 @NonNull 053 public static Builder builder() { 054 return new Builder(); 055 } 056 057 /** 058 * Acquires the default simulator options. 059 * 060 * @return the default simulator options 061 */ 062 @NonNull 063 public static SimulatorOptions defaultInstance() { 064 return DEFAULT_INSTANCE; 065 } 066 067 protected SimulatorOptions(@NonNull Builder builder) { 068 requireNonNull(builder); 069 070 this.streamingResponseBodyLimitInBytes = builder.streamingResponseBodyLimitInBytes == null 071 ? DEFAULT_STREAMING_RESPONSE_BODY_LIMIT_IN_BYTES 072 : builder.streamingResponseBodyLimitInBytes; 073 074 if (this.streamingResponseBodyLimitInBytes < 0) 075 throw new IllegalArgumentException("Streaming response body limit must be >= 0"); 076 } 077 078 /** 079 * The maximum number of streaming response bytes the simulator may materialize. 080 * 081 * @return the maximum materialized streaming response bytes 082 */ 083 @NonNull 084 public Integer getStreamingResponseBodyLimitInBytes() { 085 return this.streamingResponseBodyLimitInBytes; 086 } 087 088 /** 089 * Builder for {@link SimulatorOptions}. 090 * <p> 091 * This class is intended for use by a single thread. 092 */ 093 @NotThreadSafe 094 public static final class Builder { 095 @Nullable 096 private Integer streamingResponseBodyLimitInBytes; 097 098 private Builder() { 099 // No-op 100 } 101 102 /** 103 * Sets the maximum number of streaming response bytes the simulator may materialize. 104 * 105 * @param streamingResponseBodyLimitInBytes the maximum number of bytes, or {@code null} for the default 106 * @return this builder 107 */ 108 @NonNull 109 public Builder streamingResponseBodyLimitInBytes(@Nullable Integer streamingResponseBodyLimitInBytes) { 110 this.streamingResponseBodyLimitInBytes = streamingResponseBodyLimitInBytes; 111 return this; 112 } 113 114 /** 115 * Builds a {@link SimulatorOptions} instance. 116 * 117 * @return simulator options 118 */ 119 @NonNull 120 public SimulatorOptions build() { 121 return new SimulatorOptions(this); 122 } 123 } 124}