// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
/// This type is for internal use only,
/// end users should not use this type directly.
#internal(internal, "this type is for internal use only")
struct ReaderBuffer(@io_buffer.Buffer)

///|
#internal(internal, "this function is for internal use only")
pub fn ReaderBuffer::new() -> ReaderBuffer {
  @io_buffer.new(0)
}

///|
async fn[R : Reader] ReaderBuffer::try_ensure(
  self : Self,
  len : Int,
  reader~ : R,
) -> Bool {
  if self.len >= len {
    return true
  }
  self.0.enlarge_to(len)
  let capacity = self.buf.length()
  while self.len < len {
    let offset = self.start + self.len
    let n = reader._direct_read(self.buf, offset~, max_len=capacity - offset)
    if n == 0 {
      return false
    }
    self.len += n
  } nobreak {
    true
  }
}

///|
async fn[R : Reader] ReaderBuffer::find_opt(
  self : Self,
  target : Bytes,
  reader~ : R,
) -> Int? {
  let target_len = target.length()
  for searched = 0 {
    guard self.try_ensure(searched + target_len, reader~) else { return None }
    let len = self.len
    let start = self.start + searched
    let end = self.start + len
    let region = self.buf.unsafe_reinterpret_as_bytes()[start:end]
    if region.find(target) is Some(i) {
      return Some(searched + i)
    }
    continue len - target_len + 1
  }
}