<commit_before>// Copyright (c) 2017, <NAME>.
// All rights reserved.

package store

import (
	"crypto/rand"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"unsafe"

	"github.com/cjpatton/store/pb"
	"github.com/golang/protobuf/proto"
)

/*
// The next line gets things going on Mac:
#cgo CPPFLAGS: -I/usr/local/opt/openssl/include
#cgo LDFLAGS: -lstruct -lcrypto
#include <struct/const.h>
#include <struct/dict.h>
#include "string.h"

char **new_str_list(int len) {
	return calloc(sizeof(char *), len);
}

int *new_int_list(int len) {
	return calloc(sizeof(int), len);
}

void set_str_list(char **list, int idx, char *val) {
	list[idx] = val;
}

void set_int_list(int *list, int idx, int val) {
	list[idx] = val;
}

int get_int_list(int *list, int idx) {
	return list[idx];
}

char *get_str_list(char **list, int idx) {
	return list[idx];
}

void free_str_list(char **list, int len) {
	int i;
	for (i = 0; i < len; i++) {
		if (list[i] != NULL) {
			free(list[i]);
		}
	}
	free(list);
}

void free_int_list(int *list) {
	free(list);
}

char *get_row_ptr(char *table, int row, int row_bytes) {
	return &table[row * row_bytes];
}

node_t *get_node(graph_t *graph, int idx) {
	return &graph->node[idx];
}

int get_edge(graph_t *graph, int i, int j) {
	return graph->node[i].adj_edge[j];
}
*/
import "C"

// Number of bytes to use for the salt, a random string used to construct the
// table. It is prepended to the input of each HMAC call.
const SaltBytes = 8

// Number of row bytes allocated for the tag.
const TagBytes = 2

// The maximum length of the row. In general, the length of the row depends on
// the length of the longest output in the map. HASH_BYTES is defined in
// c/const.h.
const MaxRowBytes = C.HASH_BYTES

// The maximum length of the outputs. 1 byte of each row is allocated for
// padding the output string.
const MaxOutputBytes = MaxRowBytes - TagBytes - 1

// Length of the HMAC key. HMAC_KEY_BYTES is defined in c/const.h.
const DictKeyBytes = C.HMAC_KEY_BYTES

// GenerateKey generates a fresh, random key and returns it.
func GenerateDictKey() []byte {
	K := make([]byte, DictKeyBytes)
	_, err := rand.Read(K)
	if err != nil {
		return nil
	}
	return K
}

type Error string

func (err Error) Error() string {
	return string(err)
}

// Returned by Get() and priv.GetOutput() if the input was not found in the
// map.
const ItemNotFound = Error("item not found")

// Returned by pub.GetShare() in case x or y is not in the table index.
const ErrorIdx = Error("index out of range")

// cError propagates an error from the internal C code.
func cError(fn string, errNo C.int) Error {
	return Error(fmt.Sprintf("%s returns error %d", fn, errNo))
}

// The public representation of the map.
type PubDict struct {
	dict *C.dict_t
}

// The private state required for evaluation queries.
type PrivDict struct {
	tinyCtx    *C.tiny_ctx
	params     C.dict_params_t
	cZeroShare *C.char
}

// An undirected graph stored as an adjacency list.
type Graph [][]int32

// New generates a new structure (pub, priv) for the map M and key K.
//
// You must call pub.Free() and priv.Free() before these variables go out
// of scope. These structures contain C types that were allocated on the heap
// and must be freed before losing a reference to them.
func NewDict(K []byte, M map[string]string) (*PubDict, *PrivDict, error) {

	if len(M) == 0 {
		return nil, nil, Error("yup")
	}

	cM := newCMap(M)
	defer cM.free()

	pub, priv, _, err := newDictAndGraph(K, cM, TagBytes, true)
	if err != nil {
		return nil, nil, err
	}
	return pub, priv, nil
}

// NewPubDictFromProto creates a new *PubDict from a *pb.Dict.
//<commit_msg>Add a TODO.<commit_after>// Copyright (c) 2017, <NAME>.
// All rights reserved.

package store

import (
	"crypto/rand"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"unsafe"

	"github.com/cjpatton/store/pb"
	"github.com/golang/protobuf/proto"
)

/*
// The next line gets things going on Mac:
#cgo CPPFLAGS: -I/usr/local/opt/openssl/include
#cgo LDFLAGS: -lstruct -lcrypto
#include <struct/const.h>
#include <struct/dict.h>
#include "string.h"

char **new_str_list(int len) {
	return calloc(sizeof(char *), len);
}

int *new_int_list(int len) {
	return calloc(sizeof(int), len);
}

void set_str_list(char **list, int idx, char *val) {
	list[idx] = val;
}

void set_int_list(int *list, int idx, int val) {
	list[idx] = val;
}

int get_int_list(int *list, int idx) {
	return list[idx];
}

char *get_str_list(char **list, int idx) {
	return list[idx];
}

void free_str_list(char **list, int len) {
	int i;
	for (i = 0; i < len; i++) {
		if (list[i] != NULL) {
			free(list[i]);
		}
	}
	free(list);
}

void free_int_list(int *list) {
	free(list);
}

char *get_row_ptr(char *table, int row, int row_bytes) {
	return &table[row * row_bytes];
}

node_t *get_node(graph_t *graph, int idx) {
	return &graph->node[idx];
}

int get_edge(graph_t *graph, int i, int j) {
	return graph->node[i].adj_edge[j];
}
*/
import "C"

// Number of bytes to use for the salt, a random string used to construct the
// table. It is prepended to the input of each HMAC call.
const SaltBytes = 8

// Number of row bytes allocated for the tag.
const TagBytes = 2

// The maximum length of the row. In general, the length of the row depends on
// the length of the longest output in the map. HASH_BYTES is defined in
// c/const.h.
const MaxRowBytes = C.HASH_BYTES

// The maximum length of the outputs. 1 byte of each row is allocated for
// padding the output string.
const MaxOutputBytes = MaxRowBytes - TagBytes - 1

// Length of the HMAC key. HMAC_KEY_BYTES is defined in c/const.h.
const DictKeyBytes = C.HMAC_KEY_BYTES

// GenerateKey generates a fresh, random key and returns it.
func GenerateDictKey() []byte {
	K := make([]byte, DictKeyBytes)
	_, err := rand.Read(K)
	if err != nil {
		return nil
	}
	return K
}

type Error string

func (err Error) Error() string {
	return string(err)
}

// Returned by Get() and priv.GetOutput() if the input was not found in the
// map.
const ItemNotFound = Error("item not found")

// Returned by pub.GetShare() in case x or y is not in the table index.
const ErrorIdx = Error("index out of range")

// cError propagates an error from the internal C code.
func cError(fn string, errNo C.int) Error {
	return Error(fmt.Sprintf("%s returns error %d", fn, errNo))
}

// The public representation of the map.
type PubDict struct {
	dict *C.dict_t
}

// The private state required for evaluation queries.
type PrivDict struct {
	tinyCtx    *C.tiny_ctx
	params     C.dict_params_t
	cZeroShare *C.char
}

// An undirected graph stored as an adjacency list.
//
// TODO(cjpatton) Don't export this type.
type Graph [][]int32

// New generates a new structure (pub, priv) for the map M and key K.
//
// You must call pub.Free() and priv.Free() before these variables go out
// of scope. These structures contain C types that were allocated on the heap
// and must be freed before losing a reference to them.
func NewDict(K []byte, M map[string]string) (*PubDict, *PrivDict, error) {

	if len(M) == 0 {
		return nil, nil, Error("yup")
	}

	cM := newCMap(M)
	defer cM.free()

	pub, priv, _, err := newDictAndGraph(K, cM, TagBytes, true)
	if err != nil {
		return nil, nil, err
	}
	return pub, priv, nil
}

// NewPubDictFromProto creates a new *PubDict from a *pb.Dict.
//
{'fraction_non_alphanumeric': 0.12645567886011783, 'fraction_numerical': 0.0032881216605014385, 'mean_word_length': 3.596977329974811, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '5534628', 'n_tokens_mistral': 2650, 'n_tokens_neox': 2584, 'n_words': 941}