<commit_before>package main

import (
	"archive/zip"
	"bufio"
	"bytes"
	"fmt"
	"image"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/tensorflow/tensorflow/tensorflow/go"
	"github.com/tensorflow/tensorflow/tensorflow/go/op"

	_ "image/jpeg"
)

func recognize(msg Message, optionString string) {
	options := new(tensorflow.SessionOptions)
	// options.Target = optionString // use local tensorflow

	log.Info("Recognizing image...")
	log.Info("Looking for model file...")

	// Load the serialized GraphDef from a file.
	modelfile, labelsfile, err := modelFiles(GlobalConfig.Tensorflow.ModelDir)
	failOnError(err, "No model file in model directory")

	log.Info("Loading model file...")

	model, err := ioutil.ReadFile(modelfile)
	failOnError(err, "Unable to load model file!")

	log.Info("Constructing graph...")

	// Construct an in-memory graph from the serialized form.
	graph := tensorflow.NewGraph()
	if err := graph.Import(model, ""); err != nil {
		log.Fatal(err)
	}

	log.Info("Starting new session...")

	options = nil

	// Create a session for inference over graph.
	session, err := tensorflow.NewSession(graph, options)
	failOnError(err, "Unable to start new tensorflow session")
	defer session.Close()

	log.Info("Creating tensor from image...")

	// Run inference on thestImageFilename.
	// For multiple images, session.Run() can be called in a loop (and
	// concurrently). Furthermore, images can be batched together since the
	// model accepts batches of image data as input.
	tensor, err := makeTensorFromImage(msg.Photo)
	failOnError(err, "Unable to make tensor from image!")

	log.Info("Running recognition...")

	output, err := session.Run(
		map[tensorflow.Output]*tensorflow.Tensor{
			graph.Operation("input").Output(0): tensor,
		},
		[]tensorflow.Output{
			graph.Operation("output").Output(0),
		},
		nil)

	failOnError(err, "Error while running a tensorflow session")

	log.Info("Gathering output...")

	// output[0].Value() is a vector containing probabilities of
	// labels for each image in the "batch". The batch size was 1.
	// Find the most probably label index.
	probabilities := output[0].Value().([][]float32)[0]
	printBestLabel(probabilities, labelsfile)
}

// Conver the image in filename to a Tensor suitable as input to the Inception model.
func makeTensorFromImage(data []byte) (*tensorflow.Tensor, error) {
	reader := bytes.NewReader(data)
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, err
	}

	// Represent the image as [H][W][B,G,R]byte
	contents := make([][][3]byte, img.Bounds().Size().Y)
	for y := 0; y < len(contents); y++ {
		contents[y] = make([][3]byte, img.Bounds().Size().X)
		for x := 0; x < len(contents[y]); x++ {
			px := x + img.Bounds().Min.X
			py := y + img.Bounds().Min.Y
			r, g, b, _ := img.At(px, py).RGBA()

			// image.Image uses 16-bits for each color.
			// We want 8-bits.
			contents[y][x][0] = byte(b >> 8)
			contents[y][x][1] = byte(g >> 8)
			contents[y][x][2] = byte(r >> 8)
		}
	}

	tensor, err := tensorflow.NewTensor(contents)
	if err != nil {
		return nil, err
	}

	// Construct a graph to normalize the image
	graph, input, output, err := constructGraphToNormalizeImage()
	if err != nil {
		return nil, err
	}

	// Execute that graph to normalize this one image
	session, err := tensorflow.NewSession(graph, nil)
	if err != nil {
		return nil, err
	}

	defer session.Close()

	normalized, err := session.Run(
		map[tensorflow.Output]*tensorflow.Tensor{input: tensor},
		[]tensorflow.Output{output},
		nil)

	if err != nil {
		return nil, err
	}

	return normalized[0], nil
}

// The inception model takes as input the image described by a Tensor in a very
// specific normalized format (a particular image size, shape of the input tensor,
// normalized pixel values etc.).
//
// This function constructs a graph of TensorFlow operations which takes as input
// the raw pixel values of an image in the form of a Tensor of shape [Height, Width, 3]
// and returns a tensor suitable for input to the inception model.
//
// T[y][x] is the (Blue, Green, Red) values of the pixel at position (x, y) in the image,
// with each color value represented as a single byte.
func constructGraphToNormalizeImage() (graph *tensorflow.Graph, input, output tensorflow.Output, err error) {
	// Some constants specific to the pre-trained model at:
	// https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
	//
	// - The model was trained after with images scaled to 224x224 pixels.
	// - The colors, represented as R, G, B in 1-byte each were converted to
	//   float using (value - Mean)/Scale.
	//
	// If using a different pre-trained model, the values will have to be adjusted.
	const (
		H, W  = 224, 224
		Mean  = float32(117)
		Scale = float32(1)
	)
	// - input is a 3D tensor of shape [Height, Width, Colors=3], where
	//   each pixel is represented as a triplet of 1-byte colors
	// - ResizeBilinear (and the inception model) takes a 4D tensor of shape
	//   [BatchSize, Height, Width, Colors=3], where each pixel is
	//   represented as a triplet of floats
	// - Apply normalization on each pixel and use ExpandDims to make
	//   this single image be a "batch" of size 1 for ResizeBilinear.
	s := op.NewScope()

	input = op.Placeholder(s, tensorflow.Uint8)
	output = op.Div(s,
		op.Sub(s,
			op.ResizeBilinear(s,
				op.ExpandDims(s,
					op.Cast(s, input, tensorflow.Float),
					op.Const(s.SubScope("make_batch"), int32(0))),
				op.Const(s.SubScope("size"), []int32{H, W})),
			op.Const(s.SubScope("mean"), Mean)),
		op.Const(s.SubScope("scale"), Scale))
	graph, err = s.Finalize()
	return graph, input, output, err
}

func printBestLabel(probabilities []float32, labelsFile string) {
	bestIdx := 0
	for i, p := range probabilities {
		if p > probabilities[bestIdx] {
			bestIdx = i
		}
	}
	// Found a best match, now read the string from the labelsFile where
	// there is one line per label.
	file, err := os.Open(labelsFile)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	var labels []string
	for scanner.Scan() {
		labels = append(labels, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		log.Errorf("ERROR: failed to read %s: %v", labelsFile, err)
	}
	fmt.Printf("BEST MATCH: (%2.0f%% likely) %s\n", probabilities[bestIdx]*100.0, labels[bestIdx])
}

// TODO: refactor those methods
func modelFiles(dir string) (modelfile, labelsfile string, err error) {
	const URL = "https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip"

	var (
		model   = filepath.Join(dir, "tensorflow_inception_graph.pb")
		labels  = filepath.Join(dir, "imagenet_comp_graph_label_strings.txt")
		zipfile = filepath.Join(dir, "inception5h.zip")
	)

	if filesExist(model, labels) == nil {
		return model, labels, nil
	}

	log.Warningf("Did not find model in '%s' downloading from '%s'", dir, URL)

	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", "", err
	}

	if err := download(URL, zipfile); err != nil {
		return "", "", fmt.Errorf("failed to download %v - %v", URL, err)
	}

	if err := unzip(dir, zipfile); err != nil {
		return "", "", fmt.Errorf("failed to extract contents from model archive: %v", err)
	}

	os.Remove(zipfile)
	return model, labels, filesExist(model, labels)
}

func filesExist(files ...string) error {
	for _, f := range files {
		if _, err := os.Stat(f); err != nil {
			return fmt.Errorf("unable to stat %s: %v", f, err)
		}
	}
	return nil
}

func download(URL, filename string) error {
	resp, err := http.Get(URL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = io.Copy(file, resp.Body)
	return err
}

func unzip(dir, zipfile string) error {
	r, err := zip.OpenReader(zipfile)
	if err != nil {
		return err
	}
	defer r.Close()
	for _, f := range r.File {
		src, err := f.Open()
		if err != nil {
			return err
		}
		log.Infof("Extracting from archive '%s'...", f.Name)
		dst, err := os.OpenFile(filepath.Join(dir, f.Name), os.O_WRONLY|os.O_CREATE, 0644)
		if err != nil {
			return err
		}
		if _, err := io.Copy(dst, src); err != nil {
			return err
		}
		dst.Close()
	}
	return nil
}
<commit_msg>Ability to return label and probability from tensorflow<commit_after>package main

import (
	"archive/zip"
	"bufio"
	"bytes"
	"fmt"
	"image"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/tensorflow/tensorflow/tensorflow/go"
	"github.com/tensorflow/tensorflow/tensorflow/go/op"

	_ "image/jpeg"
)

func Recognize(msg *Message) (label string, probability float32) {
	options := new(tensorflow.SessionOptions)
	// options.Target = optionString // use local tensorflow

	log.Info("Recognizing image...")
	log.Info("Looking for model file...")

	// Load the serialized GraphDef from a file.
	modelfile, labelsfile, err := modelFiles(GlobalConfig.Tensorflow.ModelDir)
	failOnError(err, "No model file in model directory")

	log.Info("Loading model file...")

	model, err := ioutil.ReadFile(modelfile)
	failOnError(err, "Unable to load model file!")

	log.Info("Constructing graph...")

	// Construct an in-memory graph from the serialized form.
	graph := tensorflow.NewGraph()
	if err := graph.Import(model, ""); err != nil {
		log.Fatal(err)
	}

	log.Info("Starting new session...")

	options = nil

	// Create a session for inference over graph.
	session, err := tensorflow.NewSession(graph, options)
	failOnError(err, "Unable to start new tensorflow session")
	defer session.Close()

	log.Info("Creating tensor from image...")

	// Run inference on thestImageFilename.
	// For multiple images, session.Run() can be called in a loop (and
	// concurrently). Furthermore, images can be batched together since the
	// model accepts batches of image data as input.
	tensor, err := makeTensorFromImage(msg.Photo)
	failOnError(err, "Unable to make tensor from image!")

	log.Info("Running recognition...")

	output, err := session.Run(
		map[tensorflow.Output]*tensorflow.Tensor{
			graph.Operation("input").Output(0): tensor,
		},
		[]tensorflow.Output{
			graph.Operation("output").Output(0),
		},
		nil)

	failOnError(err, "Error while running a tensorflow session")

	log.Info("Gathering output...")

	// output[0].Value() is a vector containing probabilities of
	// labels for each image in the "batch". The batch size was 1.
	// Find the most probably label index.
	probabilities := output[0].Value().([][]float32)[0]
	label, probability = calculateBestLabel(probabilities, labelsfile)
	return
}

// Conver the image in filename to a Tensor suitable as input to the Inception model.
func makeTensorFromImage(data []byte) (*tensorflow.Tensor, error) {
	reader := bytes.NewReader(data)
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, err
	}

	// Represent the image as [H][W][B,G,R]byte
	contents := make([][][3]byte, img.Bounds().Size().Y)
	for y := 0; y < len(contents); y++ {
		contents[y] = make([][3]byte, img.Bounds().Size().X)
		for x := 0; x < len(contents[y]); x++ {
			px := x + img.Bounds().Min.X
			py := y + img.Bounds().Min.Y
			r, g, b, _ := img.At(px, py).RGBA()

			// image.Image uses 16-bits for each color.
			// We want 8-bits.
			contents[y][x][0] = byte(b >> 8)
			contents[y][x][1] = byte(g >> 8)
			contents[y][x][2] = byte(r >> 8)
		}
	}

	tensor, err := tensorflow.NewTensor(contents)
	if err != nil {
		return nil, err
	}

	// Construct a graph to normalize the image
	graph, input, output, err := constructGraphToNormalizeImage()
	if err != nil {
		return nil, err
	}

	// Execute that graph to normalize this one image
	session, err := tensorflow.NewSession(graph, nil)
	if err != nil {
		return nil, err
	}

	defer session.Close()

	normalized, err := session.Run(
		map[tensorflow.Output]*tensorflow.Tensor{input: tensor},
		[]tensorflow.Output{output},
		nil)

	if err != nil {
		return nil, err
	}

	return normalized[0], nil
}

// The inception model takes as input the image described by a Tensor in a very
// specific normalized format (a particular image size, shape of the input tensor,
// normalized pixel values etc.).
//
// This function constructs a graph of TensorFlow operations which takes as input
// the raw pixel values of an image in the form of a Tensor of shape [Height, Width, 3]
// and returns a tensor suitable for input to the inception model.
//
// T[y][x] is the (Blue, Green, Red) values of the pixel at position (x, y) in the image,
// with each color value represented as a single byte.
func constructGraphToNormalizeImage() (graph *tensorflow.Graph, input, output tensorflow.Output, err error) {
	// Some constants specific to the pre-trained model at:
	// https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
	//
	// - The model was trained after with images scaled to 224x224 pixels.
	// - The colors, represented as R, G, B in 1-byte each were converted to
	//   float using (value - Mean)/Scale.
	//
	// If using a different pre-trained model, the values will have to be adjusted.
	const (
		H, W  = 224, 224
		Mean  = float32(117)
		Scale = float32(1)
	)
	// - input is a 3D tensor of shape [Height, Width, Colors=3], where
	//   each pixel is represented as a triplet of 1-byte colors
	// - ResizeBilinear (and the inception model) takes a 4D tensor of shape
	//   [BatchSize, Height, Width, Colors=3], where each pixel is
	//   represented as a triplet of floats
	// - Apply normalization on each pixel and use ExpandDims to make
	//   this single image be a "batch" of size 1 for ResizeBilinear.
	s := op.NewScope()

	input = op.Placeholder(s, tensorflow.Uint8)
	output = op.Div(s,
		op.Sub(s,
			op.ResizeBilinear(s,
				op.ExpandDims(s,
					op.Cast(s, input, tensorflow.Float),
					op.Const(s.SubScope("make_batch"), int32(0))),
				op.Const(s.SubScope("size"), []int32{H, W})),
			op.Const(s.SubScope("mean"), Mean)),
		op.Const(s.SubScope("scale"), Scale))
	graph, err = s.Finalize()
	return graph, input, output, err
}

func calculateBestLabel(probabilities []float32, labelsFile string) (label string, probability float32) {
	bestIdx := 0
	for i, p := range probabilities {
		if p > probabilities[bestIdx] {
			bestIdx = i
		}
	}
	// Found a best match, now read the string from the labelsFile where
	// there is one line per label.
	file, err := os.Open(labelsFile)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	var labels []string
	for scanner.Scan() {
		labels = append(labels, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		log.Errorf("ERROR: failed to read %s: %v", labelsFile, err)
	}

	probability = probabilities[bestIdx] * 100.0
	label = labels[bestIdx]
	log.Infof("BEST MATCH: (%2.0f%% likely) %s\n", probability, label)

	return
}

// TODO: refactor those methods
func modelFiles(dir string) (modelfile, labelsfile string, err error) {
	const URL = "https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip"

	var (
		model   = filepath.Join(dir, "tensorflow_inception_graph.pb")
		labels  = filepath.Join(dir, "imagenet_comp_graph_label_strings.txt")
		zipfile = filepath.Join(dir, "inception5h.zip")
	)

	if filesExist(model, labels) == nil {
		return model, labels, nil
	}

	log.Warningf("Did not find model in '%s' downloading from '%s'", dir, URL)

	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", "", err
	}

	if err := download(URL, zipfile); err != nil {
		return "", "", fmt.Errorf("failed to download %v - %v", URL, err)
	}

	if err := unzip(dir, zipfile); err != nil {
		return "", "", fmt.Errorf("failed to extract contents from model archive: %v", err)
	}

	os.Remove(zipfile)
	return model, labels, filesExist(model, labels)
}

func filesExist(files ...string) error {
	for _, f := range files {
		if _, err := os.Stat(f); err != nil {
			return fmt.Errorf("unable to stat %s: %v", f, err)
		}
	}
	return nil
}

func download(URL, filename string) error {
	resp, err := http.Get(URL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = io.Copy(file, resp.Body)
	return err
}

func unzip(dir, zipfile string) error {
	r, err := zip.OpenReader(zipfile)
	if err != nil {
		return err
	}
	defer r.Close()
	for _, f := range r.File {
		src, err := f.Open()
		if err != nil {
			return err
		}
		log.Infof("Extracting from archive '%s'...", f.Name)
		dst, err := os.OpenFile(filepath.Join(dir, f.Name), os.O_WRONLY|os.O_CREATE, 0644)
		if err != nil {
			return err
		}
		if _, err := io.Copy(dst, src); err != nil {
			return err
		}
		dst.Close()
	}
	return nil
}
<|endoftext|>


<commit_before>package jsend

import (
	"encoding/json"
	"errors"
	"net/http"
	"sync"
)

// JSend status codes
const (
	StatusSuccess = "success"
	StatusError   = "error"
	StatusFail    = "fail"
)

// Error types
var (
	ErrInvalidRawJSON = errors.New("jsend: given data is not a valid json.RawMessage")
	ErrJSONEncode     = errors.New("jsend: could not json encode given data")
	ErrWrittenAlready = errors.New("jsend: written already")
)

// Success json encodes and writes data to specified response with "success" status.
func Success(w http.ResponseWriter, data interface{}, code int) (int, error) {
	return write(w, StatusSuccess, code, data, "")
}

// Error writes error string to specified response with "error" status.
func Error(w http.ResponseWriter, error string, code int) (int, error) {
	return write(w, StatusError, code, nil, error)
}

// Fail json encodes and writes data to specified response with "fail" status.
func Fail(w http.ResponseWriter, data interface{}, code int) (int, error) {
	return write(w, StatusFail, code, data, "")
}

type jsonResponse struct {
	Status  string          `json:"status"`
	Data    json.RawMessage `json:"data,omitempty"`
	Message string          `json:"message,omitempty"`
}

func writeJSONResponse(w http.ResponseWriter, response *jsonResponse) (int, error) {
	resJSON, err := json.Marshal(response)
	if err != nil {
		return 0, ErrInvalidRawJSON
	}

	return w.Write(resJSON)
}

func write(w http.ResponseWriter, status string, statusCode int, data interface{}, error string) (int, error) {
	res := &jsonResponse{Status: status}
	if data != nil {
		dataJSON, err := json.Marshal(data)
		if err != nil {
			return 0, ErrJSONEncode
		}

		res.Data = dataJSON
	}

	if error != "" {
		res.Message = error
	}

	if w.Header().Get("Content-Type") == "" {
		w.Header().Set("Content-Type", "application/json")
	}

	w.WriteHeader(statusCode)

	return writeJSONResponse(w, res)
}

// Wrap wraps given http.ResponseWriter and returns a response object which
// implements http.ResponseWriter interface.
func Wrap(rw http.ResponseWriter) http.ResponseWriter {
	if rw.Header().Get("Content-Type") == "" {
		rw.Header().Set("Content-Type", "application/json")
	}

	return &response{rw: rw}
}

// A response wraps a http.ResponseWriter.
type response struct {
	rw      http.ResponseWriter
	code    int
	written bool
	sync.Mutex
}

func (r *response) Header() http.Header {
	return r.rw.Header()
}

func (r *response) WriteHeader(code int) {
	r.code = code
	r.rw.WriteHeader(code)
}

func (r *response) Write(data []byte) (int, error) {
	r.Lock()
	defer r.Unlock()

	if r.written {
		return 0, ErrWrittenAlready
	}
	r.written = true

	st := getStatus(r.code)
	jr := &jsonResponse{Status: st}
	switch st {
	case StatusError:
		jr.Message = string(data)
	case StatusFail:
		jr.Data = data
	default:
		jr.Data = data
	}

	return writeJSONResponse(r.rw, jr)
}

func getStatus(code int) string {
	switch {
	case code >= 500:
		return StatusError
	case code >= 400 && code < 500:
		return StatusFail
	}

	return StatusSuccess
}
<commit_msg>Add package level godoc<commit_after>/*
Package jsend implements JSend* specification.

Use by wrapping existing ResponseWriter

You can wrap your ResponseWriter:

	w := jsend.Wrap(w)

Returning object is also implements http.ResponseWriter. You can "Write" your json blob to it.

	w.Write(`{"foo": "bar"}`)

	// body:
	{
		"status": "success",
		"data": {
			"foo": "bar"
		}
	}

Status field in response body is derived from http status code. Status is "fail"
if code is 4XX, "error" if code is 5XX and "success" otherwise.

Fail:
	w.WriteHeader(400)
	w.Write(`{"foo": "invalid"}`)

	// body:
	{
		"status": "fail",
		"data": {
			"foo": "invalid"
		}
	}

Error:
	w.WriteHeader(500)
	w.Write(`we are closed`)

	// body:
	{
		"status": "error",
		"message": "we are closed"
	}

Note: Write method does not json-encode your data.

Use status functions

You can use Success, Fail and Error functions directly to write json responses with those statuses.

Success:
	jsend.Success(w, data, 200) // w is ResponseWriter

	// body:
	{
		"status": "success",
		"data": // your json encoded data
	}

Fail:
	jsend.Fail(w, data, 400)

	// body:
	{
		"status": "fail",
		"data": // your json encoded data
	}

Error:
	jsend.Fail(w, "something bad happened", 500)

	{
		"status": "error",
		"message": "something bad happened"
	}

Success, Fail and Error functions write given statusCode to response. Also
"Content-Type" header is set to "application/json" if it is not set already.

* See http://labs.omniti.com/labs/jsend for details.
*/
package jsend

import (
	"encoding/json"
	"errors"
	"net/http"
	"sync"
)

// JSend status codes
const (
	StatusSuccess = "success"
	StatusError   = "error"
	StatusFail    = "fail"
)

// Error types
var (
	ErrInvalidRawJSON = errors.New("jsend: given data is not a valid json.RawMessage")
	ErrJSONEncode     = errors.New("jsend: could not json encode given data")
	ErrWrittenAlready = errors.New("jsend: written already")
)

// Success json encodes and writes data to specified response with "success" status.
func Success(w http.ResponseWriter, data interface{}, code int) (int, error) {
	return write(w, StatusSuccess, code, data, "")
}

// Error writes error string to specified response with "error" status.
func Error(w http.ResponseWriter, error string, code int) (int, error) {
	return write(w, StatusError, code, nil, error)
}

// Fail json encodes and writes data to specified response with "fail" status.
func Fail(w http.ResponseWriter, data interface{}, code int) (int, error) {
	return write(w, StatusFail, code, data, "")
}

type jsonResponse struct {
	Status  string          `json:"status"`
	Data    json.RawMessage `json:"data,omitempty"`
	Message string          `json:"message,omitempty"`
}

func writeJSONResponse(w http.ResponseWriter, response *jsonResponse) (int, error) {
	resJSON, err := json.Marshal(response)
	if err != nil {
		return 0, ErrInvalidRawJSON
	}

	return w.Write(resJSON)
}

func write(w http.ResponseWriter, status string, statusCode int, data interface{}, error string) (int, error) {
	res := &jsonResponse{Status: status}
	if data != nil {
		dataJSON, err := json.Marshal(data)
		if err != nil {
			return 0, ErrJSONEncode
		}

		res.Data = dataJSON
	}

	if error != "" {
		res.Message = error
	}

	if w.Header().Get("Content-Type") == "" {
		w.Header().Set("Content-Type", "application/json")
	}

	w.WriteHeader(statusCode)

	return writeJSONResponse(w, res)
}

// Wrap wraps given http.ResponseWriter and returns a response object which
// implements http.ResponseWriter interface.
func Wrap(rw http.ResponseWriter) http.ResponseWriter {
	if rw.Header().Get("Content-Type") == "" {
		rw.Header().Set("Content-Type", "application/json")
	}

	return &response{rw: rw}
}

// A response wraps a http.ResponseWriter.
type response struct {
	rw      http.ResponseWriter
	code    int
	written bool
	sync.Mutex
}

func (r *response) Header() http.Header {
	return r.rw.Header()
}

func (r *response) WriteHeader(code int) {
	r.code = code
	r.rw.WriteHeader(code)
}

func (r *response) Write(data []byte) (int, error) {
	r.Lock()
	defer r.Unlock()

	if r.written {
		return 0, ErrWrittenAlready
	}
	r.written = true

	st := getStatus(r.code)
	jr := &jsonResponse{Status: st}
	switch st {
	case StatusError:
		jr.Message = string(data)
	case StatusFail:
		jr.Data = data
	default:
		jr.Data = data
	}

	return writeJSONResponse(r.rw, jr)
}

func getStatus(code int) string {
	switch {
	case code >= 500:
		return StatusError
	case code >= 400 && code < 500:
		return StatusFail
	}

	return StatusSuccess
}
<|endoftext|>


<commit_before>// unitygooglelivecaption.go
// intended to be used in unity project
// modification of livecaption.go found in https://github.com/GoogleCloudPlatform/golang-samples.git
//
// process requires google service accounts credential file's path
// you can get one in your google cloud console
// ----------------------------------------------------------------//

// livecaption.go
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command livecaption pipes the stdin audio data to
// Google Speech API and outputs the transcript.

package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	speech "cloud.google.com/go/speech/apiv1beta1"
	"golang.org/x/net/context"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
	speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1beta1"
)

var (
	version        = "v0.1"
	responcePrefix = "response: "
)

func main() {
	var credentialDir string
	var language string
	flag.StringVar(&credentialDir, "cred", "/path/to/file/", "path of google service account credential json file")
	flag.StringVar(&language, "language", "ja-JP", "languagecode of voice")
	flag.Parse()

	os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credentialDir)
	ctx := context.Background()
	conn, err := transport.DialGRPC(
		ctx,
		option.WithEndpoint("speech.googleapis.com:443"),
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// [START speech_streaming_mic_recognize]
	client, err := speech.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	stream, err := client.StreamingRecognize(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Send the initial configuration message.
	if err := stream.Send(&speechpb.StreamingRecognizeRequest{
		StreamingRequest: &speechpb.StreamingRecognizeRequest_StreamingConfig{
			StreamingConfig: &speechpb.StreamingRecognitionConfig{
				Config: &speechpb.RecognitionConfig{
					LanguageCode: language,
					Encoding:     speechpb.RecognitionConfig_LINEAR16,
					SampleRate:   16000,
				},
				InterimResults:  true,
				SingleUtterance: true,
			},
		},
	}); err != nil {
		log.Fatal(err)
	}

	go func() {
		// Pipe stdin to the API.
		buf := make([]byte, 8192)
		for {
			n, err := os.Stdin.Read(buf)
			if err == io.EOF {
				return // Nothing else to pipe, return from this goroutine.
			}
			if err != nil {
				log.Printf("Could not read from stdin: %v", err)
				continue
			}
			if err = stream.Send(&speechpb.StreamingRecognizeRequest{
				StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{
					AudioContent: buf[:n],
				},
			}); err != nil {
				log.Printf("Could not send audio: %v", err)
			}
		}
	}()

	for {
		resp, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Cannot stream results: %v", err)
		}
		if err := resp.Error; err != nil {
			log.Fatalf("Could not recognize: %v", err)
		}
		for _, result := range resp.Results {
			fmt.Printf("Result: %v\n", result.Alternatives[0].Transcript)
		}
	}
	// [END speech_streaming_mic_recognize]
}
<commit_msg>Add base64 output option<commit_after>// unitygooglelivecaption.go
// intended to be used in unity project
// modification of livecaption.go found in https://github.com/GoogleCloudPlatform/golang-samples.git
//
// process requires google service accounts credential file's path
// you can get one in your google cloud console
// ----------------------------------------------------------------//

// livecaption.go
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command livecaption pipes the stdin audio data to
// Google Speech API and outputs the transcript.

package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	speech "cloud.google.com/go/speech/apiv1beta1"
	"golang.org/x/net/context"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
	speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1beta1"
)

var (
	version        = "v0.1"
	responcePrefix = "response: "
)

func main() {
	var credentialDir string
	var language string
	var singleUtteranceEnable bool
	var outputAsBase64 bool
	flag.StringVar(&credentialDir, "cred", "/path/to/file/", "path of google service account credential json file")
	flag.StringVar(&language, "language", "ja-JP", "languagecode of voice")
	flag.BoolVar(&singleUtteranceEnable, "s", false, "enable single utterance termination")
	flag.BoolVar(&outputAsBase64, "base64", false, "output as base64 Encoding")
	flag.Parse()

	os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credentialDir)
	ctx := context.Background()
	conn, err := transport.DialGRPC(
		ctx,
		option.WithEndpoint("speech.googleapis.com:443"),
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// [START speech_streaming_mic_recognize]
	client, err := speech.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	stream, err := client.StreamingRecognize(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Send the initial configuration message.
	if err := stream.Send(&speechpb.StreamingRecognizeRequest{
		StreamingRequest: &speechpb.StreamingRecognizeRequest_StreamingConfig{
			StreamingConfig: &speechpb.StreamingRecognitionConfig{
				Config: &speechpb.RecognitionConfig{
					LanguageCode: language,
					Encoding:     speechpb.RecognitionConfig_LINEAR16,
					SampleRate:   16000,
				},
				InterimResults:  true,
				SingleUtterance: singleUtteranceEnable,
			},
		},
	}); err != nil {
		log.Fatal(err)
	}

	go func() {
		// Pipe stdin to the API.
		buf := make([]byte, 8192)
		for {
			n, err := os.Stdin.Read(buf)
			if err == io.EOF {
				return // Nothing else to pipe, return from this goroutine.
			}
			if err != nil {
				log.Printf("Could not read from stdin: %v", err)
				continue
			}
			if err = stream.Send(&speechpb.StreamingRecognizeRequest{
				StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{
					AudioContent: buf[:n],
				},
			}); err != nil {
				log.Printf("Could not send audio: %v", err)
			}
		}
	}()

	for {
		resp, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Cannot stream results: %v", err)
		}
		if err := resp.Error; err != nil {
			log.Fatalf("Could not recognize: %v", err)
		}
		for _, result := range resp.Results {
			output := "Result: " + result.Alternatives[0].Transcript
			if outputAsBase64 {
				output = base64.StdEncoding.EncodeToString([]byte(output))
			}
			fmt.Println(output)
		}
	}
	// [END speech_streaming_mic_recognize]
}
<|endoftext|>


<commit_before>package main

import "os"
import "github.com/docker/engine-api/client"
import "math/rand"
import "os/exec"
import "strconv"
import "github.com/seehuhn/mt19937"
import "time"
import "os/user"

var cli *client.Client

type ExecRequest struct {
	Image string
	Cmd []string
	SourceFileName string
}

type Judge struct {
	Code string
	Compile *ExecRequest
	Exec ExecRequest
	Time int64
	Mem  int64
	TCCount int // The number of test cases
}

type JudgeResult int

const (
	Accepted            JudgeResult = 0
	WrongAnswer         JudgeResult = 1
	CompileError        JudgeResult = 2
	TimeLimitExceeded   JudgeResult = 3
	MemoryLimitExceeded JudgeResult = 4
	RuntimeError        JudgeResult = 5
	InternalError       JudgeResult = 6
	Judging             JudgeResult = 7
	CompileTimeLimitExceeded JudgeResult = 8
	CompileMemoryLimitExceeded JudgeResult = 9
)

type JudgeStatus struct {
	Case     *string
	JR       JudgeResult
	Mem      int64
	Time     int64
	Msg      *string
}

func CreateInternalError(msg string) JudgeStatus {
	return JudgeStatus{nil, InternalError, 0, 0, &msg}
}

const BASE_RAND_STRING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func RandomName() string {
	rng := rand.New(mt19937.New())
	rng.Seed(time.Now().UnixNano())

	res := make([]byte, 0, 32)
	for i := 0; i < 32; i++ {
		res = append(res, BASE_RAND_STRING[rng.Intn(len(BASE_RAND_STRING))])
	}

	return string(res)
}

func (j *Judge) Run(ch chan<- JudgeStatus, tests <-chan struct {
	Name string
	In  string
	Out string
}) {
	// Close a channel to send results of judging
	defer close(ch)

	// Identity
	id := RandomName()

	// User
	_, err := exec.Command("useradd", "--no-create-home", id).Output()

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory to build your code. " + err.Error())

		return
	}

	uid, err := user.Lookup(id)

	if err != nil {
		ch <- CreateInternalError("Failed to look up a user. " + err.Error())

		return
	}

	uidInt, err := strconv.ParseInt(uid.Uid, 10, 64)

	if err != nil {
		ch <- CreateInternalError("Failed to parseInt uid. " + err.Error())

		return
	}
	gidInt, err := strconv.ParseInt(uid.Gid, 10, 64)
	if err != nil {
		ch <- CreateInternalError("Failed to parseInt gid. " + err.Error())

		return
	}

	defer exec.Command("userdel", id)

	// Working Directory
	path := workingDirectory + "/" + id

	err = os.Mkdir(path, 0664)

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory. " + err.Error())

		return
	}

	defer os.RemoveAll(path)

	uidInt = uidInt * gidInt
	err = os.Chown(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chown the directory. " + err.Error())

		return
	}
	err = os.Chmod(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the directory. " + err.Error())

		return
	}
	// Source File
	fp, err := os.Create(path + "/" + j.Compile.SourceFileName)

	if err != nil {
		ch <- CreateInternalError("Failed to create source file." + err.Error())

		return
	}

	l, err := fp.Write([]byte(j.Code))

	if err != nil {
		ch <- CreateInternalError("Failed to write your code on your file. " + err.Error())

		return
	}

	if l != len(j.Code) {
		ch <- CreateInternalError("Failed to write your code on your file.")

		return
	}

	fp.Close()

	err = os.Chmod(path + "/" + j.Compile.SourceFileName, 0644)

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the source file. " + err.Error())

		return
	}

	// Compile
	if j.Compile != nil {
		exe, err := NewExecutor(id, 512 * 1024 * 1024, []string{"ls", "-la", "/work"}, j.Compile.Image, []string{path + ":" + "/work"}, uid.Uid)

		if err != nil {
			ch <- CreateInternalError("Failed to create a Docker container to compile your code." + err.Error())

			return
		}

		res := exe.Run(10000, "")

		exe.Delete()
		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				ch <- CreateInternalError("Failed to execute a compiler." + res.Stderr)

				return
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{JR: CompileMemoryLimitExceeded}

				return
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{JR: CompileTimeLimitExceeded}

				return
			}
		}

		if res.ExitCode != 0 || true { // Debug
			msg := res.Stdout + res.Stderr
			ch <- JudgeStatus{JR: CompileError, Msg: &msg}

			return
		}
	}
	return

	exe, err := NewExecutor(id, j.Mem, j.Exec.Cmd, j.Exec.Image, []string{path + ":" + "/work:ro"}, uid.Uid)

	if err != nil {
		ch <- CreateInternalError("Failed to create a Docker container to judge." + err.Error())

		return
	}

	defer exe.Delete()

	tcCounter := 0
	for tc, res := <-tests; res; tc, res = <-tests {
		res := exe.Run(j.Time, tc.In)

		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				msg := "Failed to execute your code." + res.Stderr
				ch <- JudgeStatus{Case: &tc.Name, JR: InternalError, Msg: &msg}
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: MemoryLimitExceeded}
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: TimeLimitExceeded}
			}
		}else {
			if res.ExitCode != 0 {
				ch <- JudgeStatus{Case: &tc.Name, JR: RuntimeError}
			}else {
				if res.Stdout == tc.Out {
					ch <- JudgeStatus{Case: &tc.Name, JR: Accepted}
				}else {
					ch <- JudgeStatus{Case: &tc.Name, JR: WrongAnswer}
				}
			}
		}

		tcCounter++

		msg := strconv.FormatInt(int64(tcCounter), 10) + "/" + strconv.FormatInt(int64(j.TCCount), 10)
		ch <- JudgeStatus{JR: Judging, Msg: &msg}
	}

}
<commit_msg>Sun May 22 19:23:00 JST 2016<commit_after>package main

import "os"
import "github.com/docker/engine-api/client"
import "math/rand"
import "os/exec"
import "strconv"
import "github.com/seehuhn/mt19937"
import "time"
import "os/user"

var cli *client.Client

type ExecRequest struct {
	Image string
	Cmd []string
	SourceFileName string
}

type Judge struct {
	Code string
	Compile *ExecRequest
	Exec ExecRequest
	Time int64
	Mem  int64
	TCCount int // The number of test cases
}

type JudgeResult int

const (
	Accepted            JudgeResult = 0
	WrongAnswer         JudgeResult = 1
	CompileError        JudgeResult = 2
	TimeLimitExceeded   JudgeResult = 3
	MemoryLimitExceeded JudgeResult = 4
	RuntimeError        JudgeResult = 5
	InternalError       JudgeResult = 6
	Judging             JudgeResult = 7
	CompileTimeLimitExceeded JudgeResult = 8
	CompileMemoryLimitExceeded JudgeResult = 9
)

type JudgeStatus struct {
	Case     *string
	JR       JudgeResult
	Mem      int64
	Time     int64
	Msg      *string
}

func CreateInternalError(msg string) JudgeStatus {
	return JudgeStatus{nil, InternalError, 0, 0, &msg}
}

const BASE_RAND_STRING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func RandomName() string {
	rng := rand.New(mt19937.New())
	rng.Seed(time.Now().UnixNano())

	res := make([]byte, 0, 32)
	for i := 0; i < 32; i++ {
		res = append(res, BASE_RAND_STRING[rng.Intn(len(BASE_RAND_STRING))])
	}

	return string(res)
}

func (j *Judge) Run(ch chan<- JudgeStatus, tests <-chan struct {
	Name string
	In  string
	Out string
}) {
	// Close a channel to send results of judging
	defer close(ch)

	// Identity
	id := RandomName()

	// User
	_, err := exec.Command("useradd", "--no-create-home", id).Output()

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory to build your code. " + err.Error())

		return
	}

	uid, err := user.Lookup(id)

	if err != nil {
		ch <- CreateInternalError("Failed to look up a user. " + err.Error())

		return
	}

	uidInt, err := strconv.ParseInt(uid.Uid, 10, 64)

	if err != nil {
		ch <- CreateInternalError("Failed to parseInt uid. " + err.Error())

		return
	}
	gidInt, err := strconv.ParseInt(uid.Gid, 10, 64)
	if err != nil {
		ch <- CreateInternalError("Failed to parseInt gid. " + err.Error())

		return
	}

	defer exec.Command("userdel", id)

	// Working Directory
	path := workingDirectory + "/" + id

	err = os.Mkdir(path, 0664)

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory. " + err.Error())

		return
	}

	defer os.RemoveAll(path)

	uidInt = uidInt * gidInt
	err = os.Chown(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chown the directory. " + err.Error())

		return
	}
	err = os.Chmod(path, 0664)

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the directory. " + err.Error())

		return
	}
	// Source File
	fp, err := os.Create(path + "/" + j.Compile.SourceFileName)

	if err != nil {
		ch <- CreateInternalError("Failed to create source file." + err.Error())

		return
	}

	l, err := fp.Write([]byte(j.Code))

	if err != nil {
		ch <- CreateInternalError("Failed to write your code on your file. " + err.Error())

		return
	}

	if l != len(j.Code) {
		ch <- CreateInternalError("Failed to write your code on your file.")

		return
	}

	fp.Close()

	err = os.Chmod(path + "/" + j.Compile.SourceFileName, 0644)

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the source file. " + err.Error())

		return
	}

	// Compile
	if j.Compile != nil {
		exe, err := NewExecutor(id, 512 * 1024 * 1024, []string{"ls", "-la", "/work"}, j.Compile.Image, []string{path + ":" + "/work"}, uid.Uid)

		if err != nil {
			ch <- CreateInternalError("Failed to create a Docker container to compile your code." + err.Error())

			return
		}

		res := exe.Run(10000, "")

		exe.Delete()
		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				ch <- CreateInternalError("Failed to execute a compiler." + res.Stderr)

				return
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{JR: CompileMemoryLimitExceeded}

				return
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{JR: CompileTimeLimitExceeded}

				return
			}
		}

		if res.ExitCode != 0 || true { // Debug
			msg := res.Stdout + res.Stderr
			ch <- JudgeStatus{JR: CompileError, Msg: &msg}

			return
		}
	}
	return

	exe, err := NewExecutor(id, j.Mem, j.Exec.Cmd, j.Exec.Image, []string{path + ":" + "/work:ro"}, uid.Uid)

	if err != nil {
		ch <- CreateInternalError("Failed to create a Docker container to judge." + err.Error())

		return
	}

	defer exe.Delete()

	tcCounter := 0
	for tc, res := <-tests; res; tc, res = <-tests {
		res := exe.Run(j.Time, tc.In)

		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				msg := "Failed to execute your code." + res.Stderr
				ch <- JudgeStatus{Case: &tc.Name, JR: InternalError, Msg: &msg}
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: MemoryLimitExceeded}
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: TimeLimitExceeded}
			}
		}else {
			if res.ExitCode != 0 {
				ch <- JudgeStatus{Case: &tc.Name, JR: RuntimeError}
			}else {
				if res.Stdout == tc.Out {
					ch <- JudgeStatus{Case: &tc.Name, JR: Accepted}
				}else {
					ch <- JudgeStatus{Case: &tc.Name, JR: WrongAnswer}
				}
			}
		}

		tcCounter++

		msg := strconv.FormatInt(int64(tcCounter), 10) + "/" + strconv.FormatInt(int64(j.TCCount), 10)
		ch <- JudgeStatus{JR: Judging, Msg: &msg}
	}

}
<|endoftext|>


<commit_before>package dkrcrypt
// The HIGHT Block cipher from KISA
// Copyright (c) 2012 Damian Gryski <damian@gryski.com>
// Licensed under the GPLv3 or, at your option, any later version.

/*

References:

http://tools.ietf.org/html/draft-kisa-hight-00
http://www.iacr.org/cryptodb/archive/2006/CHES/04/04.pdf
http://seed.kisa.or.kr/kor/hight/hightInfo.jsp

*/

// A HightCipher is an instance of HIGHT encryption using a particular key.
type HightCipher struct {
	wk [8]byte   // whitened keys
	sk [128]byte // subkeys
}

type KeySizeError int

func (k KeySizeError) Error() string {
	return "dkrcrypt/hight: invalid key size " + strconv.Itoa(int(k))
}

// NewHight creates and returns a new HightCipher.
// The key argument should be 16 bytes.
func NewHight(key []byte) (*HightCipher, error) {
	c := new(HightCipher)

	if klen := len(key); klen != 16 {
		return nil, KeySizeError(len(key))
	}

	whiten(key, c.wk[:])
	subkey(key, c.sk[:])
	return c, nil
}

// Reset zeros the key data so that it will no longer appear in the process' memory.
func (c *HightCipher) Reset() {
	for i := range wk {
		wk[i] = 0
	}

	for i := range sk {
		sk[i] = 0
	}

}

// BlockSize returns the Hight block size.  It is needed to satisfy the Block interface in crypto/cipher.
func (c *HightCipher) BlockSize() int { return 8 }

// rotate left
func rotl(x byte, r byte) byte {
	return (x << r) | (x >> (8 - r))
}

// F0, from the specification
func f0(x byte) byte {
	return rotl(x, 1) ^ rotl(x, 2) ^ rotl(x, 7)
}

// F1, from the specification
func f1(x byte) byte {
	return rotl(x, 3) ^ rotl(x, 4) ^ rotl(x, 6)
}

// Encrypt encrypts the 8-byte block in src and stores the resulting ciphertext in dst.
func (c *HightCipher) Encrypt(dst, src []byte) {

	// numbering looks off here, because the plaintext is stored msb, but
	// having lsb makes our life easier
	x := [...]byte{
		src[7] + c.wk[0], // p0
		src[6],           // p1
		src[5] ^ c.wk[1], // p2
		src[4],           // p3
		src[3] + c.wk[2], // p4
		src[2],           // p5
		src[1] ^ c.wk[3], // p6
		src[0],           // p0
	}

	for i := 0; i < 31; i++ {
		x00 := x[7] ^ (f0(x[6]) + c.sk[4*i+3])
		x[7] = x[6]
		x[6] = x[5] + (f1(x[4]) ^ c.sk[4*i+2])
		x[5] = x[4]
		x[4] = x[3] ^ (f0(x[2]) + c.sk[4*i+1])
		x[3] = x[2]
		x[2] = x[1] + (f1(x[0]) ^ c.sk[4*i+0])
		x[1] = x[0]
		x[0] = x00
	}

	// last round
	dst[6] = x[1] + (f1(x[0]) ^ c.sk[124])
	dst[4] = x[3] ^ (f0(x[2]) + c.sk[125])
	dst[2] = x[5] + (f1(x[4]) ^ c.sk[126])
	dst[0] = x[7] ^ (f0(x[6]) + c.sk[127])

	// whitening
	dst[7] = x[0] + c.wk[4]
	dst[5] = x[2] ^ c.wk[5]
	dst[3] = x[4] + c.wk[6]
	dst[1] = x[6] ^ c.wk[7]
}

// Decrypt decrypts the 8-byte block in src and stores the resulting plaintext in dst.
func (c *HightCipher) Decrypt(dst, src []byte) {

	// whitening
	x := [...]byte{
		src[7] - c.wk[4], // c0
		src[6],           // c1
		src[5] ^ c.wk[5], // c2
		src[4],           // c3
		src[3] - c.wk[6], // c4
		src[2],           // c5
		src[1] ^ c.wk[7], // c6
		src[0],           // c7
	}

	// undo last round
	x[1] = x[1] - (f1(x[0]) ^ c.sk[124])
	x[3] = x[3] ^ (f0(x[2]) + c.sk[125])
	x[5] = x[5] - (f1(x[4]) ^ c.sk[126])
	x[7] = x[7] ^ (f0(x[6]) + c.sk[127])

	for i := 30; i >= 0; i-- {
		x00 := x[0]
		x[0] = x[1]
		x[1] = x[2] - (f1(x[1]) ^ c.sk[4*i+0])
		x[2] = x[3]
		x[3] = x[4] ^ (f0(x[3]) + c.sk[4*i+1])
		x[4] = x[5]
		x[5] = x[6] - (f1(x[5]) ^ c.sk[4*i+2])
		x[6] = x[7]
		x[7] = x00 ^ (f0(x[7]) + c.sk[4*i+3])
	}

	// undo initial whitening
	dst[7] = x[0] - c.wk[0] // p0
	dst[6] = x[1]           // p1
	dst[5] = x[2] ^ c.wk[1] // p2
	dst[4] = x[3]           // p3
	dst[3] = x[4] - c.wk[2] // p4
	dst[2] = x[5]           // p5
	dst[1] = x[6] ^ c.wk[3] // p6
	dst[0] = x[7]           // p7
}

func whiten(mk, wk []byte) {

	for i := 0; i < 4; i++ {
		wk[i] = mk[16-i-12-1]
	}

	for i := 4; i < 8; i++ {
		wk[i] = mk[16-i+4-1]
	}
}

// This table doesn't change, so rather that recompute it every time we need to
// compute subkeys, we just build it once.  The code to create it was:

/*
   s = 0x5A
   d[0] = s
   for i := 1; i < 128; i++ {
           s = (s >> 1) | (((s & 1) ^ ((s & (1 << 3)) >> 3)) << 6)
           d[i] = s
   }
*/

var delta = []byte{
	0x5a, 0x6d, 0x36, 0x1b, 0x0d, 0x06, 0x03, 0x41,
	0x60, 0x30, 0x18, 0x4c, 0x66, 0x33, 0x59, 0x2c,
	0x56, 0x2b, 0x15, 0x4a, 0x65, 0x72, 0x39, 0x1c,
	0x4e, 0x67, 0x73, 0x79, 0x3c, 0x5e, 0x6f, 0x37,
	0x5b, 0x2d, 0x16, 0x0b, 0x05, 0x42, 0x21, 0x50,
	0x28, 0x54, 0x2a, 0x55, 0x6a, 0x75, 0x7a, 0x7d,
	0x3e, 0x5f, 0x2f, 0x17, 0x4b, 0x25, 0x52, 0x29,
	0x14, 0x0a, 0x45, 0x62, 0x31, 0x58, 0x6c, 0x76,
	0x3b, 0x1d, 0x0e, 0x47, 0x63, 0x71, 0x78, 0x7c,
	0x7e, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x43, 0x61,
	0x70, 0x38, 0x5c, 0x6e, 0x77, 0x7b, 0x3d, 0x1e,
	0x4f, 0x27, 0x53, 0x69, 0x34, 0x1a, 0x4d, 0x26,
	0x13, 0x49, 0x24, 0x12, 0x09, 0x04, 0x02, 0x01,
	0x40, 0x20, 0x10, 0x08, 0x44, 0x22, 0x11, 0x48,
	0x64, 0x32, 0x19, 0x0c, 0x46, 0x23, 0x51, 0x68,
	0x74, 0x3a, 0x5d, 0x2e, 0x57, 0x6b, 0x35, 0x5a,
}

func subkey(mk, sk []byte) {

	for i := 0; i < 8; i++ {

		for j := 0; j < 8; j++ {
			k := j - i
			if k < 0 {
				k += 8
			}
			sk[16*i+j] = mk[16-k-1] + delta[16*i+j]
		}

		for j := 0; j < 8; j++ {
			k := j - i
			if k < 0 {
				k += 8
			}
			sk[16*i+j+8] = mk[16-k-8-1] + delta[16*i+j+8]
		}

	}
}
<commit_msg>Missing import for KeySizeError<commit_after>package dkrcrypt

// The HIGHT Block cipher from KISA
// Copyright (c) 2012 Damian Gryski <damian@gryski.com>
// Licensed under the GPLv3 or, at your option, any later version.

/*

References:

http://tools.ietf.org/html/draft-kisa-hight-00
http://www.iacr.org/cryptodb/archive/2006/CHES/04/04.pdf
http://seed.kisa.or.kr/kor/hight/hightInfo.jsp

*/

import (
	"strconv"
)

// A HightCipher is an instance of HIGHT encryption using a particular key.
type HightCipher struct {
	wk [8]byte   // whitened keys
	sk [128]byte // subkeys
}

type KeySizeError int

func (k KeySizeError) Error() string {
	return "dkrcrypt/hight: invalid key size " + strconv.Itoa(int(k))
}

// NewHight creates and returns a new HightCipher.
// The key argument should be 16 bytes.
func NewHight(key []byte) (*HightCipher, error) {
	c := new(HightCipher)

	if klen := len(key); klen != 16 {
		return nil, KeySizeError(len(key))
	}

	whiten(key, c.wk[:])
	subkey(key, c.sk[:])
	return c, nil
}

// Reset zeros the key data so that it will no longer appear in the process' memory.
func (c *HightCipher) Reset() {
	for i := range wk {
		wk[i] = 0
	}

	for i := range sk {
		sk[i] = 0
	}

}

// BlockSize returns the Hight block size.  It is needed to satisfy the Block interface in crypto/cipher.
func (c *HightCipher) BlockSize() int { return 8 }

// rotate left
func rotl(x byte, r byte) byte {
	return (x << r) | (x >> (8 - r))
}

// F0, from the specification
func f0(x byte) byte {
	return rotl(x, 1) ^ rotl(x, 2) ^ rotl(x, 7)
}

// F1, from the specification
func f1(x byte) byte {
	return rotl(x, 3) ^ rotl(x, 4) ^ rotl(x, 6)
}

// Encrypt encrypts the 8-byte block in src and stores the resulting ciphertext in dst.
func (c *HightCipher) Encrypt(dst, src []byte) {

	// numbering looks off here, because the plaintext is stored msb, but
	// having lsb makes our life easier
	x := [...]byte{
		src[7] + c.wk[0], // p0
		src[6],           // p1
		src[5] ^ c.wk[1], // p2
		src[4],           // p3
		src[3] + c.wk[2], // p4
		src[2],           // p5
		src[1] ^ c.wk[3], // p6
		src[0],           // p0
	}

	for i := 0; i < 31; i++ {
		x00 := x[7] ^ (f0(x[6]) + c.sk[4*i+3])
		x[7] = x[6]
		x[6] = x[5] + (f1(x[4]) ^ c.sk[4*i+2])
		x[5] = x[4]
		x[4] = x[3] ^ (f0(x[2]) + c.sk[4*i+1])
		x[3] = x[2]
		x[2] = x[1] + (f1(x[0]) ^ c.sk[4*i+0])
		x[1] = x[0]
		x[0] = x00
	}

	// last round
	dst[6] = x[1] + (f1(x[0]) ^ c.sk[124])
	dst[4] = x[3] ^ (f0(x[2]) + c.sk[125])
	dst[2] = x[5] + (f1(x[4]) ^ c.sk[126])
	dst[0] = x[7] ^ (f0(x[6]) + c.sk[127])

	// whitening
	dst[7] = x[0] + c.wk[4]
	dst[5] = x[2] ^ c.wk[5]
	dst[3] = x[4] + c.wk[6]
	dst[1] = x[6] ^ c.wk[7]
}

// Decrypt decrypts the 8-byte block in src and stores the resulting plaintext in dst.
func (c *HightCipher) Decrypt(dst, src []byte) {

	// whitening
	x := [...]byte{
		src[7] - c.wk[4], // c0
		src[6],           // c1
		src[5] ^ c.wk[5], // c2
		src[4],           // c3
		src[3] - c.wk[6], // c4
		src[2],           // c5
		src[1] ^ c.wk[7], // c6
		src[0],           // c7
	}

	// undo last round
	x[1] = x[1] - (f1(x[0]) ^ c.sk[124])
	x[3] = x[3] ^ (f0(x[2]) + c.sk[125])
	x[5] = x[5] - (f1(x[4]) ^ c.sk[126])
	x[7] = x[7] ^ (f0(x[6]) + c.sk[127])

	for i := 30; i >= 0; i-- {
		x00 := x[0]
		x[0] = x[1]
		x[1] = x[2] - (f1(x[1]) ^ c.sk[4*i+0])
		x[2] = x[3]
		x[3] = x[4] ^ (f0(x[3]) + c.sk[4*i+1])
		x[4] = x[5]
		x[5] = x[6] - (f1(x[5]) ^ c.sk[4*i+2])
		x[6] = x[7]
		x[7] = x00 ^ (f0(x[7]) + c.sk[4*i+3])
	}

	// undo initial whitening
	dst[7] = x[0] - c.wk[0] // p0
	dst[6] = x[1]           // p1
	dst[5] = x[2] ^ c.wk[1] // p2
	dst[4] = x[3]           // p3
	dst[3] = x[4] - c.wk[2] // p4
	dst[2] = x[5]           // p5
	dst[1] = x[6] ^ c.wk[3] // p6
	dst[0] = x[7]           // p7
}

func whiten(mk, wk []byte) {

	for i := 0; i < 4; i++ {
		wk[i] = mk[16-i-12-1]
	}

	for i := 4; i < 8; i++ {
		wk[i] = mk[16-i+4-1]
	}
}

// This table doesn't change, so rather that recompute it every time we need to
// compute subkeys, we just build it once.  The code to create it was:

/*
   s = 0x5A
   d[0] = s
   for i := 1; i < 128; i++ {
           s = (s >> 1) | (((s & 1) ^ ((s & (1 << 3)) >> 3)) << 6)
           d[i] = s
   }
*/

var delta = []byte{
	0x5a, 0x6d, 0x36, 0x1b, 0x0d, 0x06, 0x03, 0x41,
	0x60, 0x30, 0x18, 0x4c, 0x66, 0x33, 0x59, 0x2c,
	0x56, 0x2b, 0x15, 0x4a, 0x65, 0x72, 0x39, 0x1c,
	0x4e, 0x67, 0x73, 0x79, 0x3c, 0x5e, 0x6f, 0x37,
	0x5b, 0x2d, 0x16, 0x0b, 0x05, 0x42, 0x21, 0x50,
	0x28, 0x54, 0x2a, 0x55, 0x6a, 0x75, 0x7a, 0x7d,
	0x3e, 0x5f, 0x2f, 0x17, 0x4b, 0x25, 0x52, 0x29,
	0x14, 0x0a, 0x45, 0x62, 0x31, 0x58, 0x6c, 0x76,
	0x3b, 0x1d, 0x0e, 0x47, 0x63, 0x71, 0x78, 0x7c,
	0x7e, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x43, 0x61,
	0x70, 0x38, 0x5c, 0x6e, 0x77, 0x7b, 0x3d, 0x1e,
	0x4f, 0x27, 0x53, 0x69, 0x34, 0x1a, 0x4d, 0x26,
	0x13, 0x49, 0x24, 0x12, 0x09, 0x04, 0x02, 0x01,
	0x40, 0x20, 0x10, 0x08, 0x44, 0x22, 0x11, 0x48,
	0x64, 0x32, 0x19, 0x0c, 0x46, 0x23, 0x51, 0x68,
	0x74, 0x3a, 0x5d, 0x2e, 0x57, 0x6b, 0x35, 0x5a,
}

func subkey(mk, sk []byte) {

	for i := 0; i < 8; i++ {

		for j := 0; j < 8; j++ {
			k := j - i
			if k < 0 {
				k += 8
			}
			sk[16*i+j] = mk[16-k-1] + delta[16*i+j]
		}

		for j := 0; j < 8; j++ {
			k := j - i
			if k < 0 {
				k += 8
			}
			sk[16*i+j+8] = mk[16-k-8-1] + delta[16*i+j+8]
		}

	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 - Michael Woolnough <michael.woolnough@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package minecraft

import (
	"github.com/MJKWoolnough/boolmap"
	"github.com/MJKWoolnough/minecraft/nbt"
	"math/rand"
	"time"
)

var (
	levelRequired = map[string]nbt.TagId{
		"LevelName": nbt.Tag_String,
		"SpawnX":    nbt.Tag_Int,
		"SpawnY":    nbt.Tag_Int,
		"SpawnZ":    nbt.Tag_Int,
	}
)

const (
	LIGHT_NONE uint8 = iota
	LIGHT_SIMPLE
	LIGHT_ALL
)

type Level struct {
	path      Path
	chunks    map[uint64]*chunk
	changes   boolmap.Map
	levelData *nbt.Compound
	lighting  uint8
	changed   bool
}

func NewLevel(location Path) (*Level, error) {
	var (
		levelDat nbt.Tag
		data     *nbt.Compound
	)
	levelDat, err := location.ReadLevelDat()
	if err != nil {
		return nil, err
	} else if levelDat == nil {
		levelDat = nbt.NewTag("", nbt.NewCompound([]nbt.Tag{
			nbt.NewTag("Data", nbt.NewCompound([]nbt.Tag{
				nbt.NewTag("GameType", nbt.NewInt(1)),
				nbt.NewTag("generatorName", nbt.NewString("flat")),
				nbt.NewTag("generatorVersion", nbt.NewInt(0)),
				nbt.NewTag("generatorOptions", nbt.NewString("0")),
				nbt.NewTag("hardcore", nbt.NewByte(0)),
				nbt.NewTag("LastPlayed", nbt.NewLong(timestampMS())),
				nbt.NewTag("LevelName", nbt.NewString("")),
				nbt.NewTag("MapFeatures", nbt.NewByte(0)),
				nbt.NewTag("RandomSeed", nbt.NewLong(rand.New(rand.NewSource(time.Now().Unix())).Int63())),
				nbt.NewTag("raining", nbt.NewByte(0)),
				nbt.NewTag("rainTime", nbt.NewInt(0)),
				nbt.NewTag("SizeOnDisk", nbt.NewLong(0)),
				nbt.NewTag("SpawnX", nbt.NewInt(0)),
				nbt.NewTag("SpawnY", nbt.NewInt(0)),
				nbt.NewTag("SpawnZ", nbt.NewInt(0)),
				nbt.NewTag("Time", nbt.NewLong(0)),
				nbt.NewTag("thundering", nbt.NewByte(0)),
				nbt.NewTag("thunderTime", nbt.NewInt(0)),
				nbt.NewTag("version", nbt.NewInt(19133)),
			})),
		}))
	}
	if levelDat.TagId() != nbt.Tag_Compound {
		return nil, WrongTypeError{"[BASE]", nbt.Tag_Compound, levelDat.TagId()}
	} else if d := levelDat.Data().(*nbt.Compound).Get("Data"); d != nil {
		if d.TagId() == nbt.Tag_Compound {
			data = d.Data().(*nbt.Compound)
		} else {
			return nil, WrongTypeError{"Data", nbt.Tag_Compound, d.TagId()}
		}
	} else {
		return nil, &MissingTagError{"Data"}
	}
	for name, tagType := range levelRequired {
		if x := data.Get(name); x == nil {
			return nil, &MissingTagError{name}
		} else if x.TagId() != tagType {
			return nil, &WrongTypeError{name, tagType, x.TagId()}
		}
	}
	return &Level{
		location,
		make(map[uint64]*chunk),
		boolmap.NewMap(),
		levelDat.Data().(*nbt.Compound).Get("Data").Data().(*nbt.Compound),
		LIGHT_NONE,
		false,
	}, nil
}

func (l Level) GetSpawn() (x, y, z int32) {
	if l.levelData == nil {
		return
	}
	xTag, yTag, zTag := l.levelData.Get("SpawnX"), l.levelData.Get("SpawnY"), l.levelData.Get("SpawnZ")
	if xd, ok := xTag.Data().(*nbt.Int); !ok {
		return
	} else {
		x = int32(*xd)
	}
	if yd, ok := yTag.Data().(*nbt.Int); !ok {
		return
	} else {
		y = int32(*yd)
	}
	if zd, ok := zTag.Data().(*nbt.Int); ok {
		z = int32(*zd)
	}
	return
}

func (l *Level) SetSpawn(x, y, z int32) {
	l.levelData.Set(nbt.NewTag("SpawnX", nbt.NewInt(x)))
	l.levelData.Set(nbt.NewTag("SpawnY", nbt.NewInt(y)))
	l.levelData.Set(nbt.NewTag("SpawnZ", nbt.NewInt(z)))
	l.changed = true
}

func (l *Level) GetBlock(x, y, z int32) (*Block, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return nil, err
	} else if c == nil {
		return &Block{}, nil
	}
	return c.GetBlock(x, y, z), nil
}

func (l *Level) SetBlock(x, y, z int32, block *Block) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	var opacity, light uint8
	if l.lighting != LIGHT_NONE {
		opacity = c.GetOpacity(x, y, z)
		if l.lighting == LIGHT_ALL {
			light = c.GetBlockLight(x, y, z)
		}
	}
	c.SetBlock(x, y, z, block)
	if l.lighting != LIGHT_NONE {
		if block.Opacity() != opacity {

		}
		if block.Light() != light {

		}
	}
	return nil
}

func (l *Level) GetBiome(x, z int32) (Biome, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return Biome_Auto, err
	} else if c == nil {
		return Biome_Plains, nil
	}
	return c.GetBiome(x, z), nil
}

func (l *Level) SetBiome(x, z int32, biome Biome) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	c.SetBiome(x, z, biome)
	return nil
}

func (l Level) GetName() string {
	s := l.levelData.Get("LevelName").Data().(*nbt.String)
	return string(*s)
}

func (l *Level) SetName(name string) {
	l.levelData.Set(nbt.NewTag("LevelName", nbt.NewString(name)))
	l.changed = true
}

func (l *Level) getChunk(x, z int32, create bool) (*chunk, error) {
	pos := uint64(z)<<32 | uint64(uint32(x))
	if l.chunks[pos] == nil {
		chunkData, err := l.path.GetChunk(x, z)
		if err != nil {
			return nil, err
		}
		if chunkData != nil {
			chunk, err := newChunk(x, z, chunkData)
			if err != nil {
				return nil, err
			}
			l.chunks[pos] = chunk
		} else if create {
			l.chunks[pos], _ = newChunk(x, z, nil)
		}
	}
	if create {
		l.changes.Set(pos, true)
	}
	return l.chunks[pos], nil
}

func (l *Level) Save() error {
	if l.changed {
		if err := l.path.WriteLevelDat(nbt.NewTag("", nbt.NewCompound([]nbt.Tag{nbt.NewTag("Data", l.levelData)}))); err != nil {
			return err
		}
		l.changed = false
	}
	toSave := make([]nbt.Tag, 0)
	for n, c := range l.chunks {
		if l.changes.Get(n) {
			toSave = append(toSave, c.GetNBT())
		}
	}
	if len(toSave) > 0 {
		return l.path.SetChunk(toSave...)
	}
	l.changes = boolmap.NewMap()
	return nil
}

func (l *Level) Close() {
	l.changed = false
	l.chunks = make(map[uint64]*chunk)
	l.changes = boolmap.NewMap()
}

func timestampMS() int64 {
	return time.Now().Unix() * 1000
}
<commit_msg>Inlined timestampMS()<commit_after>// Copyright (c) 2013 - Michael Woolnough <michael.woolnough@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package minecraft

import (
	"github.com/MJKWoolnough/boolmap"
	"github.com/MJKWoolnough/minecraft/nbt"
	"math/rand"
	"time"
)

var (
	levelRequired = map[string]nbt.TagId{
		"LevelName": nbt.Tag_String,
		"SpawnX":    nbt.Tag_Int,
		"SpawnY":    nbt.Tag_Int,
		"SpawnZ":    nbt.Tag_Int,
	}
)

const (
	LIGHT_NONE uint8 = iota
	LIGHT_SIMPLE
	LIGHT_ALL
)

type Level struct {
	path      Path
	chunks    map[uint64]*chunk
	changes   boolmap.Map
	levelData *nbt.Compound
	lighting  uint8
	changed   bool
}

func NewLevel(location Path) (*Level, error) {
	var (
		levelDat nbt.Tag
		data     *nbt.Compound
	)
	levelDat, err := location.ReadLevelDat()
	if err != nil {
		return nil, err
	} else if levelDat == nil {
		levelDat = nbt.NewTag("", nbt.NewCompound([]nbt.Tag{
			nbt.NewTag("Data", nbt.NewCompound([]nbt.Tag{
				nbt.NewTag("GameType", nbt.NewInt(1)),
				nbt.NewTag("generatorName", nbt.NewString("flat")),
				nbt.NewTag("generatorVersion", nbt.NewInt(0)),
				nbt.NewTag("generatorOptions", nbt.NewString("0")),
				nbt.NewTag("hardcore", nbt.NewByte(0)),
				nbt.NewTag("LastPlayed", nbt.NewLong(time.Now().Unix()*1000)),
				nbt.NewTag("LevelName", nbt.NewString("")),
				nbt.NewTag("MapFeatures", nbt.NewByte(0)),
				nbt.NewTag("RandomSeed", nbt.NewLong(rand.New(rand.NewSource(time.Now().Unix())).Int63())),
				nbt.NewTag("raining", nbt.NewByte(0)),
				nbt.NewTag("rainTime", nbt.NewInt(0)),
				nbt.NewTag("SizeOnDisk", nbt.NewLong(0)),
				nbt.NewTag("SpawnX", nbt.NewInt(0)),
				nbt.NewTag("SpawnY", nbt.NewInt(0)),
				nbt.NewTag("SpawnZ", nbt.NewInt(0)),
				nbt.NewTag("Time", nbt.NewLong(0)),
				nbt.NewTag("thundering", nbt.NewByte(0)),
				nbt.NewTag("thunderTime", nbt.NewInt(0)),
				nbt.NewTag("version", nbt.NewInt(19133)),
			})),
		}))
	}
	if levelDat.TagId() != nbt.Tag_Compound {
		return nil, WrongTypeError{"[BASE]", nbt.Tag_Compound, levelDat.TagId()}
	} else if d := levelDat.Data().(*nbt.Compound).Get("Data"); d != nil {
		if d.TagId() == nbt.Tag_Compound {
			data = d.Data().(*nbt.Compound)
		} else {
			return nil, WrongTypeError{"Data", nbt.Tag_Compound, d.TagId()}
		}
	} else {
		return nil, &MissingTagError{"Data"}
	}
	for name, tagType := range levelRequired {
		if x := data.Get(name); x == nil {
			return nil, &MissingTagError{name}
		} else if x.TagId() != tagType {
			return nil, &WrongTypeError{name, tagType, x.TagId()}
		}
	}
	return &Level{
		location,
		make(map[uint64]*chunk),
		boolmap.NewMap(),
		levelDat.Data().(*nbt.Compound).Get("Data").Data().(*nbt.Compound),
		LIGHT_NONE,
		false,
	}, nil
}

func (l Level) GetSpawn() (x, y, z int32) {
	if l.levelData == nil {
		return
	}
	xTag, yTag, zTag := l.levelData.Get("SpawnX"), l.levelData.Get("SpawnY"), l.levelData.Get("SpawnZ")
	if xd, ok := xTag.Data().(*nbt.Int); !ok {
		return
	} else {
		x = int32(*xd)
	}
	if yd, ok := yTag.Data().(*nbt.Int); !ok {
		return
	} else {
		y = int32(*yd)
	}
	if zd, ok := zTag.Data().(*nbt.Int); ok {
		z = int32(*zd)
	}
	return
}

func (l *Level) SetSpawn(x, y, z int32) {
	l.levelData.Set(nbt.NewTag("SpawnX", nbt.NewInt(x)))
	l.levelData.Set(nbt.NewTag("SpawnY", nbt.NewInt(y)))
	l.levelData.Set(nbt.NewTag("SpawnZ", nbt.NewInt(z)))
	l.changed = true
}

func (l *Level) GetBlock(x, y, z int32) (*Block, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return nil, err
	} else if c == nil {
		return &Block{}, nil
	}
	return c.GetBlock(x, y, z), nil
}

func (l *Level) SetBlock(x, y, z int32, block *Block) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	var opacity, light uint8
	if l.lighting != LIGHT_NONE {
		opacity = c.GetOpacity(x, y, z)
		if l.lighting == LIGHT_ALL {
			light = c.GetBlockLight(x, y, z)
		}
	}
	c.SetBlock(x, y, z, block)
	if l.lighting != LIGHT_NONE {
		if block.Opacity() != opacity {

		}
		if block.Light() != light {

		}
	}
	return nil
}

func (l *Level) GetBiome(x, z int32) (Biome, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return Biome_Auto, err
	} else if c == nil {
		return Biome_Plains, nil
	}
	return c.GetBiome(x, z), nil
}

func (l *Level) SetBiome(x, z int32, biome Biome) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	c.SetBiome(x, z, biome)
	return nil
}

func (l Level) GetName() string {
	s := l.levelData.Get("LevelName").Data().(*nbt.String)
	return string(*s)
}

func (l *Level) SetName(name string) {
	l.levelData.Set(nbt.NewTag("LevelName", nbt.NewString(name)))
	l.changed = true
}

func (l *Level) getChunk(x, z int32, create bool) (*chunk, error) {
	pos := uint64(z)<<32 | uint64(uint32(x))
	if l.chunks[pos] == nil {
		chunkData, err := l.path.GetChunk(x, z)
		if err != nil {
			return nil, err
		}
		if chunkData != nil {
			chunk, err := newChunk(x, z, chunkData)
			if err != nil {
				return nil, err
			}
			l.chunks[pos] = chunk
		} else if create {
			l.chunks[pos], _ = newChunk(x, z, nil)
		}
	}
	if create {
		l.changes.Set(pos, true)
	}
	return l.chunks[pos], nil
}

func (l *Level) Save() error {
	if l.changed {
		if err := l.path.WriteLevelDat(nbt.NewTag("", nbt.NewCompound([]nbt.Tag{nbt.NewTag("Data", l.levelData)}))); err != nil {
			return err
		}
		l.changed = false
	}
	toSave := make([]nbt.Tag, 0)
	for n, c := range l.chunks {
		if l.changes.Get(n) {
			toSave = append(toSave, c.GetNBT())
		}
	}
	if len(toSave) > 0 {
		return l.path.SetChunk(toSave...)
	}
	l.changes = boolmap.NewMap()
	return nil
}

func (l *Level) Close() {
	l.changed = false
	l.chunks = make(map[uint64]*chunk)
	l.changes = boolmap.NewMap()
}
<|endoftext|>


<commit_before>package instructions

import "github.com/MJKWoolnough/tokeniser"

// Token Types
const (
	FUNCTION tokeniser.ItemType = iota
	COMMENT
	STRING
	NUMBER
)

func lexFunction(l *tokeniser.Lexer) tokeniser.StateFn {
	if l.Accept("#") {
		return lexComment
	}
	switch l.AcceptUntil(" \n") {
	case ' ':
		l.Backup()
		l.Emit(FUNCTION)
		l.Next()
		l.Clear()
		return lexArgument
	case '\n':
		l.Backup()
		l.Emit(FUNCTION)
		l.Next()
		l.Clear()
		return lexFunction
	default:
		l.Errorf("unexpected eof")
	}
	return nil
}

func lexComment(l *tokeniser.Lexer) tokeniser.StateFn {
	l.Clear()
	l.AcceptUntil("\n")
	l.Backup()
	l.Emit(COMMENT)
	l.Next()
	l.Clear()
	return lexFunction
}

func lexArgument(l *tokeniser.Lexer) tokeniser.StateFn {
	l.AcceptRun(" ")
	if l.Peek() == '"' {
		l.Next()
		l.Clear()
		lexString(l)
	} else {
		l.Clear()
		lexNumber(l)
	}
	l.Clear()
	l.AcceptRun(" ")
	if l.Accept(",") {
		return lexArgument
	} else if l.Accept("\n") {
		l.Clear()
		return lexFunction
	}
	return nil
}

func lexNumber(l *tokeniser.Lexer) tokeniser.StateFn {
	l.Accept("+-")
	digits := "0123456789"
	if l.Accept("0") && l.Accept("xX") {
		digits = "0123456789abcdefABCDEF"
	}
	l.AcceptRun(digits)
	if l.Accept(".") {
		l.AcceptRun(digits)
	}
	if l.Accept("eE") {
		l.Accept("+-")
		l.AcceptRun(digits)
	}
	l.Accept("i")
	l.Emit(NUMBER)
	return nil
}

func lexString(l *tokeniser.Lexer) tokeniser.StateFn {
	for l.AcceptUntil("\\\"") != '"' {
		if !l.Accept("\\\"abtnfr") {
			l.Errorf("invalid escape character")
			return nil
		}
	}
	l.Backup()
	l.Emit(STRING)
	l.Next()
	return nil
}
<commit_msg>updated lexer to use new parser package<commit_after>package instructions

import (
	"errors"
	"io"

	"github.com/MJKWoolnough/parser"
)

type stateFn func() (token, stateFn)

type tokenType uint8

const (
	tokenError tokenType = iota
	tokenFunction
	tokenNumber
	tokenString
	tokenComment
	tokenDone
)

func (t tokenType) String() string {
	switch t {
	case tokenError:
		return "error"
	case tokenFunction:
		return "function"
	case tokenNumber:
		return "number"
	case tokenString:
		return "string"
	case tokenComment:
		return "comment"
	case tokenDone:
		return "done"
	default:
		return "unknown"
	}
}

type token struct {
	typ  tokenType
	data string
}

type lexer struct {
	p     parser.Parser
	state stateFn
	err   error
}

func newLexer(r io.Reader) *lexer {
	l := &lexer{
		p: parser.NewReaderParser(r),
	}
	l.state = l.lexFunction
	return l
}

func (l *lexer) GetToken() (token, error) {
	if l.err == io.EOF {
		return token{tokenDone, ""}, l.err
	}
	var t token
	t, l.state = l.state()
	//l.p.Get()
	if l.err == io.EOF {
		if t.typ == tokenError {
			l.err = io.ErrUnexpectedEOF
		}
	}
	return t, l.err
}

func (l *lexer) lexFunction() (token, stateFn) {
	if l.p.Peek() == -1 {
		l.err = io.EOF
		return token{tokenDone, "EOF"}, l.errorFn
	}
	l.p.Get()
	if l.p.Accept("#") {
		return l.lexComment()
	}
	l.p.ExceptRun(" \n")
	return token{tokenFunction, l.p.Get()}, l.lexArgument
}

func (l *lexer) lexComment() (token, stateFn) {
	l.p.Get()
	l.p.ExceptRun("\n")
	c := l.p.Get()
	l.p.Accept("\n")
	l.p.Get()
	return token{tokenComment, c}, l.lexFunction
}

func (l *lexer) lexArgument() (token, stateFn) {
	l.p.AcceptRun(" ")
	char := l.p.Peek()
	switch char {
	case '"':
		l.p.Accept(string(char))
		return l.lexString()
	case '\n':
		l.p.Accept(string(char))
		return l.lexFunction()
	default:
		return l.lexNumber()
	}
}

func (l *lexer) lexNumber() (token, stateFn) {
	l.p.Get()
	l.p.Accept("+-")
	digits := "0123456789"
	if l.p.Accept("0") && l.p.Accept("xX") {
		digits = "0123456789abcdefABCDEF"
	}
	l.p.AcceptRun(digits)
	if l.p.Accept(".") {
		l.p.AcceptRun(digits)
	}
	if l.p.Accept("eE") {
		l.p.Accept("+-")
		l.p.AcceptRun(digits)
	}
	l.p.Accept("i")
	n := l.p.Get()
	if len(n) == 0 {
		l.err = ErrInvalidNumber
		return l.errorFn()
	}
	return token{tokenNumber, n}, l.lexArgument
}

func (l *lexer) lexString() (token, stateFn) {
	l.p.Get()
Loop:
	for {
		l.p.ExceptRun("\\\"")
		switch l.p.Peek() {
		case '\\':
			if !l.p.Accept("\\\"abtnfr") {
				l.err = ErrInvalidEscape
				return l.errorFn()
			}
		case '"':
			break Loop
		default:
			l.err = io.ErrUnexpectedEOF
			return token{tokenError, l.err.Error()}, l.errorFn
		}
	}
	s := l.p.Get()
	l.p.Accept("\"")
	l.p.Get()
	return token{tokenString, s}, l.lexArgument
}

func (l *lexer) errorFn() (token, stateFn) {
	return token{tokenError, l.err.Error()}, l.errorFn
}

// Errors

var (
	ErrInvalidEscape = errors.New("invalid escape character")
	ErrInvalidNumber = errors.New("invalid number format")
)
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Jason Woods.
 *
 * This file is a modification of code from Logstash Forwarder.
 * Copyright 2012-2013 Jordan Sissel and contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package transports

import (
	"fmt"
	"net"
	"math/rand"
	"strconv"
	"time"
)

type AddressPool struct {
	servers        []string
	rfc2782        bool
	rfc2782Service string
	roundrobin     int
	host_is_ip     bool
	host           string
	addresses      []*net.TCPAddr
}

func init() {
	rand.Seed(time.Now().UnixNano())
}

func NewAddressPool(servers []string) *AddressPool {
	ret := &AddressPool{
		servers: servers,
	}

	// Randomise the initial host - after this it will round robin
	// Round robin after initial attempt ensures we don't retry same host twice,
	// and also ensures we try all hosts one by one
	rnd := rand.Intn(len(servers))
	if rnd != 0 {
		ret.servers = append(append(make([]string, 0), servers[rnd:]...), servers[:rnd]...)
	}

	return ret
}

func (p *AddressPool) SetRfc2782(enabled bool, service string) {
	p.rfc2782 = enabled
	p.rfc2782Service = service
}

func (p *AddressPool) IsLast() bool {
	return p.addresses == nil
}

func (p *AddressPool) IsLastServer() bool {
	return p.roundrobin%len(p.servers) == 0
}

func (p *AddressPool) Next() (*net.TCPAddr, string, error) {
	// Have we exhausted the address list we had?
	if p.addresses == nil {
		p.addresses = make([]*net.TCPAddr, 0)
		if err := p.populateAddresses(); err != nil {
			p.addresses = nil
			return nil, "", err
		}
	}

	next := p.addresses[0]
	if len(p.addresses) > 1 {
		p.addresses = p.addresses[1:]
	} else {
		p.addresses = nil
	}

	var desc string
	if p.host_is_ip {
		desc = fmt.Sprintf("%s", next)
	} else {
		desc = fmt.Sprintf("%s (%s)", next, p.host)
	}

	return next, desc, nil
}

func (p *AddressPool) NextServer() (string, error) {
	// Round robin to the next server
	selected := p.servers[p.roundrobin%len(p.servers)]
	p.roundrobin++

	// @hostname means SRV record where the host and port are in the record
	if len(selected) > 0 && selected[0] == '@' {
		srvs, err := p.processSrv(selected[1:])
		if err != nil {
			return "", err
		}
		return net.JoinHostPort(srvs[0].Target, strconv.FormatUint(uint64(srvs[0].Port), 10)), nil
	}

	return selected, nil
}

func (p *AddressPool) Host() string {
	return p.host
}

func (p *AddressPool) populateAddresses() (error) {
	// Round robin to the next server
	selected := p.servers[p.roundrobin%len(p.servers)]
	p.roundrobin++

	// @hostname means SRV record where the host and port are in the record
	if len(selected) > 0 && selected[0] == '@' {
		srvs, err := p.processSrv(selected[1:])
		if err != nil {
			return err
		}

		for _, srv := range srvs {
			if _, err := p.populateLookup(srv.Target, int(srv.Port)); err != nil {
				return err
			}
		}

		return nil
	}

	// Standard host:port declaration
	var port_str string
	var port uint64
	var err error
	if p.host, port_str, err = net.SplitHostPort(selected); err != nil {
		return fmt.Errorf("Invalid hostport given: %s", selected)
	}

	if port, err = strconv.ParseUint(port_str, 10, 16); err != nil {
		return fmt.Errorf("Invalid port given: %s", port_str)
	}

	if p.host_is_ip, err = p.populateLookup(p.host, int(port)); err != nil {
		return err
	}

	return nil
}

func (p *AddressPool) processSrv(server string) ([]*net.SRV, error) {
	var service, protocol string

	p.host = server
	p.host_is_ip = false

	if p.rfc2782 {
		service, protocol = p.rfc2782Service, "tcp"
	} else {
		service, protocol = "", ""
	}

	_, srvs, err := net.LookupSRV(service, protocol, p.host)
	if err != nil {
		return nil, fmt.Errorf("DNS SRV lookup failure \"%s\": %s", p.host, err)
	} else if len(srvs) == 0 {
		return nil, fmt.Errorf("DNS SRV lookup failure \"%s\": No targets found", p.host)
	}

	return srvs, nil
}

func (p *AddressPool) populateLookup(host string, port int) (bool, error) {
	if ip := net.ParseIP(host); ip != nil {
		// IP address
		p.addresses = append(p.addresses, &net.TCPAddr{
			IP:   ip,
			Port: port,
		})

		return true, nil
	}

	// Lookup the hostname in DNS
	ips, err := net.LookupIP(host)
	if err != nil {
		return false, fmt.Errorf("DNS lookup failure \"%s\": %s", host, err)
	} else if len(ips) == 0 {
		return false, fmt.Errorf("DNS lookup failure \"%s\": No addresses found", host)
	}

	for _, ip := range ips {
		p.addresses = append(p.addresses, &net.TCPAddr{
			IP:   ip,
			Port: port,
		})
	}

	return false, nil
}
<commit_msg>Implement server shuffing Fixes #161<commit_after>/*
 * Copyright 2014 Jason Woods.
 *
 * This file is a modification of code from Logstash Forwarder.
 * Copyright 2012-2013 Jordan Sissel and contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package transports

import (
	"fmt"
	"net"
	"math/rand"
	"strconv"
	"time"
)

type AddressPool struct {
	servers        []string
	rfc2782        bool
	rfc2782Service string
	roundrobin     int
	host_is_ip     bool
	host           string
	addresses      []*net.TCPAddr
}

func init() {
	rand.Seed(time.Now().UnixNano())
}

func NewAddressPool(servers []string) *AddressPool {
	ret := &AddressPool{
		servers: servers,
	}

	ret.shuffleServers()

	return ret
}

func (p *AddressPool) shuffleServers() {
	var newList []string
	oldList := p.servers
	for _, v := range rand.Perm(len(oldList)) {
		newList = append(newList, oldList[v])
	}
	p.servers = newList
}

func (p *AddressPool) SetRfc2782(enabled bool, service string) {
	p.rfc2782 = enabled
	p.rfc2782Service = service
}

func (p *AddressPool) IsLast() bool {
	return p.addresses == nil
}

func (p *AddressPool) IsLastServer() bool {
	return p.roundrobin%len(p.servers) == 0
}

func (p *AddressPool) Next() (*net.TCPAddr, string, error) {
	// Have we exhausted the address list we had?
	if p.addresses == nil {
		p.addresses = make([]*net.TCPAddr, 0)
		if err := p.populateAddresses(); err != nil {
			p.addresses = nil
			return nil, "", err
		}
	}

	next := p.addresses[0]
	if len(p.addresses) > 1 {
		p.addresses = p.addresses[1:]
	} else {
		p.addresses = nil
	}

	var desc string
	if p.host_is_ip {
		desc = fmt.Sprintf("%s", next)
	} else {
		desc = fmt.Sprintf("%s (%s)", next, p.host)
	}

	return next, desc, nil
}

func (p *AddressPool) NextServer() (string, error) {
	// Round robin to the next server
	selected := p.servers[p.roundrobin%len(p.servers)]
	p.roundrobin++

	// @hostname means SRV record where the host and port are in the record
	if len(selected) > 0 && selected[0] == '@' {
		srvs, err := p.processSrv(selected[1:])
		if err != nil {
			return "", err
		}
		return net.JoinHostPort(srvs[0].Target, strconv.FormatUint(uint64(srvs[0].Port), 10)), nil
	}

	return selected, nil
}

func (p *AddressPool) Host() string {
	return p.host
}

func (p *AddressPool) populateAddresses() (error) {
	// If we've iterated all servers, shuffle them again
	if p.roundrobin >= len(p.servers) {
		p.shuffleServers()
		p.roundrobin = 0
	}

	// Round robin to the next server
	selected := p.servers[p.roundrobin]
	p.roundrobin++

	// @hostname means SRV record where the host and port are in the record
	if len(selected) > 0 && selected[0] == '@' {
		srvs, err := p.processSrv(selected[1:])
		if err != nil {
			return err
		}

		for _, srv := range srvs {
			if _, err := p.populateLookup(srv.Target, int(srv.Port)); err != nil {
				return err
			}
		}

		return nil
	}

	// Standard host:port declaration
	var port_str string
	var port uint64
	var err error
	if p.host, port_str, err = net.SplitHostPort(selected); err != nil {
		return fmt.Errorf("Invalid hostport given: %s", selected)
	}

	if port, err = strconv.ParseUint(port_str, 10, 16); err != nil {
		return fmt.Errorf("Invalid port given: %s", port_str)
	}

	if p.host_is_ip, err = p.populateLookup(p.host, int(port)); err != nil {
		return err
	}

	return nil
}

func (p *AddressPool) processSrv(server string) ([]*net.SRV, error) {
	var service, protocol string

	p.host = server
	p.host_is_ip = false

	if p.rfc2782 {
		service, protocol = p.rfc2782Service, "tcp"
	} else {
		service, protocol = "", ""
	}

	_, srvs, err := net.LookupSRV(service, protocol, p.host)
	if err != nil {
		return nil, fmt.Errorf("DNS SRV lookup failure \"%s\": %s", p.host, err)
	} else if len(srvs) == 0 {
		return nil, fmt.Errorf("DNS SRV lookup failure \"%s\": No targets found", p.host)
	}

	return srvs, nil
}

func (p *AddressPool) populateLookup(host string, port int) (bool, error) {
	if ip := net.ParseIP(host); ip != nil {
		// IP address
		p.addresses = append(p.addresses, &net.TCPAddr{
			IP:   ip,
			Port: port,
		})

		return true, nil
	}

	// Lookup the hostname in DNS
	ips, err := net.LookupIP(host)
	if err != nil {
		return false, fmt.Errorf("DNS lookup failure \"%s\": %s", host, err)
	} else if len(ips) == 0 {
		return false, fmt.Errorf("DNS lookup failure \"%s\": No addresses found", host)
	}

	for _, ip := range ips {
		p.addresses = append(p.addresses, &net.TCPAddr{
			IP:   ip,
			Port: port,
		})
	}

	return false, nil
}
<|endoftext|>