// 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.
///|
/// A reader based on a string
struct StringReader {
mut closed : Bool
mut buffer : StringView
}
///|
/// Creates a new StringReader based on a string
pub fn string_reader(string : String) -> StringReader {
{ closed: false, buffer: string.view() }
}
///|
pub impl Closable for StringReader with close(self) {
self.closed = true
}
///|
pub impl Reader for StringReader with read(self, builder, max_len?) {
@promise.spawn(fn() {
guard !self.closed else { fail("EOF") }
if self.buffer is [] {
return None
} else if max_len is Some(max_len) &&
self.buffer.offset_of_nth_char(max_len) is Some(index) {
builder.write_substring(
self.buffer.data(),
self.buffer.start_offset(),
index,
)
self.buffer = self.buffer.view(start_offset=index)
Some(())
} else {
builder.write_substring(
self.buffer.data(),
self.buffer.start_offset(),
self.buffer.length(),
)
self.buffer = "".view()
Some(())
}
})
}
///|
test "string reader" {
@promise.spawn(fn() {
try {
let reader = string_reader("asdf")
let builder = StringBuilder::new()
guard reader.read(builder, max_len=0).await() is Some(_)
inspect(builder, content="")
guard reader.read(builder, max_len=2).await() is Some(_)
inspect(builder, content="as")
guard reader.read(builder, max_len=10).await() is Some(_)
inspect(builder, content="asdf")
guard reader.read(builder, max_len=10).await() is None
} catch {
InspectError(e) => {
println(e)
panic()
}
e => {
println(e)
panic()
}
}
})
|> ignore
}