<commit_before>package libkb

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	lru "github.com/hashicorp/golang-lru"
	jsonw "github.com/keybase/go-jsonw"
)

const (
	UID_LEN    = 16
	UID_SUFFIX = 0x00
)

type UID [UID_LEN]byte

func (u UID) String() string {
	return hex.EncodeToString(u[:])
}

func (u UID) IsZero() bool {
	for _, b := range u {
		if b != 0 {
			return false
		}
	}
	return true
}

func UidFromHex(s string) (u *UID, err error) {
	var bv []byte
	bv, err = hex.DecodeString(s)
	if err != nil {
		return
	}
	if len(bv) != UID_LEN {
		err = fmt.Errorf("Bad UID '%s'; must be %d bytes long", s, UID_LEN)
		return
	}
	if bv[len(bv)-1] != UID_SUFFIX {
		err = fmt.Errorf("Bad UID '%s': must end in 0x'%x'", s, UID_SUFFIX)
		return
	}
	out := UID{}
	copy(out[:], bv[0:UID_LEN])
	u = &out
	return
}

func GetUid(w *jsonw.Wrapper) (u *UID, err error) {
	s, err := w.GetString()
	if err != nil {
		return nil, err
	}
	ret, err := UidFromHex(s)
	return ret, err
}

func (u UID) Eq(u2 UID) bool {
	return FastByteArrayEq(u[:], u2[:])
}

func GetUidVoid(w *jsonw.Wrapper, u *UID, e *error) {
	ret, err := GetUid(w)
	if err != nil {
		*e = err
	} else {
		*u = *ret
	}
	return
}

//==================================================================

// UsernameToUID works for users created after "Fri Feb  6 19:33:08 EST 2015"
func UsernameToUID(s string) UID {
	h := sha256.Sum256([]byte(s))
	var uid UID
	copy(uid[:], h[0:UID_LEN-1])
	uid[UID_LEN-1] = 0x00
	return uid
}

func CheckUIDAgainstUsername(uid UID, username string) (err error) {
	u2 := UsernameToUID(username)
	if !uid.Eq(u2) {
		err = UidMismatchError{fmt.Sprintf("%s != %s (via %s)",
			uid, u2, username)}
	}
	return
}

//==================================================================

type User struct {
	// Raw JSON element read from the server or our local DB.
	basics     *jsonw.Wrapper
	publicKeys *jsonw.Wrapper
	sigs       *jsonw.Wrapper

	// Processed fields<commit_msg>accept either the old or new UID suffix<commit_after>package libkb

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	lru "github.com/hashicorp/golang-lru"
	jsonw "github.com/keybase/go-jsonw"
)

const (
	UID_LEN      = 16
	UID_SUFFIX   = 0x00
	UID_SUFFIX_2 = 0x19
)

type UID [UID_LEN]byte

func (u UID) String() string {
	return hex.EncodeToString(u[:])
}

func (u UID) IsZero() bool {
	for _, b := range u {
		if b != 0 {
			return false
		}
	}
	return true
}

func UidFromHex(s string) (u *UID, err error) {
	var bv []byte
	bv, err = hex.DecodeString(s)
	if err != nil {
		return
	}
	if len(bv) != UID_LEN {
		err = fmt.Errorf("Bad UID '%s'; must be %d bytes long", s, UID_LEN)
		return
	}
	if bv[len(bv)-1] != UID_SUFFIX && bv[len(bv)-1] != UID_SUFFIX_2 {
		err = fmt.Errorf("Bad UID '%s': must end in 0x%x or 0x%x", s, UID_SUFFIX, UID_SUFFIX_2)
		return
	}
	out := UID{}
	copy(out[:], bv[0:UID_LEN])
	u = &out
	return
}

func GetUid(w *jsonw.Wrapper) (u *UID, err error) {
	s, err := w.GetString()
	if err != nil {
		return nil, err
	}
	ret, err := UidFromHex(s)
	return ret, err
}

func (u UID) Eq(u2 UID) bool {
	return FastByteArrayEq(u[:], u2[:])
}

func GetUidVoid(w *jsonw.Wrapper, u *UID, e *error) {
	ret, err := GetUid(w)
	if err != nil {
		*e = err
	} else {
		*u = *ret
	}
	return
}

//==================================================================

// UsernameToUID works for users created after "Fri Feb  6 19:33:08 EST 2015"
func UsernameToUID(s string) UID {
	h := sha256.Sum256([]byte(s))
	var uid UID
	copy(uid[:], h[0:UID_LEN-1])
	uid[UID_LEN-1] = UID_SUFFIX_2
	return uid
}

func CheckUIDAgainstUsername(uid UID, username string) (err error) {
	u2 := UsernameToUID(username)
	if !uid.Eq(u2) {
		err = UidMismatchError{fmt.Sprintf("%s != %s (via %s)",
			uid, u2, username)}
	}
	return
}

//==================================================================

type User struct {
	// Raw JSON element read from the server or our local DB.
	basics     *jsonw.Wrapper
	publicKeys *jsonw.Wrapper
	sigs       *jsonw.Wrapper

	// Processed fields
{'fraction_non_alphanumeric': 0.21073558648111332, 'fraction_numerical': 0.021371769383697812, 'mean_word_length': 3.6158256880733943, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '565007', 'n_tokens_mistral': 1748, 'n_tokens_neox': 1644, 'n_words': 439}