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;
020
021import javax.annotation.concurrent.NotThreadSafe;
022import java.io.IOException;
023import java.nio.ByteBuffer;
024
025/**
026 * Writable byte sink for a streaming HTTP response.
027 * <p>
028 * This type is intentionally not thread-safe. A stream must have one active writer at a time; applications that
029 * produce bytes from multiple threads should serialize those writes before calling this API.
030 *
031 * @author <a href="https://www.revetkn.com">Mark Allen</a>
032 */
033@NotThreadSafe
034public interface ResponseStream {
035        /**
036         * Writes bytes to the response stream.
037         * <p>
038         * Implementations copy the provided bytes before this method returns.
039         *
040         * @param bytes the bytes to write
041         * @throws IOException if the bytes cannot be written
042         * @throws InterruptedException if the writer is interrupted while waiting for stream capacity
043         * @throws StreamingResponseCanceledException if the stream has been canceled
044         */
045        void write(@NonNull byte[] bytes) throws IOException, InterruptedException, StreamingResponseCanceledException;
046
047        /**
048         * Writes the remaining bytes of a byte buffer to the response stream without mutating the caller's buffer.
049         * <p>
050         * Implementations copy the remaining bytes before this method returns.
051         *
052         * @param byteBuffer the byte buffer to write
053         * @throws IOException if the bytes cannot be written
054         * @throws InterruptedException if the writer is interrupted while waiting for stream capacity
055         * @throws StreamingResponseCanceledException if the stream has been canceled
056         */
057        void write(@NonNull ByteBuffer byteBuffer) throws IOException, InterruptedException, StreamingResponseCanceledException;
058
059        /**
060         * Hints that buffered bytes should be made available to the transport promptly.
061         * <p>
062         * Calling this method is not required for correctness. Soklet flushes any remaining bytes when the stream completes.
063         *
064         * @throws IOException if the stream cannot be flushed
065         * @throws InterruptedException if the writer is interrupted while waiting for stream capacity
066         * @throws StreamingResponseCanceledException if the stream has been canceled
067         */
068        void flush() throws IOException, InterruptedException, StreamingResponseCanceledException;
069
070        /**
071         * Is this stream currently open for writes?
072         *
073         * @return {@code true} if open
074         */
075        @NonNull
076        Boolean isOpen();
077}