<commit_before>package shortuuid

import (
	"fmt"
	"math"
	"math/big"
	"strings"

	uuid "github.com/satori/go.uuid"
)

// UUID returns a new UUID v4.
func UUID() string {
	return New().UUID("")
}

type ShortUUID struct {
	// alphabet is the character set to construct the UUID from.
	alphabet alphabet
}

// New returns a new (short) UUID with the default alphabet.
func New() *ShortUUID {
	return &ShortUUID{newAlphabet(DefaultAlphabet)}
}

// New returns a new (short) UUID using alphabet.
// The alphabet will be sorted and if it contains duplicate characters, they
// will be removed.
func NewWithAlphabet(alphabet string) (*ShortUUID, error) {
	if alphabet == "" {
		return nil, fmt.Errorf("alphabet must not be empty")
	}

	return &ShortUUID{newAlphabet(alphabet)}, nil
}

// UUID returns a new (short) UUID. If name is non-empty, the namespace
// matching the name will be used to generate a UUID.
func (su *ShortUUID) UUID(name string) string {
	var u uuid.UUID

	switch {
	case name == "":
		u = uuid.NewV4()
	case strings.HasPrefix(name, "http"):
		u = uuid.NewV5(uuid.NamespaceDNS, name)
	default:
		u = uuid.NewV5(uuid.NamespaceURL, name)
	}

	return su.Encode(u)
}

// Encode encodes uuid.UUID into a string using the least significant bits
// (LSB) first according to the alphabet. if the most significant bits (MSB)
// are 0, the string might be shorter.
func (su *ShortUUID) Encode(u uuid.UUID) string {
	var num big.Int
	num.SetString(strings.Replace(u.String(), "-", "", 4), 16)
	return su.numToString(&num, su.encodedLength(len(u.Bytes())))
}

// Decode decodes a string according to the alphabet into a uuid.UUID. If s is
// too short, its most significant bits (MSB) will be padded with 0 (zero).
func (su *ShortUUID) Decode(u string) (uuid.UUID, error) {
	return uuid.FromString(su.stringToNum(u))
}

// String genreates a new (short) UUID v4. This is not deterministic, and will
// return a new value each time it's called.
// Implements the fmt.Stringer interface.
func (su *ShortUUID) String() string {
	return su.UUID("")
}

func (su *ShortUUID) numToString(number *big.Int, padToLen int) string {
	var (
		out   string
		digit *big.Int
	)

	for number.Uint64() > 0 {
		number, digit = new(big.Int).DivMod(number, big.NewInt(su.alphabet.Length()), new(big.Int))
		out += su.alphabet.chars[digit.Int64()]
	}

	if padToLen > 0 {
		remainder := math.Max(float64(padToLen-len(out)), 0)
		out = out + strings.Repeat(su.alphabet.chars[0], int(remainder))
	}

	return out
}

// stringToNum converts a string a number using the given alpabet.
func (su *ShortUUID) stringToNum(s string) string {
	n := big.NewInt(0)

	for i := len(s) - 1; i >= 0; i-- {
		n.Mul(n, big.NewInt(su.alphabet.Length()))
		n.Add(n, big.NewInt(su.alphabet.Index(string(s[i]))))
	}

	x := fmt.Sprintf("%x", n)

	// Pad the most significant bit (MSG) with 0 (zero) if the string is too short.
	if len(x) < 32 {
		x = strings.Repeat("0", 32-len(x)) + x
	}

	return fmt.Sprintf("%s-%s-%s-%s-%s", x[0:8], x[8:12], x[12:16], x[16:20], x[20:32])
}

func (su *ShortUUID) encodedLength(numBytes int) int {
	factor := math.Log(float64(25)) / math.Log(float64(su.alphabet.Length()))
	length := math.Ceil(factor * float64(numBytes))
	return int(length)
}<commit_msg>Inline encodedLength()<commit_after>package shortuuid

import (
	"fmt"
	"math"
	"math/big"
	"strings"

	uuid "github.com/satori/go.uuid"
)

// UUID returns a new UUID v4.
func UUID() string {
	return New().UUID("")
}

type ShortUUID struct {
	// alphabet is the character set to construct the UUID from.
	alphabet alphabet
}

// New returns a new (short) UUID with the default alphabet.
func New() *ShortUUID {
	return &ShortUUID{newAlphabet(DefaultAlphabet)}
}

// New returns a new (short) UUID using alphabet.
// The alphabet will be sorted and if it contains duplicate characters, they
// will be removed.
func NewWithAlphabet(alphabet string) (*ShortUUID, error) {
	if alphabet == "" {
		return nil, fmt.Errorf("alphabet must not be empty")
	}

	return &ShortUUID{newAlphabet(alphabet)}, nil
}

// UUID returns a new (short) UUID. If name is non-empty, the namespace
// matching the name will be used to generate a UUID.
func (su *ShortUUID) UUID(name string) string {
	var u uuid.UUID

	switch {
	case name == "":
		u = uuid.NewV4()
	case strings.HasPrefix(name, "http"):
		u = uuid.NewV5(uuid.NamespaceDNS, name)
	default:
		u = uuid.NewV5(uuid.NamespaceURL, name)
	}

	return su.Encode(u)
}

// Encode encodes uuid.UUID into a string using the least significant bits
// (LSB) first according to the alphabet. if the most significant bits (MSB)
// are 0, the string might be shorter.
func (su *ShortUUID) Encode(u uuid.UUID) string {
	var num big.Int
	num.SetString(strings.Replace(u.String(), "-", "", 4), 16)

	// Calculate encoded length.
	factor := math.Log(float64(25)) / math.Log(float64(su.alphabet.Length()))
	length := math.Ceil(factor * float64(len(u.Bytes())))

	return su.numToString(&num, int(length))
}

// Decode decodes a string according to the alphabet into a uuid.UUID. If s is
// too short, its most significant bits (MSB) will be padded with 0 (zero).
func (su *ShortUUID) Decode(u string) (uuid.UUID, error) {
	return uuid.FromString(su.stringToNum(u))
}

// String genreates a new (short) UUID v4. This is not deterministic, and will
// return a new value each time it's called.
// Implements the fmt.Stringer interface.
func (su *ShortUUID) String() string {
	return su.UUID("")
}

func (su *ShortUUID) numToString(number *big.Int, padToLen int) string {
	var (
		out   string
		digit *big.Int
	)

	for number.Uint64() > 0 {
		number, digit = new(big.Int).DivMod(number, big.NewInt(su.alphabet.Length()), new(big.Int))
		out += su.alphabet.chars[digit.Int64()]
	}

	if padToLen > 0 {
		remainder := math.Max(float64(padToLen-len(out)), 0)
		out = out + strings.Repeat(su.alphabet.chars[0], int(remainder))
	}

	return out
}

// stringToNum converts a string a number using the given alpabet.
func (su *ShortUUID) stringToNum(s string) string {
	n := big.NewInt(0)

	for i := len(s) - 1; i >= 0; i-- {
		n.Mul(n, big.NewInt(su.alphabet.Length()))
		n.Add(n, big.NewInt(su.alphabet.Index(string(s[i]))))
	}

	x := fmt.Sprintf("%x", n)

	// Pad the most significant bit (MSG) with 0 (zero) if the string is too short.
	if len(x) < 32 {
		x = strings.Repeat("0", 32-len(x)) + x
	}

	return fmt.Sprintf("%s-%s-%s-%s-%s", x[0:8], x[8:12], x[12:16], x[16:20], x[20:32])
}
{'fraction_non_alphanumeric': 0.14855634895995032, 'fraction_numerical': 0.016764979819931698, 'mean_word_length': 3.8553127354935945, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 9, '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': '5848069', 'n_tokens_mistral': 2423, 'n_tokens_neox': 2342, 'n_words': 718}