package iterators

type Stringish interface {
	[]byte | string
}

type SplitFunc[ Stringish] func(, bool) (int, , error)

// Iterator is a generic iterator for words that are either []byte or string.
// Iterate while Next() is true, and access the word via Value().
type Iterator[ Stringish] struct {
	split SplitFunc[]
	data  
	start int
	pos   int
}

// New creates a new Iterator for the given data and SplitFunc.
func [ Stringish]( SplitFunc[],  ) *Iterator[] {
	return &Iterator[]{
		split: ,
		data:  ,
	}
}

// SetText sets the text for the iterator to operate on, and resets all state.
func ( *Iterator[]) ( ) {
	.data = 
	.start = 0
	.pos = 0
}

// Split sets the SplitFunc for the Iterator.
func ( *Iterator[]) ( SplitFunc[]) {
	.split = 
}

// Next advances the iterator to the next token. It returns false when there
// are no remaining tokens or an error occurred.
func ( *Iterator[]) () bool {
	if .pos == len(.data) {
		return false
	}
	if .pos > len(.data) {
		panic("SplitFunc advanced beyond the end of the data")
	}

	.start = .pos

	, ,  := .split(.data[.pos:], true)
	if  != nil {
		panic()
	}
	if  <= 0 {
		panic("SplitFunc returned a zero or negative advance")
	}

	.pos += 
	if .pos > len(.data) {
		panic("SplitFunc advanced beyond the end of the data")
	}

	return true
}

// Value returns the current token.
func ( *Iterator[]) ()  {
	return .data[.start:.pos]
}

// Start returns the byte position of the current token in the original data.
func ( *Iterator[]) () int {
	return .start
}

// End returns the byte position after the current token in the original data.
func ( *Iterator[]) () int {
	return .pos
}

// Reset resets the iterator to the beginning of the data.
func ( *Iterator[]) () {
	.start = 0
	.pos = 0
}