func (a *anonymiser) ReadTable(tableName string, rowChan chan<- database.Row, opts reader.ReadTableOpt) error {
	logger := log.WithField("table", tableName)
	logger.Debug("Loading anonymiser config")
	table := a.tables.FindByName(tableName)
	if table == nil {
		logger.Debug("the table is not configured to be anonymised")
		return a.Reader.ReadTable(tableName, rowChan, opts)
	}
	if len(table.Anonymise) == 0 {
		logger.Debug("Skipping anonymiser")
		return a.Reader.ReadTable(tableName, rowChan, opts)
	}
	rawChan := make(chan database.Row)
	go func(rowChan chan<- database.Row, rawChan chan database.Row, table *config.Table) {
		for {
			row, more := <-rawChan
			if !more {
				close(rowChan)
				return
			}
			for column, fakerType := range table.Anonymise {
				if strings.HasPrefix(fakerType, literalPrefix) {
					row[column] = strings.TrimPrefix(fakerType, literalPrefix)
					continue
				}
				fakerType, args := getTypeArgs(fakerType)
				faker, found := Functions[fakerType]
				if !found {
					logger.WithField("anonymiser", fakerType).Error("Anonymiser is not found")
					row[column] = fmt.Sprintf("Invalid anonymiser: %s", fakerType)
					continue
				}
				var value string
				switch fakerType {
				case email, username:
					b := make([]byte, 2)
					rand.Read(b)
					value = fmt.Sprintf(
						"%s.%s",
						faker.Call([]reflect.Value{})[0].String(),
						hex.EncodeToString(b),
					)
				default:
					value = faker.Call(args)[0].String()
				}
				row[column] = value
			}
			rowChan <- row
		}
	}(rowChan, rawChan, table)
	if err := a.Reader.ReadTable(tableName, rawChan, opts); err != nil {
		return fmt.Errorf("anonymiser: error while reading table: %w", err)
	}
	return nil
}
ReadTable decorates reader.ReadTable method for anonymising rows published from the reader.Reader
package anonymiser
import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"github.com/hellofresh/klepto/pkg/config"
	"github.com/hellofresh/klepto/pkg/database"
	"github.com/hellofresh/klepto/pkg/reader"
	log "github.com/sirupsen/logrus"
)
const (
	literalPrefix = "literal:"
	email         = "EmailAddress"
	username      = "UserName"
)
var requireArgs = map[string]bool{
	"CharactersN":   true,
	"DigitsN":       true,
	"ParagraphsN":   true,
	"SentencesN":    true,
	"WordsN":        true,
	"CreditCardNum": true,
	"Password":      true,
	"Year":          true,
}
type (
	anonymiser struct {
		reader.Reader
		tables config.Tables
	}
)
func NewAnonymiser(source reader.Reader, tables config.Tables) reader.Reader {
	return &anonymiser{source, tables}
}