package dns

// Implement a simple scanner, return a byte stream from an io reader.

import (
	"bufio"
	"context"
	"io"
	"text/scanner"
)

type scan struct {
	src      *bufio.Reader
	position scanner.Position
	eof      bool // Have we just seen a eof
	ctx      context.Context
}

func scanInit(r io.Reader) (*scan, context.CancelFunc) {
	s := new(scan)
	s.src = bufio.NewReader(r)
	s.position.Line = 1

	ctx, cancel := context.WithCancel(context.Background())
	s.ctx = ctx

	return s, cancel
}

// tokenText returns the next byte from the input
func (s *scan) tokenText() (byte, error) {
	c, err := s.src.ReadByte()
	if err != nil {
		return c, err
	}
	select {
	case <-s.ctx.Done():
		return c, context.Canceled
	default:
		break
	}

	// delay the newline handling until the next token is delivered,
	// fixes off-by-one errors when reporting a parse error.
	if s.eof == true {
		s.position.Line++
		s.position.Column = 0
		s.eof = false
	}
	if c == '\n' {
		s.eof = true
		return c, nil
	}
	s.position.Column++
	return c, nil
}