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}