<commit_before>package aspect

import (
	"database/sql"
	"fmt"
	"reflect"
	"unicode"
)

const tagLabel = "db"

var scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()

type field struct {
	index   []int  // struct field indexes - with possible embedding
	column  string // SQL column name
	table   string // SQL table name
	options options
}

func (f field) Exists() bool {
	return len(f.index) > 0
}

type fields []field

func (f fields) Empty() bool {
	for _, field := range f {
		if field.Exists() {
			return false
		}
	}
	return true
}

func SelectFields(v interface{}) ([]field, error) {
	value := reflect.ValueOf(v)
	if value.Kind() != reflect.Ptr {
		return nil, fmt.Errorf(
			"aspect: can only take select into pointer values, received %s",
			value.Kind(),
		)
	}
	return recurse([]int{}, reflect.TypeOf(v).Elem()), nil
}

func SelectFieldsFromElem(elem reflect.Type) []field {
	return recurse([]int{}, elem)
}

func recurse(indexes []int, elem reflect.Type) (fields []field) {
	if elem.Kind() != reflect.Struct {
		return nil
	}

	for i := 0; i < elem.NumField(); i += 1 {
		f := elem.Field(i)
		if f.Type.Kind() == reflect.Struct && !reflect.PtrTo(f.Type).Implements(scannerType) {
			switch f.Type.String() { // TODO switch on the actual type
			case "time.Time":
			default:
				fields = append(fields, recurse(append(indexes, i), f.Type)...)
				continue
			}
		}

		// TODO ignore un-exported fields?<commit_msg>Replaced instances of type []field with fields<commit_after>package aspect

import (
	"database/sql"
	"fmt"
	"reflect"
	"unicode"
)

const tagLabel = "db"

var scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()

type field struct {
	index   []int  // struct field indexes - with possible embedding
	column  string // SQL column name
	table   string // SQL table name
	options options
}

// Exists returns true if the field contains a valid recursive field index
func (f field) Exists() bool {
	return len(f.index) > 0
}

type fields []field

// Empty returns true if all of its fields do not exist
func (f fields) Empty() bool {
	for _, field := range f {
		if field.Exists() {
			return false
		}
	}
	return true
}

// SelectFields returns the ordered list of fields from the given interface.
// The interface must be a pointer to a struct.
func SelectFields(v interface{}) (fields, error) {
	value := reflect.ValueOf(v)
	if value.Kind() != reflect.Ptr {
		return nil, fmt.Errorf(
			"aspect: can only take select into pointer values, received %s",
			value.Kind(),
		)
	}
	return recurse([]int{}, reflect.TypeOf(v).Elem()), nil
}

// SelectFieldsFromElem returns the ordered list of fields from the given
// reflect Type
func SelectFieldsFromElem(elem reflect.Type) fields {
	return recurse([]int{}, elem)
}

func recurse(indexes []int, elem reflect.Type) (fields fields) {
	if elem.Kind() != reflect.Struct {
		return nil
	}

	for i := 0; i < elem.NumField(); i += 1 {
		f := elem.Field(i)
		if f.Type.Kind() == reflect.Struct && !reflect.PtrTo(f.Type).Implements(scannerType) {
			switch f.Type.String() { // TODO switch on the actual type
			case "time.Time":
			default:
				fields = append(fields, recurse(append(indexes, i), f.Type)...)
				continue
			}
		}

		// TODO ignore un-exported fields?
{'fraction_non_alphanumeric': 0.13871763255240444, 'fraction_numerical': 0.0018495684340320592, 'mean_word_length': 3.5069444444444446, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7333444', 'n_tokens_mistral': 1133, 'n_tokens_neox': 1053, 'n_words': 346}