From 31b424d2050e38184db3740bc2550014d4a53b69 Mon Sep 17 00:00:00 2001 From: Emma Tebibyte Date: Mon, 27 Oct 2025 23:37:11 -0600 Subject: [PATCH] libdelimit: initial commit --- src/libdelimit.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/libdelimit.rs diff --git a/src/libdelimit.rs b/src/libdelimit.rs new file mode 100644 index 0000000..6e648cf --- /dev/null +++ b/src/libdelimit.rs @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2025 Emma Tebibyte + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +use std::{ + io::{ Read, Result, stdin }, + mem::self, + process::ExitCode, +}; + +const BUFFER_SIZE: usize = 4096; + +struct Delimited { + stream: Box, + delimiter: Vec, + buffer: Vec +} + +impl Delimited { + fn new(stream: Box, delimiter: &[u8]) -> Self { + Delimited { + stream, + delimiter: delimiter.to_vec(), + buffer: Vec::with_capacity(BUFFER_SIZE), + } + } +} + +impl Iterator for Delimited { + type Item = Result>; + + fn next(&mut self) -> Option { + let mut buf = [0; BUFFER_SIZE]; + + loop { + if let Some(p) = find_subslice(&self.buffer, &self.delimiter) { + let chunk = self.buffer.drain(..p).collect::>(); + + let _ = self.buffer.drain(..self.delimiter.len()); + + return Some(Ok(chunk)); + } + + match self.stream.read(&mut buf) { + Ok(0) => { + if self.buffer.is_empty() { + return None; + } + + return Some(Ok(mem::take(&mut self.buffer))); + }, + Ok(n) => { + let content = &buf[..n]; + self.buffer.extend_from_slice(&content); + }, + Err(e) => { + return Some(Err(e)); + }, + } + } + } +} + +fn find_subslice(stack: &[u8], key: &[u8]) -> Option { + if key.len() == 1 { + return stack.iter().position(|&b| b == key[0]); + } + if key.len() > stack.len() { + return None; + } + for i in 0..=stack.len() - key.len() { + if &stack[i..i + key.len()] == key { + return Some(i); + } + } + + None +}