package norm import ( "database/sql" "iter" "reflect" ) type Scanner[T any] struct { rows *sql.Rows onError func(err error) } func NewScanner[T any](rows *sql.Rows) Scanner[T] { return Scanner[T]{ rows: rows, } } func (s *Scanner[T]) Scan() iter.Seq2[T, error] { return func(yield func(T, error) bool) { for s.rows.Next() { var data T elem := reflect.ValueOf(&data).Elem() numCols := elem.NumField() columns := make([]any, numCols) for i := range numCols { field := elem.Field(i) columns[i] = field.Addr().Interface() } err := s.rows.Scan(columns...) if !yield(data, err) { return } } } } func (s *Scanner[T]) Close() error { return s.rows.Close() } func ScanAll[T any](rows *sql.Rows, dest *[]T) error { scanner := NewScanner[T](rows) defer scanner.Close() for elem, err := range scanner.Scan() { if err != nil { return err } *dest = append(*dest, elem) } return nil } func Scan[T any](row *sql.Row, dest *T) error { elem := reflect.ValueOf(dest).Elem() numCols := elem.NumField() columns := make([]any, numCols) for i := range numCols { field := elem.Field(i) columns[i] = field.Addr().Interface() } return row.Scan(columns...) }