Default implementations of streams

This commit is contained in:
Andrew Golovashevich 2025-11-12 20:02:39 +03:00
parent 1545ed40e7
commit 28d44f907c
14 changed files with 573 additions and 29 deletions

4
.gitignore vendored
View File

@ -1,3 +1,3 @@
/.idea
/target/*
/Cargo.lock
target/
Cargo.lock

View File

@ -0,0 +1,8 @@
[package]
name = "source-stream-0-default-streams-0"
edition = "2024"
[lib]
[dependencies]
source-stream-0 = { path = ".." }

View File

@ -0,0 +1,25 @@
use crate::iterators::StrSourceIterator;
use crate::pos::{NewLinePosCounter, PosLineCol};
use crate::{_CollectScopeContext, SourceIterator};
#[test]
fn sandbox() {
let mut z: StrSourceIterator<'_, '_, PosLineCol, NewLinePosCounter> =
StrSourceIterator::start("12\n34");
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
println!("{}", z.pos().col);
z.next();
return;
}

View File

@ -0,0 +1,26 @@
use source_stream_0::{CollectResult, CollectedSubstring, Pos};
pub trait PosCounter<'pos, C, P: Pos<'pos>> {
fn update(&mut self, c: Option<C>);
fn export(&self) -> P;
fn init() -> Self;
}
pub trait _CollectScopeContext<'source, C> {
fn next(&mut self) -> Option<C>;
fn current(&mut self) -> Option<C>;
}
pub trait SourceIterator<'source, 'pos, C, P: Pos<'pos>, CS: CollectedSubstring<'source, C>>:
_CollectScopeContext<'source, C>
{
fn pos(&self) -> P;
type CollectScopeContext: _CollectScopeContext<'source, C>;
fn collect(
&mut self,
scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool,
) -> CollectResult<CS>;
}

View File

@ -0,0 +1,128 @@
use crate::iterator::{_CollectScopeContext, PosCounter, SourceIterator};
use source_stream_0::{CollectResult, CollectedSubstring, Keyword, KeywordComparatorIterator, Pos};
use std::marker::PhantomData;
use std::slice::Iter;
enum _CurrentChar<C> {
UNINITIALIZED,
EOF,
Got(C),
}
pub struct ArrayCollectedSubstring<'source, C> {
pub slice: &'source [C],
}
impl<'source, C: Copy> CollectedSubstring<'source, C> for ArrayCollectedSubstring<'source, C> {
fn compareKeyword<'keyword>(&self, kw: impl Keyword<'keyword, C>) -> bool {
let mut kwi;
match kw.startComparation(self.slice.len()) {
None => return false,
Some(_kwi) => kwi = _kwi,
};
for c in self.slice.iter() {
if !kwi.consume(*c) {
return false;
}
}
return true;
}
}
pub struct ArraySourceIterator<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>> {
_source: &'source [C],
_iter: Iter<'source, C>,
_current: _CurrentChar<&'source C>,
_posRaw: usize,
_posHighlevel: PC,
__phantom1: PhantomData<&'pos ()>,
__phantom2: PhantomData<P>,
}
impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
ArraySourceIterator<'source, 'pos, C, P, PC>
{
pub fn start(arr: &'source [C]) -> ArraySourceIterator<'source, 'pos, C, P, PC> {
return ArraySourceIterator {
_source: arr,
_iter: arr.iter(),
_current: _CurrentChar::UNINITIALIZED,
_posRaw: 0,
_posHighlevel: PC::init(),
__phantom1: PhantomData::default(),
__phantom2: PhantomData::default(),
};
}
}
impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
_CollectScopeContext<'source, C> for ArraySourceIterator<'source, 'pos, C, P, PC>
{
fn next(&mut self) -> Option<C> {
match self._iter.next() {
None => {
if let _CurrentChar::Got(_) = self._current {
self._posHighlevel.update(None);
self._posRaw += 1;
}
self._current = _CurrentChar::EOF;
return None;
}
Some(c) => {
self._posHighlevel.update(Some(*c));
if let _CurrentChar::Got(_) = self._current {
self._posRaw += 1;
}
self._current = _CurrentChar::Got(c);
return Some(*c);
}
}
}
fn current(&mut self) -> Option<C> {
match self._current {
_CurrentChar::UNINITIALIZED => return self.next(),
_CurrentChar::EOF => return None,
_CurrentChar::Got(c) => return Some(*c),
}
}
}
impl<'source, 'pos, C: Copy, P: Pos<'pos>, PC: PosCounter<'pos, C, P>>
SourceIterator<'source, 'pos, C, P, ArrayCollectedSubstring<'source, C>>
for ArraySourceIterator<'source, 'pos, C, P, PC>
{
fn pos(&self) -> P {
return self._posHighlevel.export();
}
type CollectScopeContext = ArraySourceIterator<'source, 'pos, C, P, PC>;
fn collect(
&mut self,
scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool,
) -> CollectResult<ArrayCollectedSubstring<'source, C>> {
match self._current {
_CurrentChar::EOF => return CollectResult::EOF,
_CurrentChar::UNINITIALIZED => {}
_CurrentChar::Got(_) => {}
}
let startPosRaw = self._posRaw;
match scope(self) {
false => return CollectResult::NotMatches,
true => {
let slice: &'source [C];
match self._current {
_CurrentChar::EOF => slice = &self._source[startPosRaw..],
_CurrentChar::UNINITIALIZED => slice = &[],
_CurrentChar::Got(_) => slice = &self._source[startPosRaw..self._posRaw],
}
return CollectResult::Matches(ArrayCollectedSubstring { slice: slice });
}
}
}
}

View File

@ -0,0 +1,8 @@
mod str;
mod array;
pub use str::StrCollectedSubstring;
pub use str::StrSourceIterator;
pub use array::ArrayCollectedSubstring;
pub use array::ArraySourceIterator;

View File

@ -0,0 +1,137 @@
use crate::iterator::{_CollectScopeContext, PosCounter, SourceIterator};
use source_stream_0::{CollectResult, CollectedSubstring, Keyword, KeywordComparatorIterator, Pos};
use std::marker::PhantomData;
use std::str::CharIndices;
enum _CurrentChar {
UNINITIALIZED,
EOF,
Got(char),
}
pub struct StrCollectedSubstring<'source> {
pub slice: &'source str,
pub size: usize,
}
impl<'source> CollectedSubstring<'source, char> for StrCollectedSubstring<'source> {
fn compareKeyword<'keyword>(&self, kw: impl Keyword<'keyword, char>) -> bool {
let mut kwi;
match kw.startComparation(self.size) {
None => return false,
Some(_kwi) => kwi = _kwi,
};
for c in self.slice.chars() {
if !kwi.consume(c) {
return false;
}
}
return true;
}
}
pub struct StrSourceIterator<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>> {
_source: &'source str,
_iter: CharIndices<'source>,
_current: _CurrentChar,
_posRaw: usize,
_posCodePoints: usize,
_posHighlevel: PC,
__phantom1: PhantomData<&'pos ()>,
__phantom2: PhantomData<P>,
}
impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>>
StrSourceIterator<'source, 'pos, P, PC>
{
pub fn start(s: &'source str) -> StrSourceIterator<'source, 'pos, P, PC> {
return StrSourceIterator {
_source: s,
_iter: s.char_indices(),
_current: _CurrentChar::UNINITIALIZED,
_posRaw: 0,
_posCodePoints: 0,
_posHighlevel: PC::init(),
__phantom1: PhantomData::default(),
__phantom2: PhantomData::default(),
};
}
}
impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>> _CollectScopeContext<'source, char>
for StrSourceIterator<'source, 'pos, P, PC>
{
fn next(&mut self) -> Option<char> {
match self._iter.next() {
None => {
if let _CurrentChar::Got(_) = self._current {
self._posHighlevel.update(None);
self._posCodePoints += 1;
self._posRaw = self._source.len();
}
self._current = _CurrentChar::EOF;
return None;
}
Some((p, c)) => {
self._posRaw = p;
if let _CurrentChar::Got(_) = self._current {
self._posCodePoints += 1;
}
self._posHighlevel.update(Some(c));
self._current = _CurrentChar::Got(c);
return Some(c);
}
}
}
fn current(&mut self) -> Option<char> {
match self._current {
_CurrentChar::UNINITIALIZED => return self.next(),
_CurrentChar::EOF => return None,
_CurrentChar::Got(c) => return Some(c),
}
}
}
impl<'source, 'pos, P: Pos<'pos>, PC: PosCounter<'pos, char, P>>
SourceIterator<'source, 'pos, char, P, StrCollectedSubstring<'source>>
for StrSourceIterator<'source, 'pos, P, PC>
{
fn pos(&self) -> P {
return self._posHighlevel.export();
}
type CollectScopeContext = StrSourceIterator<'source, 'pos, P, PC>;
fn collect(
&mut self,
scope: impl FnOnce(&mut Self::CollectScopeContext) -> bool,
) -> CollectResult<StrCollectedSubstring<'source>> {
match self._current {
_CurrentChar::EOF => return CollectResult::EOF,
_CurrentChar::UNINITIALIZED => {}
_CurrentChar::Got(_) => {}
}
let startPosRaw = self._posRaw;
let startPosCodePoints = self._posCodePoints;
match scope(self) {
false => return CollectResult::NotMatches,
true => {
let slice: &'source str;
match self._current {
_CurrentChar::EOF => slice = &self._source[startPosRaw..],
_CurrentChar::UNINITIALIZED => slice = "",
_CurrentChar::Got(_) => slice = &self._source[startPosRaw..self._posRaw],
}
return CollectResult::Matches(StrCollectedSubstring {
slice: slice,
size: self._posCodePoints - startPosCodePoints,
});
}
}
}
}

View File

@ -0,0 +1,11 @@
mod iterator;
mod stream;
pub use iterator::PosCounter;
pub use iterator::SourceIterator;
pub use iterator::_CollectScopeContext;
pub use stream::SourceStreamOverIterator;
pub mod pos;
pub mod iterators;
mod _sandbox;

View File

@ -0,0 +1,19 @@
use crate::iterator::PosCounter;
pub struct IndexPosCounter {
index: usize,
}
impl<C> PosCounter<'static, C, usize> for IndexPosCounter {
fn update(&mut self, c: Option<C>) {
self.index += 1;
}
fn export(&self) -> usize {
return self.index;
}
fn init() -> Self {
return IndexPosCounter { index: 0 };
}
}

View File

@ -0,0 +1,6 @@
mod index;
mod newline;
pub use index::IndexPosCounter;
pub use newline::PosLineCol;
pub use newline::NewLinePosCounter;

View File

@ -0,0 +1,69 @@
use crate::iterator::PosCounter;
use source_stream_0::Pos;
pub struct PosLineCol {
pub row: usize,
pub col: usize,
}
impl Pos<'static> for PosLineCol {}
pub struct NewLinePosCounter {
row: usize,
col: usize,
}
impl NewLinePosCounter {
pub fn _update<C: PartialEq>(&mut self, actual: Option<C>, expected: C) {
match actual {
None => {}
Some(c) => {
if c == expected {
self.row += 1;
self.col = 0;
} else {
self.col += 1;
}
}
}
}
pub fn _export(&self) -> PosLineCol {
return PosLineCol {
row: self.row,
col: self.col,
};
}
pub fn _init() -> Self {
return NewLinePosCounter { row: 0, col: 0 };
}
}
impl PosCounter<'static, char, PosLineCol> for NewLinePosCounter {
fn update(&mut self, c: Option<char>) {
self._update(c, '\n')
}
fn export(&self) -> PosLineCol {
self._export()
}
fn init() -> Self {
return NewLinePosCounter::_init();
}
}
impl PosCounter<'static, u8, PosLineCol> for NewLinePosCounter {
fn update(&mut self, c: Option<u8>) {
self._update(c, b'\n')
}
fn export(&self) -> PosLineCol {
self._export()
}
fn init() -> Self {
return NewLinePosCounter::_init();
}
}

View File

@ -0,0 +1,106 @@
use crate::iterator::{_CollectScopeContext, SourceIterator};
use source_stream_0::{CollectResult, CollectedSubstring, Pos, Predicate, SourceStream};
use std::marker::PhantomData;
pub struct SourceStreamOverIterator<
'source,
'pos,
C,
P: Pos<'pos>,
CS: CollectedSubstring<'source, C>,
I: SourceIterator<'source, 'pos, C, P, CS>,
> {
_iter: I,
__phantom1: PhantomData<&'source ()>,
__phantom2: PhantomData<&'pos ()>,
__phantom3: PhantomData<C>,
__phantom4: PhantomData<P>,
__phantom5: PhantomData<CS>,
}
impl<
'source,
'pos,
C,
P: Pos<'pos>,
CS: CollectedSubstring<'source, C>,
I: SourceIterator<'source, 'pos, C, P, CS>,
> SourceStreamOverIterator<'source, 'pos, C, P, CS, I>
{
fn wrap(iter: I) -> SourceStreamOverIterator<'source, 'pos, C, P, CS, I> {
return SourceStreamOverIterator {
_iter: iter,
__phantom1: PhantomData::default(),
__phantom2: PhantomData::default(),
__phantom3: PhantomData::default(),
__phantom4: PhantomData::default(),
__phantom5: PhantomData::default(),
};
}
}
impl<
'source,
'pos,
C,
P: Pos<'pos>,
CS: CollectedSubstring<'source, C>,
I: SourceIterator<'source, 'pos, C, P, CS>,
> SourceStream<'source, 'pos, C, P, CS> for SourceStreamOverIterator<'source, 'pos, C, P, CS, I>
{
fn skip(&mut self, predicate: &mut impl Predicate<C>) -> bool {
match self._iter.current() {
Some(c) => match predicate.check(c) {
false => return false,
true => {}
},
None => return true,
}
loop {
match self._iter.next() {
None => return true,
Some(c) => match predicate.check(c) {
true => continue,
false => return false,
},
}
}
}
fn collect(&mut self, predicate: &mut impl Predicate<C>) -> CollectResult<CS> {
return self._iter.collect(|iter| {
match iter.current() {
Some(c) => match predicate.check(c) {
false => return false,
true => {}
},
None => return false,
}
loop {
match iter.next() {
None => {
return true;
}
Some(c) => match predicate.check(c) {
true => continue,
false => return true,
},
}
}
});
}
fn pos(&self) -> P {
return self._iter.pos();
}
fn currentChar(&mut self) -> Option<C> {
return self._iter.current();
}
fn nextChar(&mut self) -> Option<C> {
return self._iter.next();
}
}

View File

@ -1,17 +1,17 @@
use std::slice::Iter;
use std::str::Chars;
impl crate::_KeywordComparatorIterator<char> for Chars<'_> {
impl <'keyword> crate::KeywordComparatorIterator<'keyword, char> for Chars<'keyword> {
fn consume(&mut self, e: char) -> bool {
return self.next().is_some_and(|a| a == e);
}
}
impl crate::_Keyword<char> for &str {
impl <'keyword> crate::Keyword<'keyword, char> for &'keyword str {
fn startComparation(
&self,
expectedLen: usize,
) -> Option<impl crate::_KeywordComparatorIterator<char>> {
) -> Option<impl crate::KeywordComparatorIterator<'keyword, char>> {
if (self.len() != expectedLen) {
return Option::None;
}
@ -20,11 +20,11 @@ impl crate::_Keyword<char> for &str {
}
}
impl crate::_Keyword<char> for &String {
impl <'keyword> crate::Keyword<'keyword, char> for &'keyword String {
fn startComparation(
&self,
expectedLen: usize,
) -> Option<impl crate::_KeywordComparatorIterator<char>> {
) -> Option<impl crate::KeywordComparatorIterator<'keyword, char>> {
if (self.len() != expectedLen) {
return Option::None;
}
@ -32,17 +32,17 @@ impl crate::_Keyword<char> for &String {
return Option::Some(self.chars());
}
}
impl<T: PartialEq> crate::_KeywordComparatorIterator<T> for Iter<'_, T> {
impl<'keyword, T: PartialEq> crate::KeywordComparatorIterator<'keyword, T> for Iter<'keyword, T> {
fn consume(&mut self, e: T) -> bool {
return self.next().is_some_and(|a| a.eq(&e));
}
}
impl<T: PartialEq> crate::_Keyword<T> for &[T] {
impl<'keyword, T: PartialEq> crate::Keyword<'keyword, T> for &'keyword [T] {
fn startComparation(
&self,
expectedLen: usize,
) -> Option<impl crate::_KeywordComparatorIterator<T>> {
) -> Option<impl crate::KeywordComparatorIterator<'keyword, T>> {
if (self.len() != expectedLen) {
return Option::None;
}
@ -51,11 +51,11 @@ impl<T: PartialEq> crate::_Keyword<T> for &[T] {
}
}
impl<T: PartialEq, const SZ: usize> crate::_Keyword<T> for &[T; SZ] {
impl<'keyword, T: PartialEq, const SZ: usize> crate::Keyword<'keyword, T> for &'keyword [T; SZ] {
fn startComparation(
&self,
expectedLen: usize,
) -> Option<impl crate::_KeywordComparatorIterator<T>> {
) -> Option<impl crate::KeywordComparatorIterator<'keyword, T>> {
if (self.len() != expectedLen) {
return Option::None;
}

View File

@ -4,43 +4,44 @@ pub trait Predicate<C> {
fn check(&mut self, chr: C) -> bool;
}
impl<C, F: FnMut(C) -> bool> Predicate<C> for F {
fn check(&mut self, chr: C) -> bool {
return self(chr);
}
}
pub trait Pos<'pos> {}
pub trait Pos {}
impl Pos<'static> for usize {}
pub trait _KeywordComparatorIterator<C> {
pub trait KeywordComparatorIterator<'keyword, C> {
fn consume(&mut self, c: C) -> bool;
}
pub trait _Keyword<C> {
fn startComparation(&self, expectedLen: usize) -> Option<impl _KeywordComparatorIterator<C>>;
pub trait Keyword<'keyword, C> {
fn startComparation(
&self,
expectedLen: usize,
) -> Option<impl KeywordComparatorIterator<'keyword, C>>;
}
pub trait CollectedSubstring<C> {
fn compareKeyword(&self, kw: impl _Keyword<C>);
pub trait CollectedSubstring<'source, C> {
fn compareKeyword<'keyword>(&self, kw: impl Keyword<'keyword, C>) -> bool;
}
pub enum CollectResult<T> {
EOF,
NotMatches,
Matches(T)
Matches(T),
}
pub trait SourceStream<C, P: Pos, CS: CollectedSubstring<C>> {
pub trait SourceStream<'source, 'pos, C, P: Pos<'pos>, CS: CollectedSubstring<'source, C>> {
/**
* Returns `true` if the end of stream reached.
*/
fn skip(&mut self, predicate: impl Predicate<C>) -> bool;
fn collect(&mut self, predicate: impl Predicate<C>) -> CollectResult<CS>;
fn skip(&mut self, predicate: &mut impl Predicate<C>) -> bool;
fn collect(&mut self, predicate: &mut impl Predicate<C>) -> CollectResult<CS>;
fn pos(&self) -> P;
fn currentChar(&self) -> Option<C>;
fn currentChar(&mut self) -> Option<C>;
fn nextChar(&mut self) -> Option<C>;
fn isEnded(&self) -> bool;
fn isEnded(&mut self) -> bool {
return self.currentChar().is_none();
}
}