using System.Runtime.CompilerServices;

namespace AyCode.Core.Serializers.Binaries;

/// <summary>
/// Abstract base interface for binary input implementations.
/// Provides only the buffer management strategy (initialize/advance) — all read methods live in
/// BinaryDeserializationContext which owns the _buffer/_position state for zero virtual dispatch.
///
/// Mirrors IBinaryOutputBase pattern from the serializer side.
///
/// Derived structs implement:
/// - Initialize: provide the initial buffer, position, and length
/// - TryAdvanceSegment: handle buffer exhaustion (return false for single-buffer, advance for multi-segment)
/// </summary>
public interface IBinaryInputBase
{
    /// <summary>
    /// Provides the initial buffer, starting position, and buffer length.
    /// Called once before deserialization begins.
    /// For ArrayBinaryInput: sets buffer = byte[], position = 0, bufferLength = data.Length.
    /// For SequenceBinaryInput: sets buffer to first segment's array, position/length to segment bounds.
    /// </summary>
    void Initialize(out byte[] buffer, out int position, out int bufferLength);

    /// <summary>
    /// Called when the context's buffer cannot satisfy 'needed' more bytes. Cold path only.
    /// Returns true if more data is available (segment advanced), false if end of input.
    /// For ArrayBinaryInput: always returns false (single contiguous buffer).
    /// For SequenceBinaryInput: advances to next segment, handles cross-boundary reads.
    /// </summary>
    [MethodImpl(MethodImplOptions.NoInlining)]
    bool TryAdvanceSegment(ref byte[] buffer, ref int position, ref int bufferLength, int needed);

    /// <summary>
    /// Releases any rented buffers (e.g. ArrayPool scratch in SequenceBinaryInput).
    /// Must be called after deserialization completes.
    /// For ArrayBinaryInput: no-op.
    /// </summary>
    void Release();
}
