<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/ae6rt/decap/web/api/v1"
	"github.com/ae6rt/decap/web/gittools"
	"github.com/ae6rt/decap/web/retry"
)

const buildScriptRegex = `build\.sh`
const projectDescriptorRegex = `project\.json`
const sideCarRegex = `^.+-sidecar\.json`

var projectSetChan = make(chan map[string]v1.Project)
var projectGetChan = make(chan map[string]v1.Project)

func projectMux(initialValue map[string]v1.Project) {
	t := initialValue
	Log.Print("Project channel mux running")
	for {
		select {
		case t = <-projectSetChan:
		case projectGetChan <- t:
		}
	}
}

func filesByRegex(root, expression string) ([]string, error) {
	if !strings.HasPrefix(root, "/") {
		return nil, fmt.Errorf("Root must be an absolute path: %s\n", root)
	}
	if strings.HasSuffix(root, "/") {
		return nil, fmt.Errorf("Root must not end in /: %s\n", root)
	}

	regex, err := regexp.Compile(expression)
	if err != nil {
		return nil, err
	}

	// files of interest reside at a fixed depth of 3 below root
	slashOffset := strings.Count(root, "/") + 3

	var files []string
	markFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if strings.HasPrefix(path, ".git") {
			return filepath.SkipDir
		}

		// record this as a too-deep path we never want to traverse again
		if info.IsDir() && strings.Count(path, "/") > slashOffset {
			return filepath.SkipDir
		}

		if strings.Count(path, "/") == slashOffset && info.Mode().IsRegular() && regex.MatchString(info.Name()) {
			files = append(files, path)
		}
		return nil
	}

	// Walk relative to root.
	err = filepath.Walk(root, markFn)
	if err != nil {
		return nil, err
	}

	return files, nil
}

func assembleProjects(scriptsRepo, scriptsRepoBranch string) (map[string]v1.Project, error) {
	projects := make(map[string]v1.Project, 0)
	work := func() error {
		Log.Printf("Clone build-scripts repository...\n")
		cloneDirectory, err := ioutil.TempDir("", "repoclone-")
		defer func() {
			if err := os.RemoveAll(cloneDirectory); err != nil {
				Log.Printf("assembleProjects(%s,%s) error removing clone directory %s: %v\n", scriptsRepo, scriptsRepoBranch, cloneDirectory, err)
			}
		}()

		if err != nil {
			return err
		}
		if err := gittools.Clone(scriptsRepo, scriptsRepoBranch, cloneDirectory, true); err != nil {
			return err
		}

		// Build scripts are the anchors for a project.  If build.sh does not exist the project is skipped.
		buildScripts, err := filesByRegex(cloneDirectory, buildScriptRegex)
		if err != nil {
			return err
		}
		descriptorFiles, err := filesByRegex(cloneDirectory, projectDescriptorRegex)
		if err != nil {
			return err
		}
		sidecarFiles, err := filesByRegex(cloneDirectory, sideCarRegex)
		if err != nil {
			return err
		}

		buildScriptMap := indexFilesByTeamProject(buildScripts)
		descriptorMap := indexFilesByTeamProject(descriptorFiles)
		sidecarMap := indexSidecarsByTeamProject(sidecarFiles)

		for k, _ := range buildScriptMap {
			if _, present := descriptorMap[k]; !present {
				Log.Printf("Skipping project without a descriptor: %s\n", k)
				continue
			}

			descriptorData, err := ioutil.ReadFile(descriptorMap[k])
			if err != nil {
				Log.Println(err)
				continue
			}

			descriptor, err := descriptorForTeamProject(descriptorData)
			if err != nil {
				Log.Println(err)
				continue
			}
			if descriptor.Image == "" {
				Log.Printf("Skipping project %s without descriptor build image: %+v\n", k, descriptor)
				continue
			}

			sidecars := readSidecars(sidecarMap[k])

			parts := strings.Split(k, "/")
			p := v1.Project{
				Team:        parts[0],
				ProjectName: parts[1],
				Descriptor:  descriptor,
				Sidecars:    sidecars,
			}
			projects[k] = p
		}
		return nil
	}

	err := retry.New(5, func(attempts int) {
		if attempts == 0 {
			return
		}
		Log.Printf("Wait for clone-repository with-backoff try %d\n", attempts+1)
		time.Sleep((1 << uint(attempts)) * time.Second)
	}).Try(work)

	if err != nil {
		return nil, err
	}
	return projects, nil
}

func getProjects() map[string]v1.Project {
	p := <-projectGetChan
	pm := make(map[string]v1.Project, len(p))
	for k, v := range p {
		pm[k] = v
	}
	return pm
}

func setProjects(p map[string]v1.Project) {
	projectSetChan <- p
}

func projectByTeamName(team, project string) (v1.Project, bool) {
	projects := getProjects()
	key := projectKey(team, project)
	p, ok := projects[key]
	return p, ok
}

func projectKey(team, project string) string {
	return fmt.Sprintf("%s/%s", team, project)
}

func teamProject(file string) (string, string, error) {
	parts := strings.Split(file, "/")
	if len(parts) < 3 {
		return "", "", fmt.Errorf("Path does not contain minimum depth of 3: %s", file)
	}
	return parts[len(parts)-3], parts[len(parts)-2], nil
}

func indexFilesByTeamProject(files []string) map[string]string {
	m := make(map[string]string)
	for _, file := range files {
		team, project, err := teamProject(file)
		if err != nil {
			Log.Println(err)
			continue
		}
		key := projectKey(team, project)
		m[key] = file
	}
	return m
}

func indexSidecarsByTeamProject(files []string) map[string][]string {
	m := make(map[string][]string)
	for _, file := range files {
		team, project, err := teamProject(file)
		if err != nil {
			Log.Println(err)
			continue
		}
		key := projectKey(team, project)
		arr, present := m[key]
		if !present {
			arr = make([]string, 0)
		}
		arr = append(arr, file)
		m[key] = arr
	}
	return m
}

func readSidecars(files []string) []string {
	arr := make([]string, len(files))
	for i, v := range files {
		data, err := ioutil.ReadFile(v)
		if err != nil {
			Log.Println(err)
			continue
		}
		arr[i] = string(data)
	}
	return arr
}

func descriptorForTeamProject(data []byte) (v1.ProjectDescriptor, error) {
	var descriptor v1.ProjectDescriptor
	if err := json.Unmarshal(data, &descriptor); err != nil {
		return v1.ProjectDescriptor{}, err
	}

	if descriptor.ManagedRefRegexStr != "" {
		if re, err := regexp.Compile(descriptor.ManagedRefRegexStr); err != nil {
			Log.Printf("Error parsing managed-branch-regex %s for descriptor %+v: %v\n", descriptor.ManagedRefRegexStr, data, err)
		} else {
			descriptor.Regex = re
		}
	}

	return descriptor, nil
}
<commit_msg>[dynamo-locks] inline git clone, and stop using an external package.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/ae6rt/decap/web/api/v1"
	"github.com/ae6rt/decap/web/retry"
)

const buildScriptRegex = `build\.sh`
const projectDescriptorRegex = `project\.json`
const sideCarRegex = `^.+-sidecar\.json`

var projectSetChan = make(chan map[string]v1.Project)
var projectGetChan = make(chan map[string]v1.Project)

func projectMux(initialValue map[string]v1.Project) {
	t := initialValue
	Log.Print("Project channel mux running")
	for {
		select {
		case t = <-projectSetChan:
		case projectGetChan <- t:
		}
	}
}

func filesByRegex(root, expression string) ([]string, error) {
	if !strings.HasPrefix(root, "/") {
		return nil, fmt.Errorf("Root must be an absolute path: %s\n", root)
	}
	if strings.HasSuffix(root, "/") {
		return nil, fmt.Errorf("Root must not end in /: %s\n", root)
	}

	regex, err := regexp.Compile(expression)
	if err != nil {
		return nil, err
	}

	// files of interest reside at a fixed depth of 3 below root
	slashOffset := strings.Count(root, "/") + 3

	var files []string
	markFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if strings.HasPrefix(path, ".git") {
			return filepath.SkipDir
		}

		// record this as a too-deep path we never want to traverse again
		if info.IsDir() && strings.Count(path, "/") > slashOffset {
			return filepath.SkipDir
		}

		if strings.Count(path, "/") == slashOffset && info.Mode().IsRegular() && regex.MatchString(info.Name()) {
			files = append(files, path)
		}
		return nil
	}

	// Walk relative to root.
	err = filepath.Walk(root, markFn)
	if err != nil {
		return nil, err
	}

	return files, nil
}

func assembleProjects(scriptsRepo, scriptsRepoBranch string) (map[string]v1.Project, error) {
	projects := make(map[string]v1.Project, 0)
	work := func() error {
		Log.Printf("Clone build-scripts repository...\n")
		cloneDirectory, err := ioutil.TempDir("", "repoclone-")
		defer func() {
			if err := os.RemoveAll(cloneDirectory); err != nil {
				Log.Printf("assembleProjects(%s,%s) error removing clone directory %s: %v\n", scriptsRepo, scriptsRepoBranch, cloneDirectory, err)
			}
		}()

		if err != nil {
			return err
		}
		if err := clone(scriptsRepo, scriptsRepoBranch, cloneDirectory, true); err != nil {
			return err
		}

		// Build scripts are the anchors for a project.  If build.sh does not exist the project is skipped.
		buildScripts, err := filesByRegex(cloneDirectory, buildScriptRegex)
		if err != nil {
			return err
		}
		descriptorFiles, err := filesByRegex(cloneDirectory, projectDescriptorRegex)
		if err != nil {
			return err
		}
		sidecarFiles, err := filesByRegex(cloneDirectory, sideCarRegex)
		if err != nil {
			return err
		}

		buildScriptMap := indexFilesByTeamProject(buildScripts)
		descriptorMap := indexFilesByTeamProject(descriptorFiles)
		sidecarMap := indexSidecarsByTeamProject(sidecarFiles)

		for k, _ := range buildScriptMap {
			if _, present := descriptorMap[k]; !present {
				Log.Printf("Skipping project without a descriptor: %s\n", k)
				continue
			}

			descriptorData, err := ioutil.ReadFile(descriptorMap[k])
			if err != nil {
				Log.Println(err)
				continue
			}

			descriptor, err := descriptorForTeamProject(descriptorData)
			if err != nil {
				Log.Println(err)
				continue
			}
			if descriptor.Image == "" {
				Log.Printf("Skipping project %s without descriptor build image: %+v\n", k, descriptor)
				continue
			}

			sidecars := readSidecars(sidecarMap[k])

			parts := strings.Split(k, "/")
			p := v1.Project{
				Team:        parts[0],
				ProjectName: parts[1],
				Descriptor:  descriptor,
				Sidecars:    sidecars,
			}
			projects[k] = p
		}
		return nil
	}

	err := retry.New(5, func(attempts int) {
		if attempts == 0 {
			return
		}
		Log.Printf("Wait for clone-repository with-backoff try %d\n", attempts+1)
		time.Sleep((1 << uint(attempts)) * time.Second)
	}).Try(work)

	if err != nil {
		return nil, err
	}
	return projects, nil
}

func getProjects() map[string]v1.Project {
	p := <-projectGetChan
	pm := make(map[string]v1.Project, len(p))
	for k, v := range p {
		pm[k] = v
	}
	return pm
}

func setProjects(p map[string]v1.Project) {
	projectSetChan <- p
}

func projectByTeamName(team, project string) (v1.Project, bool) {
	projects := getProjects()
	key := projectKey(team, project)
	p, ok := projects[key]
	return p, ok
}

func projectKey(team, project string) string {
	return fmt.Sprintf("%s/%s", team, project)
}

func teamProject(file string) (string, string, error) {
	parts := strings.Split(file, "/")
	if len(parts) < 3 {
		return "", "", fmt.Errorf("Path does not contain minimum depth of 3: %s", file)
	}
	return parts[len(parts)-3], parts[len(parts)-2], nil
}

func indexFilesByTeamProject(files []string) map[string]string {
	m := make(map[string]string)
	for _, file := range files {
		team, project, err := teamProject(file)
		if err != nil {
			Log.Println(err)
			continue
		}
		key := projectKey(team, project)
		m[key] = file
	}
	return m
}

func indexSidecarsByTeamProject(files []string) map[string][]string {
	m := make(map[string][]string)
	for _, file := range files {
		team, project, err := teamProject(file)
		if err != nil {
			Log.Println(err)
			continue
		}
		key := projectKey(team, project)
		arr, present := m[key]
		if !present {
			arr = make([]string, 0)
		}
		arr = append(arr, file)
		m[key] = arr
	}
	return m
}

func readSidecars(files []string) []string {
	arr := make([]string, len(files))
	for i, v := range files {
		data, err := ioutil.ReadFile(v)
		if err != nil {
			Log.Println(err)
			continue
		}
		arr[i] = string(data)
	}
	return arr
}

func descriptorForTeamProject(data []byte) (v1.ProjectDescriptor, error) {
	var descriptor v1.ProjectDescriptor
	if err := json.Unmarshal(data, &descriptor); err != nil {
		return v1.ProjectDescriptor{}, err
	}

	if descriptor.ManagedRefRegexStr != "" {
		if re, err := regexp.Compile(descriptor.ManagedRefRegexStr); err != nil {
			Log.Printf("Error parsing managed-branch-regex %s for descriptor %+v: %v\n", descriptor.ManagedRefRegexStr, data, err)
		} else {
			descriptor.Regex = re
		}
	}

	return descriptor, nil
}

// Clone clones the Git repository at repositoryURL at the given branch into the given directory.  If shallow is true, use --depth 1.
func clone(repositoryURL, branch, dir string, shallow bool) error {
	args := []string{"clone"}
	if shallow {
		args = append(args, []string{"--depth", "1"}...)
	}
	args = append(args, []string{"--branch", branch, repositoryURL, dir}...)
	return executeShellCommand("git", args)
}

func executeShellCommand(commandName string, args []string) error {
	Log.Printf("Executing %s %+v\n", commandName, args)
	command := exec.Command(commandName, args...)
	var stdOutErr []byte
	var err error
	stdOutErr, err = command.CombinedOutput()
	if err != nil {
		return err
	}
	Log.Printf("%v\n", string(stdOutErr))

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"log"
	"net/http"
	"io"
	"sync"
	"strings"
	"os/exec"
	"fmt"
	"encoding/xml"
	"io/ioutil"
	"encoding/json"
	"bytes"
	"flag"
	"path/filepath"
	"mime/multipart"
	"net/url"

	"github.com/gorilla/mux"
)

type Config struct {
	Port       int `xml:"port"`
	Slic3rPath string `xml:"slic3rPath"`
}

var config = Config{}
//Declare flags
var debugFlag = flag.Bool("debug", false, "If set debug output will print")
var portFlag = flag.Int("port", 0, "If set slic3r server will bind to given port and will override config file")
var slic3rPathFlag = flag.String("", "slic3r", "If set slic3r server will use given sli3r path and will override config file")

func main() {
	log.Println("Starting Slic3r Server")
	//Parse flags
	flag.Parse()
	//Generate Directories
	if _, err := os.Stat("stl"); os.IsNotExist(err) {
		if (*debugFlag) {
			log.Println("Making STL Directory")
		}
		os.Mkdir("stl", 0777)
	}
	if _, err := os.Stat("gcode"); os.IsNotExist(err) {
		if *debugFlag {
			log.Println("Making Gcode Directory")
		}
		os.Mkdir("gcode", 0777)
	}
	//Create config file if does not exist
	if _, err := os.Stat("config.xml"); os.IsNotExist(err) {
		if *debugFlag {
			log.Println("Making config")
		}
		config.Port = 7766
		config.Slic3rPath = "slic3r"
		xml, err := xml.MarshalIndent(config, "", "    ")
		if err != nil {
			panic(err)
			return
		}
		err = ioutil.WriteFile("config.xml", xml, 0666)
		if err != nil {
			panic(err)
			return
		}
	} else {
		//Read config file if does exist
		data, err := ioutil.ReadFile("config.xml")
		if err != nil || string(data) == "" {
			panic(err)
			return
		}
		if err = xml.Unmarshal(data, &config); err != nil {
			panic(err)
			return
		}
	}
	//Override config with flags if set
	if *portFlag != 0 {
		config.Port = *portFlag
	}
	if *slic3rPathFlag != "" {
		config.Slic3rPath = *slic3rPathFlag
	}
	//Start HTTP server
	router := mux.NewRouter()
	router.HandleFunc("/slice", sliceHandler).Methods("POST")
	router.Handle("/gcode/{name}", http.StripPrefix("/gcode/", http.FileServer(http.Dir("gcode")))).Methods("GET")
	router.Handle("/stl/{name}", http.StripPrefix("/stl/", http.FileServer(http.Dir("stl")))).Methods("GET")
	router.HandleFunc("/{stl|gcode}", fileListHandler).Methods("GET")
	router.HandleFunc("/{stl|gcode}", clearFilesHandler).Methods("DELETE")
	router.HandleFunc("/{type:stl|gcode}/{name}", deleteFileHandler).Methods("DELETE")
	http.Handle("/", router)
	log.Printf("Slic3r Server binding to port: %d\n", config.Port)
	http.ListenAndServe(fmt.Sprintf(":%d", config.Port), nil)
}

func fileListHandler(writer http.ResponseWriter, request *http.Request) {
	files, err := ioutil.ReadDir("." + request.URL.String())
	if err != nil {
		http.Error(writer, "Could not get file list", 500)
		log.Println(err)
		return
	}
	var fileList []string
	for _, file := range files {
		fileList = append(fileList, file.Name())
	}
	data, err := json.MarshalIndent(fileList, "", "    ")
	if err != nil {
		http.Error(writer, "Could not get file list", 500)
		log.Println(err)
		return
	}
	writer.Write(data)
}

func deleteFileHandler(writer http.ResponseWriter, request *http.Request)  {
	vars := mux.Vars(request)
	fileType := vars["type"]
	fileName := vars["name"]
	if err := os.Remove("./" + fileType + "/" + fileName); err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete file", 500)
		return
	}
	writer.WriteHeader(204)
}

func clearFilesHandler(writer http.ResponseWriter, request *http.Request) {
	d, err := os.Open("." + request.URL.String())
	if err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete files", 500)
		return
	}
	defer d.Close()
	names, err := d.Readdirnames(-1)
	if err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete files", 500)
		return
	}
	for _, name := range names {
		err = os.RemoveAll(filepath.Join("." + request.URL.String(), name))
		if err != nil {
			log.Println(err)
			http.Error(writer, "Failed to delete files", 500)
			return
		}
	}
	writer.WriteHeader(204)
}

func sliceHandler(writer http.ResponseWriter, request *http.Request) {
	//Reject request if it is not a POST request
	if request.Method != "POST" {
		http.Error(writer, "Request is not a POST request", 400)
		return
	}
	//Get form data
	request.ParseMultipartForm(32 << 20)
	var otherArgs, callbackType, callbackURL string
	var wait bool
	for key, value := range request.Form {
		if key == "callback" && len(value) > 0 {
			tmp := strings.Split(value[0], ",")
			callbackType = tmp[0]
			callbackURL = tmp[1]
		} else if key == "wait" && len(value) > 0 {
			if value[0] == "true" {
				wait = true
			}
			if value[0] != "true" && value[0] != "false" {
				http.Error(writer, "Invalid value given for wait", 400)
				return
			}
		} else {
			if (len(value) > 0) {
				otherArgs += fmt.Sprintf(" --%s %s", key, value[0])
			} else {
				otherArgs += fmt.Sprintf(" --%s", key)
			}
		}
	}
	//Check if request is valid
	if (callbackType != "" && callbackType != "url" && callbackType != "file") {
		http.Error(writer, "Invalid callback type", 400)
		return
	}
	if (callbackURL != "") {
		_, err := url.Parse(callbackURL)
		if (err != nil) {
			http.Error(writer, "Invalid callback URL", 400)
			return
		}
	}
	//Get STL file
	tmpFile, header, err := request.FormFile("file")
	if err != nil {
		log.Println(err)
		http.Error(writer, "Could not parse file form request", 400)
		return
	}
	defer tmpFile.Close()
	fileName := header.Filename[:(len(header.Filename) - 4)]
	file, err := os.OpenFile("stl/" + header.Filename, os.O_WRONLY | os.O_CREATE, 0666)
	if err != nil {
		log.Println(err)
		http.Error(writer, "Could not open file: stl/" + header.Filename, 500)
		return
	}
	io.Copy(file, tmpFile)
	file.Close()
	//Run slic3r with STL file and args
	args := fmt.Sprintf(" stl/%s.stl %s --output gcode/%s.gcode", fileName, otherArgs, fileName)
	wg := new(sync.WaitGroup)
	wg.Add(1)
	go exe_cmd(config.Slic3rPath + args, wg)
	gcodeFile := "/gcode/" + fileName + ".gcode"
	//Wait if needed
	if (!wait) {
		writer.Write([]byte(gcodeFile))
	}else if (wait && callbackURL == "") {
		wg.Wait()
		writer.Write([]byte(gcodeFile))
	}
	//Run callback
	if (callbackType == "url" && callbackURL != "") {
		wg.Wait()
		req, err := http.NewRequest("POST", callbackURL, bytes.NewBuffer([]byte(gcodeFile)))
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		client := &http.Client{}
		_, err = client.Do(req)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		if (wait) {
			writer.Write([]byte(gcodeFile))
		}
	} else if (callbackType == "file" && callbackURL != "") {
		wg.Wait()
		file, err := os.Open(gcodeFile[1:len(gcodeFile)])
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		defer file.Close()
		body := &bytes.Buffer{}
		mpWriter := multipart.NewWriter(body)
		part, err := mpWriter.CreateFormFile("file", filepath.Base(gcodeFile[1:len(gcodeFile)]))
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		_, err = io.Copy(part, file)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		err = mpWriter.Close()
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		req, err := http.NewRequest("POST", callbackURL, body)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		req.Header.Set("Content-Type", mpWriter.FormDataContentType())
		client := &http.Client{}
		_, err = client.Do(req)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		if (wait) {
			writer.Write([]byte(gcodeFile))
		}
	}
}

func exe_cmd(cmd string, wg *sync.WaitGroup) {
	if (*debugFlag) {
		log.Println("executing: ", cmd)
	}
	parts := strings.Fields(cmd)
	head := parts[0]
	parts = parts[1:len(parts)]

	out, err := exec.Command(head, parts...).Output()
	if err != nil {
		log.Printf("%s\n", err)
	}
	if (*debugFlag) {
		log.Printf("%s\n", out)
	}
	wg.Done()
}

<commit_msg>Moved setup into functions<commit_after>package main

import (
	"os"
	"log"
	"net/http"
	"io"
	"sync"
	"strings"
	"os/exec"
	"fmt"
	"encoding/xml"
	"io/ioutil"
	"encoding/json"
	"bytes"
	"flag"
	"path/filepath"
	"mime/multipart"
	"net/url"

	"github.com/gorilla/mux"
)

type Config struct {
	Port       int `xml:"port"`
	Slic3rPath string `xml:"slic3rPath"`
}

var config = Config{}
//Declare flags
var debugFlag = flag.Bool("debug", false, "If set debug output will print")
var portFlag = flag.Int("port", 0, "If set slic3r server will bind to given port and will override config file")
var slic3rPathFlag = flag.String("", "slic3r", "If set slic3r server will use given sli3r path and will override config file")

func main() {
	log.Println("Starting Slic3r Server")
	//Parse flags
	flag.Parse()
	server := NewServer()
	if server == nil {
		panic("Server creation failed")
	}
	http.Handle("/", server)
	log.Printf("Slic3r Server binding to port: %d\n", config.Port)
	http.ListenAndServe(fmt.Sprintf(":%d", config.Port), nil)
}

func NewServer() *mux.Router{
	//Generate Directories
	if _, err := os.Stat("stl"); os.IsNotExist(err) {
		if (*debugFlag) {
			log.Println("Making STL Directory")
		}
		os.Mkdir("stl", 0777)
	}
	if _, err := os.Stat("gcode"); os.IsNotExist(err) {
		if *debugFlag {
			log.Println("Making Gcode Directory")
		}
		os.Mkdir("gcode", 0777)
	}
	//Create config file if does not exist
	if _, err := os.Stat("config.xml"); os.IsNotExist(err) {
		if *debugFlag {
			log.Println("Making config")
		}
		config.Port = 7766
		config.Slic3rPath = "slic3r"
		xml, err := xml.MarshalIndent(config, "", "    ")
		if err != nil {
			panic(err)
			return nil
		}
		err = ioutil.WriteFile("config.xml", xml, 0666)
		if err != nil {
			panic(err)
			return nil
		}
	} else {
		//Read config file if does exist
		data, err := ioutil.ReadFile("config.xml")
		if err != nil || string(data) == "" {
			panic(err)
			return nil
		}
		if err = xml.Unmarshal(data, &config); err != nil {
			panic(err)
			return nil
		}
		if *debugFlag {
			log.Println(config)
		}
	}
	//Override config with flags if set
	if *portFlag != 0 {
		config.Port = *portFlag
	}
	if *slic3rPathFlag != "" {
		config.Slic3rPath = *slic3rPathFlag
	}

	//Start HTTP server
	router := mux.NewRouter()
	router.HandleFunc("/slice", sliceHandler).Methods("POST")
	router.Handle("/gcode/{name}", http.StripPrefix("/gcode/", http.FileServer(http.Dir("gcode")))).Methods("GET")
	router.Handle("/stl/{name}", http.StripPrefix("/stl/", http.FileServer(http.Dir("stl")))).Methods("GET")
	router.HandleFunc("/{stl|gcode}", fileListHandler).Methods("GET")
	router.HandleFunc("/{stl|gcode}", clearFilesHandler).Methods("DELETE")
	router.HandleFunc("/{type:stl|gcode}/{name}", deleteFileHandler).Methods("DELETE")

	return router
}

func fileListHandler(writer http.ResponseWriter, request *http.Request) {
	files, err := ioutil.ReadDir("." + request.URL.String())
	if err != nil {
		http.Error(writer, "Could not get file list", 500)
		log.Println(err)
		return
	}
	var fileList []string
	for _, file := range files {
		fileList = append(fileList, file.Name())
	}
	data, err := json.MarshalIndent(fileList, "", "    ")
	if err != nil {
		http.Error(writer, "Could not get file list", 500)
		log.Println(err)
		return
	}
	writer.Write(data)
}

func deleteFileHandler(writer http.ResponseWriter, request *http.Request) {
	vars := mux.Vars(request)
	fileType := vars["type"]
	fileName := vars["name"]
	if err := os.Remove("./" + fileType + "/" + fileName); err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete file", 500)
		return
	}
	writer.WriteHeader(204)
}

func clearFilesHandler(writer http.ResponseWriter, request *http.Request) {
	d, err := os.Open("." + request.URL.String())
	if err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete files", 500)
		return
	}
	defer d.Close()
	names, err := d.Readdirnames(-1)
	if err != nil {
		log.Println(err)
		http.Error(writer, "Failed to delete files", 500)
		return
	}
	for _, name := range names {
		err = os.RemoveAll(filepath.Join("." + request.URL.String(), name))
		if err != nil {
			log.Println(err)
			http.Error(writer, "Failed to delete files", 500)
			return
		}
	}
	writer.WriteHeader(204)
}

func sliceHandler(writer http.ResponseWriter, request *http.Request) {
	//Reject request if it is not a POST request
	if request.Method != "POST" {
		http.Error(writer, "Request is not a POST request", 400)
		return
	}
	//Get form data
	request.ParseMultipartForm(32 << 20)
	var otherArgs, callbackType, callbackURL string
	var wait bool
	for key, value := range request.Form {
		if key == "callback" && len(value) > 0 {
			tmp := strings.Split(value[0], ",")
			callbackType = tmp[0]
			callbackURL = tmp[1]
		} else if key == "wait" && len(value) > 0 {
			if value[0] == "true" {
				wait = true
			}
			if value[0] != "true" && value[0] != "false" {
				http.Error(writer, "Invalid value given for wait", 400)
				return
			}
		} else {
			if (len(value) > 0) {
				otherArgs += fmt.Sprintf(" --%s %s", key, value[0])
			} else {
				otherArgs += fmt.Sprintf(" --%s", key)
			}
		}
	}
	//Check if request is valid
	if (callbackType != "" && callbackType != "url" && callbackType != "file") {
		http.Error(writer, "Invalid callback type", 400)
		return
	}
	if (callbackURL != "") {
		_, err := url.Parse(callbackURL)
		if (err != nil) {
			http.Error(writer, "Invalid callback URL", 400)
			return
		}
	}
	//Get STL file
	tmpFile, header, err := request.FormFile("file")
	if err != nil {
		log.Println(err)
		http.Error(writer, "Could not parse file form request", 400)
		return
	}
	defer tmpFile.Close()
	fileName := header.Filename[:(len(header.Filename) - 4)]
	file, err := os.OpenFile("stl/" + header.Filename, os.O_WRONLY | os.O_CREATE, 0666)
	if err != nil {
		log.Println(err)
		http.Error(writer, "Could not open file: stl/" + header.Filename, 500)
		return
	}
	io.Copy(file, tmpFile)
	file.Close()
	//Run slic3r with STL file and args
	args := fmt.Sprintf(" stl/%s.stl %s --output gcode/%s.gcode", fileName, otherArgs, fileName)
	wg := new(sync.WaitGroup)
	wg.Add(1)
	go exe_cmd(config.Slic3rPath + args, wg)
	gcodeFile := "/gcode/" + fileName + ".gcode"
	//Wait if needed
	if (!wait) {
		writer.Write([]byte(gcodeFile))
	}else if (wait && callbackURL == "") {
		wg.Wait()
		writer.Write([]byte(gcodeFile))
	}
	//Run callback
	if (callbackType == "url" && callbackURL != "") {
		wg.Wait()
		req, err := http.NewRequest("POST", callbackURL, bytes.NewBuffer([]byte(gcodeFile)))
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		client := &http.Client{}
		_, err = client.Do(req)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		if (wait) {
			writer.Write([]byte(gcodeFile))
		}
	} else if (callbackType == "file" && callbackURL != "") {
		wg.Wait()
		file, err := os.Open(gcodeFile[1:len(gcodeFile)])
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		defer file.Close()
		body := &bytes.Buffer{}
		mpWriter := multipart.NewWriter(body)
		part, err := mpWriter.CreateFormFile("file", filepath.Base(gcodeFile[1:len(gcodeFile)]))
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		_, err = io.Copy(part, file)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		err = mpWriter.Close()
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		req, err := http.NewRequest("POST", callbackURL, body)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		req.Header.Set("Content-Type", mpWriter.FormDataContentType())
		client := &http.Client{}
		_, err = client.Do(req)
		if (err != nil) {
			log.Println(err)
			if (wait) {
				http.Error(writer, "Callback could not be completed", 500)
			}
			return
		}
		if (wait) {
			writer.Write([]byte(gcodeFile))
		}
	}
}

func exe_cmd(cmd string, wg *sync.WaitGroup) {
	if (*debugFlag) {
		log.Println("executing: ", cmd)
	}
	parts := strings.Fields(cmd)
	head := parts[0]
	parts = parts[1:len(parts)]

	out, err := exec.Command(head, parts...).Output()
	if err != nil {
		log.Printf("%s\n", err)
	}
	if (*debugFlag) {
		log.Printf("%s\n", out)
	}
	wg.Done()
}

<|endoftext|>


<commit_before>// Package leaderboard
package leaderboard

import (
	"errors"
	"sort"
)

type Color struct {
	R float32
	G float32
	B float32
}

type Player struct {
	Username string
	Team     struct {
		R float32
		G float32
		B float32
	}
	HomePlanet string
	Planets    uint32
}

type Team struct {
	Name    string
	Color   Color
	Players uint32
	Planets uint32
}

type Teams []*Team

type Leaderboard struct {
	places map[string]int
	board  []*Player
	teams  Teams
}

func New() *Leaderboard {
	l := new(Leaderboard)
	l.places = make(map[string]int)
	l.board = make([]*Player, 0)
	l.teams = make([]*Team, 0)
	return l
}

func (l *Leaderboard) Add(player *Player) {
	l.board = append(l.board, player)
	l.places[player.Username] = len(l.board) - 1

	for _, team := range l.teams {
		if player.Team == team.Color {
			team.Players++
			team.Planets += player.Planets
			return
		}
	}

	l.teams = append(l.teams, &Team{
		Name:    "Red Panda",
		Color:   player.Team,
		Players: 1,
		Planets: player.Planets,
	})
}

func (l *Leaderboard) FindTeam(color Color) *Team {
	for _, team := range l.teams {
		if team.Color == color {
			return team
		}
	}
	return nil
}

func (l *Leaderboard) Len() int {
	return len(l.board)
}

func (l *Leaderboard) Swap(i, j int) {
	l.board[i], l.board[j] = l.board[j], l.board[i]
}

func (l *Leaderboard) Less(i, j int) bool {
	return l.board[i].Planets > l.board[j].Planets
}

func (l *Leaderboard) Sort() {
	sort.Sort(l)
	for index, player := range l.board {
		l.places[player.Username] = index
	}
}

func (l *Leaderboard) RecountTeamsPlanets() {
	for _, team := range l.teams {
		team.Planets = 0
	}

	for _, player := range l.board {
		team := l.FindTeam(player.Team)
		if team != nil {
			team.Planets += player.Planets
		}
	}
}

func (l *Leaderboard) Transfer(from_username, to_username string) {
	from, hasOwner := l.places[from_username]
	to := l.places[to_username]

	if hasOwner {
		l.board[from].Planets--
		l.moveDown(from_username)
		team := l.FindTeam(l.board[from].Team)
		if team != nil {
			team.Planets++
		}
	}

	l.board[to].Planets++
	l.moveUp(to_username)
	team := l.FindTeam(l.board[to].Team)
	if team != nil {
		team.Planets++
	}
	l.teams.Sort()
}

func (l *Leaderboard) Page(page int64) ([]*Player, error) {
	if page <= 0 {
		return []*Player{}, errors.New("No such page")
	}
	from := (page - 1) * 10
	to := ((page - 1) * 10) + 10
	if len(l.board) < int(from) {
		return []*Player{}, errors.New("No such page")
	}

	if len(l.board) < int(to) {
		to = int64(len(l.board))
	}
	return l.board[from:to], nil
}

func (l *Leaderboard) Place(username string) int {
	place, ok := l.places[username]
	if !ok {
		return 0
	}

	return place
}

func (l *Leaderboard) Teams() []*Team {
	return l.teams
}

func (l *Leaderboard) move(username string, modificator int) bool {
	firstBlood := true
	isMoved := false
	i := l.places[username]

	for isMoved || firstBlood {
		firstBlood = false
		if modificator < 0 && i == 0 || modificator > 0 && i == len(l.board)-1 {
			return false
		}

		if modificator < 0 {
			isMoved = l.Less(i, i+modificator)
		} else {
			isMoved = l.Less(i+modificator, i)
		}

		if isMoved {
			l.Swap(i, i+modificator)
			l.places[l.board[i].Username], l.places[l.board[i+modificator].Username] = i+modificator, i
		}
		i += modificator
	}
	return isMoved
}

func (l *Leaderboard) moveUp(username string) bool {
	return l.move(username, -1)
}

func (l *Leaderboard) moveDown(username string) bool {
	return l.move(username, 1)
}

func (t *Teams) Len() int {
	return len(*t)
}

func (t *Teams) Swap(i, j int) {
	(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
}

func (t *Teams) Less(i, j int) bool {
	return (*t)[i].Planets > (*t)[j].Planets
}

func (t *Teams) Sort() {
	sort.Sort(t)
}
<commit_msg>Sort teams after sorting players<commit_after>// Package leaderboard
package leaderboard

import (
	"errors"
	"sort"
)

type Color struct {
	R float32
	G float32
	B float32
}

type Player struct {
	Username string
	Team     struct {
		R float32
		G float32
		B float32
	}
	HomePlanet string
	Planets    uint32
}

type Team struct {
	Name    string
	Color   Color
	Players uint32
	Planets uint32
}

type Teams []*Team

type Leaderboard struct {
	places map[string]int
	board  []*Player
	teams  Teams
}

func New() *Leaderboard {
	l := new(Leaderboard)
	l.places = make(map[string]int)
	l.board = make([]*Player, 0)
	l.teams = make([]*Team, 0)
	return l
}

func (l *Leaderboard) Add(player *Player) {
	l.board = append(l.board, player)
	l.places[player.Username] = len(l.board) - 1

	for _, team := range l.teams {
		if player.Team == team.Color {
			team.Players++
			team.Planets += player.Planets
			return
		}
	}

	l.teams = append(l.teams, &Team{
		Name:    "Red Panda",
		Color:   player.Team,
		Players: 1,
		Planets: player.Planets,
	})
}

func (l *Leaderboard) FindTeam(color Color) *Team {
	for _, team := range l.teams {
		if team.Color == color {
			return team
		}
	}
	return nil
}

func (l *Leaderboard) Len() int {
	return len(l.board)
}

func (l *Leaderboard) Swap(i, j int) {
	l.board[i], l.board[j] = l.board[j], l.board[i]
}

func (l *Leaderboard) Less(i, j int) bool {
	return l.board[i].Planets > l.board[j].Planets
}

func (l *Leaderboard) Sort() {
	sort.Sort(l)
	for index, player := range l.board {
		l.places[player.Username] = index
	}
	l.teams.Sort()
}

func (l *Leaderboard) RecountTeamsPlanets() {
	for _, team := range l.teams {
		team.Planets = 0
	}

	for _, player := range l.board {
		team := l.FindTeam(player.Team)
		if team != nil {
			team.Planets += player.Planets
		}
	}
}

func (l *Leaderboard) Transfer(from_username, to_username string) {
	from, hasOwner := l.places[from_username]
	to := l.places[to_username]

	if hasOwner {
		l.board[from].Planets--
		l.moveDown(from_username)
		team := l.FindTeam(l.board[from].Team)
		if team != nil {
			team.Planets++
		}
	}

	l.board[to].Planets++
	l.moveUp(to_username)
	team := l.FindTeam(l.board[to].Team)
	if team != nil {
		team.Planets++
	}
	l.teams.Sort()
}

func (l *Leaderboard) Page(page int64) ([]*Player, error) {
	if page <= 0 {
		return []*Player{}, errors.New("No such page")
	}
	from := (page - 1) * 10
	to := ((page - 1) * 10) + 10
	if len(l.board) < int(from) {
		return []*Player{}, errors.New("No such page")
	}

	if len(l.board) < int(to) {
		to = int64(len(l.board))
	}
	return l.board[from:to], nil
}

func (l *Leaderboard) Place(username string) int {
	place, ok := l.places[username]
	if !ok {
		return 0
	}

	return place
}

func (l *Leaderboard) Teams() []*Team {
	return l.teams
}

func (l *Leaderboard) move(username string, modificator int) bool {
	firstBlood := true
	isMoved := false
	i := l.places[username]

	for isMoved || firstBlood {
		firstBlood = false
		if modificator < 0 && i == 0 || modificator > 0 && i == len(l.board)-1 {
			return false
		}

		if modificator < 0 {
			isMoved = l.Less(i, i+modificator)
		} else {
			isMoved = l.Less(i+modificator, i)
		}

		if isMoved {
			l.Swap(i, i+modificator)
			l.places[l.board[i].Username], l.places[l.board[i+modificator].Username] = i+modificator, i
		}
		i += modificator
	}
	return isMoved
}

func (l *Leaderboard) moveUp(username string) bool {
	return l.move(username, -1)
}

func (l *Leaderboard) moveDown(username string) bool {
	return l.move(username, 1)
}

func (t *Teams) Len() int {
	return len(*t)
}

func (t *Teams) Swap(i, j int) {
	(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
}

func (t *Teams) Less(i, j int) bool {
	return (*t)[i].Planets > (*t)[j].Planets
}

func (t *Teams) Sort() {
	sort.Sort(t)
}
<|endoftext|>


<commit_before>package util

import (
	"os"
	"errors"
	"io/ioutil"
	"path/filepath"
)

type Replacer struct {
	Name string		// Name of the file being replaced
	Info os.FileInfo	// Timestamp of target file before replacement
	File *os.File		// Temporary file used for writing
}

var raceErr = errors.New("File was concurrently modified")

// Open a file to replace an existing file as safely as possible,
// attempting to avoid corruption on crash or concurrent writers.
//
// Creates a new temporary file in the same directory as the target,
// but does not actually touch the target until Close() is called.
// The caller can also call Abort() to close and delete the temporary file
// without replacing the original file.
//
// If r.Info is nil, sets it to the status of the target file
// at the time of this Open() call, for later race detection on Close().
// The caller can pre-set r.Info to a different timestamp
// to define the race-detection window explicitly:
// e.g., using an earlier timestamp obtained
// when the original file was first read.
//
// Something like this functionality might be useful to have in os.ioutil.
func (r *Replacer) Open(filename string) error {
	r.Name = filename

	// Save a time-stamp of the file we're replacing
	// so we can detect concurrent modifications.
	if r.Info == nil {
		info,err := os.Stat(filename)
		if err != nil {
			if !os.IsNotExist(err) {
				return err
			}
		}
		r.Info = info
	}

	// Create a temporary file in the same directory for the replacement
	dir := filepath.Dir(filename)
	pfx := filepath.Base(filename)
	file,err := ioutil.TempFile(dir,pfx)
	if err != nil {
		return err
	}
	r.File = file

	return nil
}

// Attempt to commit the temporary replacement file to the target.
// On success, Close()s the temporary file and atomically renames it
// to the target filename saved in the Name field.
//
// Returns an error if the target was modified by someone else
// in the time since the temporary file was created.
// In this case, the caller might for example call Abort()
// and create a new Replacer after accounting for the new modifications.
// Alternatively the caller might call ForceCommit() instead after
// warning the user that state might be lost and prompting for confirmation.
func (r *Replacer) Commit() error {

	// Make sure the file hasn't been concurrently modified.
	// Since this check is not atomic with the Rename below,
	// a race can still happen; this is only a heuristic.
	// OS-specific facilities would be needed to make it truly atomic.
	if r.Info != nil {
		info,err := os.Stat(r.Name)
		if err != nil {
			return err
		}
		if	info.Name() != r.Info.Name() ||
			info.Size() != r.Info.Size() ||
			info.ModTime() != r.Info.ModTime() {
			return raceErr
		}
	}

	// Close the tmpfile
	tmpname := r.File.Name()
	if err := r.File.Close(); err != nil {
		return err
	}

	// Atomically update the target filename
	if err := os.Rename(tmpname, r.Name); err != nil {
		return err
	}

	r.File = nil
	return nil
}

// Commit the temporary replacement file
// without checking for concurrent modifications in the meantime.
func (r *Replacer) ForceCommit() error {
	r.Info = nil
	return r.Commit()
}

// Abort replacement by closing and deleting the temporary file.
// It is harmless to call Abort() after the Replacer
// has already committed or aborted:
// thus, the caller may wish to 'defer r.Abort()' immediately after Open().
func (r *Replacer) Abort() {
	if r.File != nil {
		tmpname := r.File.Name()
		r.File.Close()
		r.File = nil
		os.Remove(tmpname)
	}
}

// Returns true if an error returned by Commit() indicates
// that the commit failed because a concurrent write was detected
// and the force flag was not specified.
func IsRace(err error) bool {
	return err == raceErr
}

<commit_msg>Removes Replace.go<commit_after><|endoftext|>


<commit_before>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package util

// VERSION identifies Khan's current version
var VERSION = "2.4.0"
<commit_msg>bump version to 2.5.0<commit_after>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package util

// VERSION identifies Khan's current version
var VERSION = "2.5.0"
<|endoftext|>


<commit_before>package utility

import (
	"encoding/json"
	"github.com/bitspill/bitsig-go"
	"github.com/btcsuite/btcutil"
)

var utilIsTestnet bool = false

func SetTestnet(testnet bool) {
	utilIsTestnet = testnet
}

func Testnet() bool {
	return utilIsTestnet
}

func CheckAddress(address string) bool {
	var err error
	if utilIsTestnet {
		_, err = btcutil.DecodeAddress(address, &FloTestnetParams)
	} else {
		_, err = btcutil.DecodeAddress(address, &FloParams)
	}
	if err != nil {
		return false
	}
	return true
}

func CheckSignature(address string, signature string, message string) (bool, error) {
	if utilIsTestnet {
		return bitsig_go.CheckSignature(address, signature, message, "FLO", &FloTestnetParams)
	}
	return bitsig_go.CheckSignature(address, signature, message, "FLO", &FloParams)
}

// reference: Cory LaNou, Mar 2 '14 at 15:21, http://stackoverflow.com/a/22129435/2576956
func IsJSON(s string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(s), &js) == nil
}
<commit_msg>Revert to v0.10 method of signature generation<commit_after>package utility

import (
	"encoding/json"
	"github.com/bitspill/bitsig-go"
	"github.com/btcsuite/btcutil"
)

var utilIsTestnet bool = false

func SetTestnet(testnet bool) {
	utilIsTestnet = testnet
}

func Testnet() bool {
	return utilIsTestnet
}

func CheckAddress(address string) bool {
	var err error
	if utilIsTestnet {
		_, err = btcutil.DecodeAddress(address, &FloTestnetParams)
	} else {
		_, err = btcutil.DecodeAddress(address, &FloParams)
	}
	if err != nil {
		return false
	}
	return true
}

func CheckSignature(address string, signature string, message string) (bool, error) {
	if utilIsTestnet {
		return bitsig_go.CheckSignature(address, signature, message, "Florincoin", &FloTestnetParams)
	}
	return bitsig_go.CheckSignature(address, signature, message, "Florincoin", &FloParams)
}

// reference: Cory LaNou, Mar 2 '14 at 15:21, http://stackoverflow.com/a/22129435/2576956
func IsJSON(s string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(s), &js) == nil
}
<|endoftext|>


<commit_before>package gotility

import (
	"testing"
	"reflect"
)

func TestIsEmail(t *testing.T) {
	isEmail := IsEmail("xyz@gmail.com")
	if isEmail != true {
		t.Error("Expected true, got ", isEmail)
	}
	isEmail = IsEmail("mail")
	if isEmail != false {
		t.Error("Expected false, got ", isEmail)
	}
}

func TestIsUrl(t *testing.T) {
	isUrl := IsUrl("google.com")
	if isUrl != true {
		t.Error("Expected true, got ", isUrl)
	}
	isUrl = IsUrl("123.com1")
	if isUrl != false {
		t.Error("Expected false, got ", isUrl)
	}
}

func TestIsNumber(t *testing.T) {
	isNumber := IsNumber("12134.0009")
	if isNumber != true {
		t.Error("Expected true, got ", isNumber)
	}
	isNumber = IsNumber("a12134.0009")
	if isNumber != false {
		t.Error("Expected false, got ", isNumber)
	}
}

func TestIsTitleCase(t *testing.T) {
	isTitleCase := IsTitleCase("Go Is VEry Popular")
	if isTitleCase != true {
		t.Error("Expected true, got ", isTitleCase)
	}
	isTitleCase = IsTitleCase("gO IS NOT POPULAR")
	if isTitleCase != false {
		t.Error("Expected false, got ", isTitleCase)
	}
}

func TestFlattenFloat64(t *testing.T) {
	row := FlattenFloat64([][]float64{{1.1, 2.2}, {3.3, 4.4}})
	if !reflect.DeepEqual(row, []float64{1.1, 2.2, 3.3, 4.4}) {
		t.Error("Expected [1.1 2.2 3.3 4.4], got ", row)
	}
}

func TestFlattenInt(t *testing.T) {
	row := FlattenInt([][]int{{1, 2}, {3, 4}})
	if !reflect.DeepEqual(row, []int{1, 2, 3, 4}) {
		t.Error("Expected [1 2 3 4], got ", row)
	}
}

func TestFlattenString(t *testing.T) {
	row := FlattenString([][]string{{"A", "B"}, {"C", "D"}})
	if !reflect.DeepEqual(row, []string{"A", "B", "C", "D"}) {
		t.Error("Expected [A B C D], got ", row)
	}
}
<commit_msg>Prettified test file<commit_after>package gotility

import (
	"reflect"
	"testing"
)

func TestIsEmail(t *testing.T) {
	isEmail := IsEmail("xyz@gmail.com")
	if isEmail != true {
		t.Error("Expected true, got ", isEmail)
	}
	isEmail = IsEmail("mail")
	if isEmail != false {
		t.Error("Expected false, got ", isEmail)
	}
}

func TestIsUrl(t *testing.T) {
	isUrl := IsUrl("google.com")
	if isUrl != true {
		t.Error("Expected true, got ", isUrl)
	}
	isUrl = IsUrl("123.com1")
	if isUrl != false {
		t.Error("Expected false, got ", isUrl)
	}
}

func TestIsNumber(t *testing.T) {
	isNumber := IsNumber("12134.0009")
	if isNumber != true {
		t.Error("Expected true, got ", isNumber)
	}
	isNumber = IsNumber("a12134.0009")
	if isNumber != false {
		t.Error("Expected false, got ", isNumber)
	}
}

func TestIsTitleCase(t *testing.T) {
	isTitleCase := IsTitleCase("Go Is VEry Popular")
	if isTitleCase != true {
		t.Error("Expected true, got ", isTitleCase)
	}
	isTitleCase = IsTitleCase("gO IS NOT POPULAR")
	if isTitleCase != false {
		t.Error("Expected false, got ", isTitleCase)
	}
}

func TestFlattenFloat64(t *testing.T) {
	row := FlattenFloat64([][]float64{{1.1, 2.2}, {3.3, 4.4}})
	if !reflect.DeepEqual(row, []float64{1.1, 2.2, 3.3, 4.4}) {
		t.Error("Expected [1.1 2.2 3.3 4.4], got ", row)
	}
}

func TestFlattenInt(t *testing.T) {
	row := FlattenInt([][]int{{1, 2}, {3, 4}})
	if !reflect.DeepEqual(row, []int{1, 2, 3, 4}) {
		t.Error("Expected [1 2 3 4], got ", row)
	}
}

func TestFlattenString(t *testing.T) {
	row := FlattenString([][]string{{"A", "B"}, {"C", "D"}})
	if !reflect.DeepEqual(row, []string{"A", "B", "C", "D"}) {
		t.Error("Expected [A B C D], got ", row)
	}
}
<|endoftext|>


<commit_before>package widget

import (
	"fmt"

	"github.com/richardwilkes/toolbox/xmath/geom"
	"github.com/richardwilkes/ui"
	"github.com/richardwilkes/ui/border"
	"github.com/richardwilkes/ui/color"
	"github.com/richardwilkes/ui/draw"
	"github.com/richardwilkes/ui/event"
	"github.com/richardwilkes/ui/layout"
	"github.com/richardwilkes/ui/object"
)

// Block is the basic graphical block in a window.
type Block struct {
	object.Base
	Describer     func() string
	eventHandlers *event.Handlers
	window        ui.Window
	parent        ui.Widget
	children      []ui.Widget
	sizer         layout.Sizer
	layout        layout.Layout
	border        border.Border
	bounds        geom.Rect
	layoutData    interface{}
	background    color.Color
	needLayout    bool
	disabled      bool
	focusable     bool
	grabsFocus    bool
}

// NewBlock creates a new, empty block.
func NewBlock() *Block {
	block := &Block{}
	block.InitTypeAndID(block)
	return block
}

func (b *Block) String() string {
	if b.Describer != nil {
		return b.Describer()
	}
	return fmt.Sprintf("Block #%d", b.ID())
}

// EventHandlers implements the event.Target interface.
func (b *Block) EventHandlers() *event.Handlers {
	if b.eventHandlers == nil {
		b.eventHandlers = &event.Handlers{}
	}
	return b.eventHandlers
}

// ParentTarget implements the event.Target interface.
func (b *Block) ParentTarget() event.Target {
	if b.parent != nil {
		return b.parent
	}
	return b.window
}

// Sizer implements the Widget interface.
func (b *Block) Sizer() layout.Sizer {
	return b.sizer
}

// SetSizer implements the Widget interface.
func (b *Block) SetSizer(sizer layout.Sizer) {
	b.sizer = sizer
}

// Layout implements the Widget interface.
func (b *Block) Layout() layout.Layout {
	return b.layout
}

// SetLayout implements the Widget interface.
func (b *Block) SetLayout(layout layout.Layout) {
	b.layout = layout
	b.SetNeedLayout(true)
}

// NeedLayout implements the Widget interface.
func (b *Block) NeedLayout() bool {
	return b.needLayout
}

// SetNeedLayout implements the Widget interface.
func (b *Block) SetNeedLayout(needLayout bool) {
	b.needLayout = needLayout
}

// LayoutData implements the Widget interface.
func (b *Block) LayoutData() interface{} {
	return b.layoutData
}

// SetLayoutData implements the Widget interface.
func (b *Block) SetLayoutData(data interface{}) {
	if b.layoutData != data {
		b.layoutData = data
		b.SetNeedLayout(true)
	}
}

// ValidateLayout implements the Widget interface.
func (b *Block) ValidateLayout() {
	if b.NeedLayout() {
		if layout := b.Layout(); layout != nil {
			layout.Layout()
			b.Repaint()
		}
		b.SetNeedLayout(false)
	}
	for _, child := range b.children {
		child.ValidateLayout()
	}
}

// Border implements the Widget interface.
func (b *Block) Border() border.Border {
	return b.border
}

// SetBorder implements the Widget interface.
func (b *Block) SetBorder(border border.Border) {
	b.border = border
}

// Repaint implements the Widget interface.
func (b *Block) Repaint() {
	b.RepaintBounds(b.LocalBounds())
}

// RepaintBounds implements the Widget interface.
func (b *Block) RepaintBounds(bounds geom.Rect) {
	bounds.Intersect(b.LocalBounds())
	if !bounds.IsEmpty() {
		if p := b.Parent(); p != nil {
			bounds.X += b.bounds.X
			bounds.Y += b.bounds.Y
			p.RepaintBounds(bounds)
		} else if b.RootOfWindow() {
			b.Window().RepaintBounds(bounds)
		}
	}
}

// Paint implements the Widget interface.
func (b *Block) Paint(gc *draw.Graphics, dirty geom.Rect) {
	dirty.Intersect(b.LocalBounds())
	if !dirty.IsEmpty() {
		gc.Save()
		gc.Rect(dirty)
		gc.Clip()
		gc.Save()
		if b.background.Alpha() > 0 {
			gc.SetColor(b.background)
			gc.FillRect(dirty)
		}
		event.Dispatch(event.NewPaint(b, gc, dirty))
		gc.Restore()
		for _, child := range b.children {
			adjusted := dirty
			bounds := child.Bounds()
			adjusted.Intersect(bounds)
			if !adjusted.IsEmpty() {
				gc.Save()
				gc.Translate(bounds.X, bounds.Y)
				adjusted.X -= bounds.X
				adjusted.Y -= bounds.Y
				child.Paint(gc, adjusted)
				gc.Restore()
			}
		}
		if border := b.Border(); border != nil {
			gc.Save()
			border.Draw(gc, b.LocalBounds())
			gc.Restore()
		}
		gc.Restore()
	}
}

// Enabled implements the Widget interface.
func (b *Block) Enabled() bool {
	return !b.disabled
}

// SetEnabled implements the Widget interface.
func (b *Block) SetEnabled(enabled bool) {
	disabled := !enabled
	if b.disabled != disabled {
		b.disabled = disabled
		b.Repaint()
	}
}

// Focusable implements the Widget interface.
func (b *Block) Focusable() bool {
	return b.focusable && !b.disabled
}

// SetFocusable implements the Widget interface.
func (b *Block) SetFocusable(focusable bool) {
	if b.focusable != focusable {
		b.focusable = focusable
	}
}

// GrabFocusWhenClickedOn implements the Widget interface.
func (b *Block) GrabFocusWhenClickedOn() bool {
	return b.grabsFocus
}

// SetGrabFocusWhenClickedOn implements the Widget interface.
func (b *Block) SetGrabFocusWhenClickedOn(grabsFocus bool) {
	if b.grabsFocus != grabsFocus {
		b.grabsFocus = grabsFocus
	}
}

// Focused implements the Widget interface.
func (b *Block) Focused() bool {
	if window := b.Window(); window != nil {
		return window.Focused() && b.Is(window.Focus())
	}
	return false
}

// Children implements the Widget interface.
func (b *Block) Children() []ui.Widget {
	return b.children
}

// IndexOfChild implements the Widget interface.
func (b *Block) IndexOfChild(child ui.Widget) int {
	for i, one := range b.children {
		if one.ID() == child.ID() {
			return i
		}
	}
	return -1
}

// AddChild implements the Widget interface.
func (b *Block) AddChild(child ui.Widget) {
	child.RemoveFromParent()
	b.children = append(b.children, child)
	child.SetParent(b)
	b.SetNeedLayout(true)
}

// AddChildAtIndex implements the Widget interface.
func (b *Block) AddChildAtIndex(child ui.Widget, index int) {
	child.RemoveFromParent()
	if index < 0 || index >= len(b.children) {
		b.children = append(b.children, child)
	} else {
		b.children = append(b.children, nil)
		copy(b.children[index+1:], b.children[index:])
		b.children[index] = child
	}
	child.SetParent(b)
	b.SetNeedLayout(true)
}

// RemoveChild implements the Widget interface.
func (b *Block) RemoveChild(child ui.Widget) {
	b.RemoveChildAtIndex(b.IndexOfChild(child))
}

// RemoveChildAtIndex implements the Widget interface.
func (b *Block) RemoveChildAtIndex(index int) {
	if index >= 0 && index < len(b.children) {
		child := b.children[index]
		copy(b.children[index:], b.children[index+1:])
		length := len(b.children) - 1
		b.children[length] = nil
		b.children = b.children[:length]
		b.SetNeedLayout(true)
		child.SetParent(nil)
	}
}

// RemoveFromParent implements the Widget interface.
func (b *Block) RemoveFromParent() {
	if p := b.Parent(); p != nil {
		p.RemoveChild(b)
	}
}

// Parent implements the Widget interface.
func (b *Block) Parent() ui.Widget {
	return b.parent
}

// SetParent implements the Widget interface.
func (b *Block) SetParent(parent ui.Widget) {
	b.parent = parent
}

// Window implements the Widget interface.
func (b *Block) Window() ui.Window {
	if b.window != nil {
		return b.window
	}
	if b.parent != nil {
		return b.parent.Window()
	}
	return nil
}

// SetWindow sets the window of this Block and the Block's bounds to the window's ContentLocalFrame().
func (b *Block) SetWindow(wnd ui.Window) {
	b.window = wnd
	b.bounds = wnd.ContentLocalFrame()
}

// RootOfWindow implements the Widget interface.
func (b *Block) RootOfWindow() bool {
	return b.window != nil
}

// Bounds implements the Widget interface.
func (b *Block) Bounds() geom.Rect {
	return b.bounds
}

// LocalBounds implements the Widget interface.
func (b *Block) LocalBounds() geom.Rect {
	return b.bounds.CopyAndZeroLocation()
}

// LocalInsetBounds implements the Widget interface.
func (b *Block) LocalInsetBounds() geom.Rect {
	bounds := b.LocalBounds()
	if border := b.Border(); border != nil {
		bounds.Inset(border.Insets())
	}
	return bounds
}

// SetBounds implements the Widget interface.
func (b *Block) SetBounds(bounds geom.Rect) {
	moved := b.bounds.X != bounds.X || b.bounds.Y != bounds.Y
	resized := b.bounds.Width != bounds.Width || b.bounds.Height != bounds.Height
	if moved || resized {
		b.Repaint()
		if moved {
			b.bounds.Point = bounds.Point
		}
		if resized {
			b.bounds.Size = bounds.Size
			b.SetNeedLayout(true)
			event.Dispatch(event.NewResized(b))
		}
		b.Repaint()
	}
}

// Location implements the Widget interface.
func (b *Block) Location() geom.Point {
	return b.bounds.Point
}

// SetLocation implements the Widget interface.
func (b *Block) SetLocation(pt geom.Point) {
	if b.bounds.Point != pt {
		b.Repaint()
		b.bounds.Point = pt
		b.Repaint()
	}
}

// Size implements the Widget interface.
func (b *Block) Size() geom.Size {
	return b.bounds.Size
}

// SetSize implements the Widget interface.
func (b *Block) SetSize(size geom.Size) {
	if b.bounds.Size != size {
		b.Repaint()
		b.bounds.Size = size
		b.SetNeedLayout(true)
		event.Dispatch(event.NewResized(b))
		b.Repaint()
	}
}

// WidgetAt implements the Widget interface.
func (b *Block) WidgetAt(pt geom.Point) ui.Widget {
	for _, child := range b.children {
		bounds := child.Bounds()
		if bounds.ContainsPoint(pt) {
			pt.Subtract(bounds.Point)
			return child.WidgetAt(pt)
		}
	}
	return b
}

// ToWindow implements the Widget interface.
func (b *Block) ToWindow(pt geom.Point) geom.Point {
	pt.Add(b.bounds.Point)
	parent := b.parent
	for parent != nil {
		pt.Add(parent.Bounds().Point)
		parent = parent.Parent()
	}
	return pt
}

// FromWindow implements the Widget interface.
func (b *Block) FromWindow(pt geom.Point) geom.Point {
	pt.Subtract(b.bounds.Point)
	parent := b.parent
	for parent != nil {
		pt.Subtract(parent.Bounds().Point)
		parent = parent.Parent()
	}
	return pt
}

// Background implements the Widget interface.
func (b *Block) Background() color.Color {
	return b.background
}

// SetBackground implements the Widget interface.
func (b *Block) SetBackground(color color.Color) {
	if color != b.background {
		b.background = color
		b.Repaint()
	}
}

// ScrollIntoView attempts to scroll the block into view.
func (b *Block) ScrollIntoView() {
	// RAW: Implement
}
<commit_msg>Be cautious<commit_after>package widget

import (
	"fmt"

	"github.com/richardwilkes/toolbox/xmath/geom"
	"github.com/richardwilkes/ui"
	"github.com/richardwilkes/ui/border"
	"github.com/richardwilkes/ui/color"
	"github.com/richardwilkes/ui/draw"
	"github.com/richardwilkes/ui/event"
	"github.com/richardwilkes/ui/layout"
	"github.com/richardwilkes/ui/object"
)

// Block is the basic graphical block in a window.
type Block struct {
	object.Base
	Describer     func() string
	eventHandlers *event.Handlers
	window        ui.Window
	parent        ui.Widget
	children      []ui.Widget
	sizer         layout.Sizer
	layout        layout.Layout
	border        border.Border
	bounds        geom.Rect
	layoutData    interface{}
	background    color.Color
	needLayout    bool
	disabled      bool
	focusable     bool
	grabsFocus    bool
}

// NewBlock creates a new, empty block.
func NewBlock() *Block {
	block := &Block{}
	block.InitTypeAndID(block)
	return block
}

func (b *Block) String() string {
	if b.Describer != nil {
		return b.Describer()
	}
	return fmt.Sprintf("Block #%d", b.ID())
}

// EventHandlers implements the event.Target interface.
func (b *Block) EventHandlers() *event.Handlers {
	if b.eventHandlers == nil {
		b.eventHandlers = &event.Handlers{}
	}
	return b.eventHandlers
}

// ParentTarget implements the event.Target interface.
func (b *Block) ParentTarget() event.Target {
	if b.parent != nil {
		return b.parent
	}
	return b.window
}

// Sizer implements the Widget interface.
func (b *Block) Sizer() layout.Sizer {
	return b.sizer
}

// SetSizer implements the Widget interface.
func (b *Block) SetSizer(sizer layout.Sizer) {
	b.sizer = sizer
}

// Layout implements the Widget interface.
func (b *Block) Layout() layout.Layout {
	return b.layout
}

// SetLayout implements the Widget interface.
func (b *Block) SetLayout(layout layout.Layout) {
	b.layout = layout
	b.SetNeedLayout(true)
}

// NeedLayout implements the Widget interface.
func (b *Block) NeedLayout() bool {
	return b.needLayout
}

// SetNeedLayout implements the Widget interface.
func (b *Block) SetNeedLayout(needLayout bool) {
	b.needLayout = needLayout
}

// LayoutData implements the Widget interface.
func (b *Block) LayoutData() interface{} {
	return b.layoutData
}

// SetLayoutData implements the Widget interface.
func (b *Block) SetLayoutData(data interface{}) {
	if b.layoutData != data {
		b.layoutData = data
		b.SetNeedLayout(true)
	}
}

// ValidateLayout implements the Widget interface.
func (b *Block) ValidateLayout() {
	if b.NeedLayout() {
		if layout := b.Layout(); layout != nil {
			layout.Layout()
			b.Repaint()
		}
		b.SetNeedLayout(false)
	}
	for _, child := range b.children {
		child.ValidateLayout()
	}
}

// Border implements the Widget interface.
func (b *Block) Border() border.Border {
	return b.border
}

// SetBorder implements the Widget interface.
func (b *Block) SetBorder(border border.Border) {
	b.border = border
}

// Repaint implements the Widget interface.
func (b *Block) Repaint() {
	b.RepaintBounds(b.LocalBounds())
}

// RepaintBounds implements the Widget interface.
func (b *Block) RepaintBounds(bounds geom.Rect) {
	bounds.Intersect(b.LocalBounds())
	if !bounds.IsEmpty() {
		if p := b.Parent(); p != nil {
			bounds.X += b.bounds.X
			bounds.Y += b.bounds.Y
			p.RepaintBounds(bounds)
		} else if b.RootOfWindow() {
			b.Window().RepaintBounds(bounds)
		}
	}
}

// Paint implements the Widget interface.
func (b *Block) Paint(gc *draw.Graphics, dirty geom.Rect) {
	dirty.Intersect(b.LocalBounds())
	if !dirty.IsEmpty() {
		gc.Save()
		gc.Rect(dirty)
		gc.Clip()
		gc.Save()
		if b.background.Alpha() > 0 {
			gc.SetColor(b.background)
			gc.FillRect(dirty)
		}
		event.Dispatch(event.NewPaint(b, gc, dirty))
		gc.Restore()
		for _, child := range b.children {
			adjusted := dirty
			bounds := child.Bounds()
			adjusted.Intersect(bounds)
			if !adjusted.IsEmpty() {
				gc.Save()
				gc.Translate(bounds.X, bounds.Y)
				adjusted.X -= bounds.X
				adjusted.Y -= bounds.Y
				child.Paint(gc, adjusted)
				gc.Restore()
			}
		}
		if border := b.Border(); border != nil {
			gc.Save()
			border.Draw(gc, b.LocalBounds())
			gc.Restore()
		}
		gc.Restore()
	}
}

// Enabled implements the Widget interface.
func (b *Block) Enabled() bool {
	return !b.disabled
}

// SetEnabled implements the Widget interface.
func (b *Block) SetEnabled(enabled bool) {
	disabled := !enabled
	if b.disabled != disabled {
		b.disabled = disabled
		b.Repaint()
	}
}

// Focusable implements the Widget interface.
func (b *Block) Focusable() bool {
	return b.focusable && !b.disabled
}

// SetFocusable implements the Widget interface.
func (b *Block) SetFocusable(focusable bool) {
	if b.focusable != focusable {
		b.focusable = focusable
	}
}

// GrabFocusWhenClickedOn implements the Widget interface.
func (b *Block) GrabFocusWhenClickedOn() bool {
	return b.grabsFocus
}

// SetGrabFocusWhenClickedOn implements the Widget interface.
func (b *Block) SetGrabFocusWhenClickedOn(grabsFocus bool) {
	if b.grabsFocus != grabsFocus {
		b.grabsFocus = grabsFocus
	}
}

// Focused implements the Widget interface.
func (b *Block) Focused() bool {
	if window := b.Window(); window != nil {
		return window.Focused() && b.Is(window.Focus())
	}
	return false
}

// Children implements the Widget interface.
func (b *Block) Children() []ui.Widget {
	return b.children
}

// IndexOfChild implements the Widget interface.
func (b *Block) IndexOfChild(child ui.Widget) int {
	for i, one := range b.children {
		if one.ID() == child.ID() {
			return i
		}
	}
	return -1
}

// AddChild implements the Widget interface.
func (b *Block) AddChild(child ui.Widget) {
	child.RemoveFromParent()
	b.children = append(b.children, child)
	child.SetParent(b)
	b.SetNeedLayout(true)
}

// AddChildAtIndex implements the Widget interface.
func (b *Block) AddChildAtIndex(child ui.Widget, index int) {
	child.RemoveFromParent()
	if index < 0 || index >= len(b.children) {
		b.children = append(b.children, child)
	} else {
		b.children = append(b.children, nil)
		copy(b.children[index+1:], b.children[index:])
		b.children[index] = child
	}
	child.SetParent(b)
	b.SetNeedLayout(true)
}

// RemoveChild implements the Widget interface.
func (b *Block) RemoveChild(child ui.Widget) {
	b.RemoveChildAtIndex(b.IndexOfChild(child))
}

// RemoveChildAtIndex implements the Widget interface.
func (b *Block) RemoveChildAtIndex(index int) {
	if index >= 0 && index < len(b.children) {
		child := b.children[index]
		copy(b.children[index:], b.children[index+1:])
		length := len(b.children) - 1
		b.children[length] = nil
		b.children = b.children[:length]
		b.SetNeedLayout(true)
		child.SetParent(nil)
	}
}

// RemoveFromParent implements the Widget interface.
func (b *Block) RemoveFromParent() {
	if p := b.Parent(); p != nil {
		p.RemoveChild(b)
	}
}

// Parent implements the Widget interface.
func (b *Block) Parent() ui.Widget {
	return b.parent
}

// SetParent implements the Widget interface.
func (b *Block) SetParent(parent ui.Widget) {
	b.parent = parent
}

// Window implements the Widget interface.
func (b *Block) Window() ui.Window {
	if b.window != nil {
		return b.window
	}
	if b.parent != nil {
		return b.parent.Window()
	}
	return nil
}

// SetWindow sets the window of this Block and the Block's bounds to the
// window's ContentLocalFrame().
func (b *Block) SetWindow(wnd ui.Window) {
	b.window = wnd
	if wnd != nil {
		b.bounds = wnd.ContentLocalFrame()
	}
}

// RootOfWindow implements the Widget interface.
func (b *Block) RootOfWindow() bool {
	return b.window != nil
}

// Bounds implements the Widget interface.
func (b *Block) Bounds() geom.Rect {
	return b.bounds
}

// LocalBounds implements the Widget interface.
func (b *Block) LocalBounds() geom.Rect {
	return b.bounds.CopyAndZeroLocation()
}

// LocalInsetBounds implements the Widget interface.
func (b *Block) LocalInsetBounds() geom.Rect {
	bounds := b.LocalBounds()
	if border := b.Border(); border != nil {
		bounds.Inset(border.Insets())
	}
	return bounds
}

// SetBounds implements the Widget interface.
func (b *Block) SetBounds(bounds geom.Rect) {
	moved := b.bounds.X != bounds.X || b.bounds.Y != bounds.Y
	resized := b.bounds.Width != bounds.Width || b.bounds.Height != bounds.Height
	if moved || resized {
		b.Repaint()
		if moved {
			b.bounds.Point = bounds.Point
		}
		if resized {
			b.bounds.Size = bounds.Size
			b.SetNeedLayout(true)
			event.Dispatch(event.NewResized(b))
		}
		b.Repaint()
	}
}

// Location implements the Widget interface.
func (b *Block) Location() geom.Point {
	return b.bounds.Point
}

// SetLocation implements the Widget interface.
func (b *Block) SetLocation(pt geom.Point) {
	if b.bounds.Point != pt {
		b.Repaint()
		b.bounds.Point = pt
		b.Repaint()
	}
}

// Size implements the Widget interface.
func (b *Block) Size() geom.Size {
	return b.bounds.Size
}

// SetSize implements the Widget interface.
func (b *Block) SetSize(size geom.Size) {
	if b.bounds.Size != size {
		b.Repaint()
		b.bounds.Size = size
		b.SetNeedLayout(true)
		event.Dispatch(event.NewResized(b))
		b.Repaint()
	}
}

// WidgetAt implements the Widget interface.
func (b *Block) WidgetAt(pt geom.Point) ui.Widget {
	for _, child := range b.children {
		bounds := child.Bounds()
		if bounds.ContainsPoint(pt) {
			pt.Subtract(bounds.Point)
			return child.WidgetAt(pt)
		}
	}
	return b
}

// ToWindow implements the Widget interface.
func (b *Block) ToWindow(pt geom.Point) geom.Point {
	pt.Add(b.bounds.Point)
	parent := b.parent
	for parent != nil {
		pt.Add(parent.Bounds().Point)
		parent = parent.Parent()
	}
	return pt
}

// FromWindow implements the Widget interface.
func (b *Block) FromWindow(pt geom.Point) geom.Point {
	pt.Subtract(b.bounds.Point)
	parent := b.parent
	for parent != nil {
		pt.Subtract(parent.Bounds().Point)
		parent = parent.Parent()
	}
	return pt
}

// Background implements the Widget interface.
func (b *Block) Background() color.Color {
	return b.background
}

// SetBackground implements the Widget interface.
func (b *Block) SetBackground(color color.Color) {
	if color != b.background {
		b.background = color
		b.Repaint()
	}
}

// ScrollIntoView attempts to scroll the block into view.
func (b *Block) ScrollIntoView() {
	// RAW: Implement
}
<|endoftext|>


<commit_before>package values

import (
	"fmt"
	"reflect"
	"strconv"
)

// In returns true if the key exists.
func In(m map[string]interface{}, key string) bool {
	if _, ok := m[key]; ok {
		return true
	}
	return false
}

// Ins returns true if the key exists.
func Ins(m map[string]string, key string) bool {
	if _, ok := m[key]; ok {
		return true
	}
	return false
}

// GetString returns the value of the key.
//
// The key must exist, or panic.
func GetString(m map[string]string, key string) string {
	if v, ok := m[key]; ok {
		return v
	}
	panic(fmt.Errorf("the key '%s' is missing", key))
}

// GetStringWithDefault returns the value of the key.
//
// Return the default if the key does not exist.
func GetStringWithDefault(m map[string]string, key string, _default string) string {
	if v, ok := m[key]; ok {
		return v
	}
	return _default
}

// GetInterface returns the value of the key.
//
// The key must exist, or panic.
func GetInterface(m map[string]interface{}, key string) interface{} {
	if v, ok := m[key]; ok {
		return v
	}
	panic(fmt.Errorf("the key '%s' is missing", key))
}

// GetInterfaceWithDefault returns the value of the key.
//
// Return the default if the key does not exist.
func GetInterfaceWithDefault(m map[string]interface{}, key string, _default interface{}) interface{} {
	if v, ok := m[key]; ok {
		return v
	}
	return _default
}

// ToBool does the best to convert a certain value to bool.
//
// When the value is string, for "t", "T", "1", "true", "True", "TRUE",
// it's true, for "f", "F", "0", "false", "False", "FALSE", "", it's false.
//
// For other types, if the value is ZERO of the type, it's false. Or it's true.
func ToBool(v interface{}) (bool, error) {
	switch _v := v.(type) {
	case string:
		switch _v {
		case "t", "T", "1", "true", "True", "TRUE":
			return true, nil
		case "f", "F", "0", "false", "False", "FALSE", "":
			return false, nil
		default:
			return false, fmt.Errorf("unrecognized bool string: %s", _v)
		}
	}
	return !IsZero(v), nil
}

// ToInt64 does the best to convert a certain value to int64.
func ToInt64(_v interface{}) (v int64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = int64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = int64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Int()
	case uint, uint8, uint16, uint32, uint64:
		v = int64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = int64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseInt(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToInt64 must parse the value v to int64, or panic.
//
// Notice: it will do the best to parse v.
func MustToInt64(v interface{}) int64 {
	_v, err := ToInt64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToUInt64 is the alias of ToUint64. This function is deprecated, and please
// use ToUint64.
func ToUInt64(_v interface{}) (v uint64, err error) {
	return ToUint64(_v)
}

// ToUint64 does the best to convert a certain value to uint64.
func ToUint64(_v interface{}) (v uint64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = uint64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = uint64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Uint()
	case uint, uint8, uint16, uint32, uint64:
		v = uint64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = uint64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseUint(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToUInt64 is the alias of MustToUint64. This function is deprecated,
// and please use MustToUint64.
func MustToUInt64(v interface{}) uint64 {
	return MustToUint64(v)
}

// MustToUint64 must parse the value v to uint64, or panic.
//
// Notice: it will do the best to parse v.
func MustToUint64(v interface{}) uint64 {
	_v, err := ToUint64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToString does the best to convert a certain value to string.
func ToString(_v interface{}) (v string, err error) {
	switch _v.(type) {
	case string:
		v = _v.(string)
	case []byte:
		v = string(_v.([]byte))
	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		v = fmt.Sprintf("%d", _v)
	case float32, float64:
		v = fmt.Sprintf("%f", _v)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToString must parse the value v to string, or panic.
//
// Notice: it will do the best to parse v.
func MustToString(v interface{}) string {
	_v, err := ToString(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToFloat64 does the best to convert a certain value to float64.
func ToFloat64(_v interface{}) (v float64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = float64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = float64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = float64(reflect.ValueOf(_v).Int())
	case uint, uint8, uint16, uint32, uint64:
		v = float64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = reflect.ValueOf(_v).Float()
	case string:
		return strconv.ParseFloat(_v.(string), 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToFloat64 must parse the value v to float64, or panic.
//
// Notice: it will do the best to parse v.
func MustToFloat64(v interface{}) float64 {
	_v, err := ToFloat64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToComplex128 does the best to convert a certain value to complex128.
func ToComplex128(_v interface{}) (v complex128, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = complex128(reflect.ValueOf(_v).Complex())
	case bool:
		v = complex(float64(Bool2Int(_v.(bool))), 0)
	case int, int8, int16, int32, int64:
		v = complex(float64(reflect.ValueOf(_v).Int()), 0)
	case uint, uint8, uint16, uint32, uint64:
		v = complex(float64(reflect.ValueOf(_v).Uint()), 0)
	case float32, float64:
		v = complex(reflect.ValueOf(_v).Float(), 0)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToComplex128 must parse the value v to complex128, or panic.
//
// Notice: it will do the best to parse v.
func MustToComplex128(v interface{}) complex128 {
	_v, err := ToComplex128(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToInt does the best to convert a certain value to int.
func ToInt(v interface{}) (int, error) {
	_v, err := ToInt64(v)
	return int(_v), err
}

// ToUInt is the alias of ToUint. This function is deprecated, and please use
// ToUint.
func ToUInt(v interface{}) (uint, error) {
	return ToUint(v)
}

// ToUint does the best to convert a certain value to uint.
func ToUint(v interface{}) (uint, error) {
	_v, err := ToUint64(v)
	return uint(_v), err
}

// ToInt32 does the best to convert a certain value to int32.
func ToInt32(v interface{}) (int32, error) {
	_v, err := ToInt64(v)
	return int32(_v), err
}

// ToUInt32 is the alias of ToUint32. This function is deprecated, and please
// use ToUint32.
func ToUInt32(v interface{}) (uint32, error) {
	return ToUint32(v)
}

// ToUint32 does the best to convert a certain value to uint32.
func ToUint32(v interface{}) (uint32, error) {
	_v, err := ToUint64(v)
	return uint32(_v), err
}
<commit_msg>Change deprecated to the UPPER.<commit_after>package values

import (
	"fmt"
	"reflect"
	"strconv"
)

// In returns true if the key exists.
func In(m map[string]interface{}, key string) bool {
	if _, ok := m[key]; ok {
		return true
	}
	return false
}

// Ins returns true if the key exists.
func Ins(m map[string]string, key string) bool {
	if _, ok := m[key]; ok {
		return true
	}
	return false
}

// GetString returns the value of the key.
//
// The key must exist, or panic.
func GetString(m map[string]string, key string) string {
	if v, ok := m[key]; ok {
		return v
	}
	panic(fmt.Errorf("the key '%s' is missing", key))
}

// GetStringWithDefault returns the value of the key.
//
// Return the default if the key does not exist.
func GetStringWithDefault(m map[string]string, key string, _default string) string {
	if v, ok := m[key]; ok {
		return v
	}
	return _default
}

// GetInterface returns the value of the key.
//
// The key must exist, or panic.
func GetInterface(m map[string]interface{}, key string) interface{} {
	if v, ok := m[key]; ok {
		return v
	}
	panic(fmt.Errorf("the key '%s' is missing", key))
}

// GetInterfaceWithDefault returns the value of the key.
//
// Return the default if the key does not exist.
func GetInterfaceWithDefault(m map[string]interface{}, key string, _default interface{}) interface{} {
	if v, ok := m[key]; ok {
		return v
	}
	return _default
}

// ToBool does the best to convert a certain value to bool.
//
// When the value is string, for "t", "T", "1", "true", "True", "TRUE",
// it's true, for "f", "F", "0", "false", "False", "FALSE", "", it's false.
//
// For other types, if the value is ZERO of the type, it's false. Or it's true.
func ToBool(v interface{}) (bool, error) {
	switch _v := v.(type) {
	case string:
		switch _v {
		case "t", "T", "1", "true", "True", "TRUE":
			return true, nil
		case "f", "F", "0", "false", "False", "FALSE", "":
			return false, nil
		default:
			return false, fmt.Errorf("unrecognized bool string: %s", _v)
		}
	}
	return !IsZero(v), nil
}

// ToInt64 does the best to convert a certain value to int64.
func ToInt64(_v interface{}) (v int64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = int64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = int64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Int()
	case uint, uint8, uint16, uint32, uint64:
		v = int64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = int64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseInt(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToInt64 must parse the value v to int64, or panic.
//
// Notice: it will do the best to parse v.
func MustToInt64(v interface{}) int64 {
	_v, err := ToInt64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToUInt64 is the alias of ToUint64. This function is DEPRECATED, and please
// use ToUint64.
func ToUInt64(_v interface{}) (v uint64, err error) {
	return ToUint64(_v)
}

// ToUint64 does the best to convert a certain value to uint64.
func ToUint64(_v interface{}) (v uint64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = uint64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = uint64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = reflect.ValueOf(_v).Uint()
	case uint, uint8, uint16, uint32, uint64:
		v = uint64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = uint64(reflect.ValueOf(_v).Float())
	case string:
		return strconv.ParseUint(_v.(string), 10, 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToUInt64 is the alias of MustToUint64. This function is DEPRECATED,
// and please use MustToUint64.
func MustToUInt64(v interface{}) uint64 {
	return MustToUint64(v)
}

// MustToUint64 must parse the value v to uint64, or panic.
//
// Notice: it will do the best to parse v.
func MustToUint64(v interface{}) uint64 {
	_v, err := ToUint64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToString does the best to convert a certain value to string.
func ToString(_v interface{}) (v string, err error) {
	switch _v.(type) {
	case string:
		v = _v.(string)
	case []byte:
		v = string(_v.([]byte))
	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		v = fmt.Sprintf("%d", _v)
	case float32, float64:
		v = fmt.Sprintf("%f", _v)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToString must parse the value v to string, or panic.
//
// Notice: it will do the best to parse v.
func MustToString(v interface{}) string {
	_v, err := ToString(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToFloat64 does the best to convert a certain value to float64.
func ToFloat64(_v interface{}) (v float64, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = float64(real(reflect.ValueOf(_v).Complex()))
	case bool:
		v = float64(Bool2Int(_v.(bool)))
	case int, int8, int16, int32, int64:
		v = float64(reflect.ValueOf(_v).Int())
	case uint, uint8, uint16, uint32, uint64:
		v = float64(reflect.ValueOf(_v).Uint())
	case float32, float64:
		v = reflect.ValueOf(_v).Float()
	case string:
		return strconv.ParseFloat(_v.(string), 64)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToFloat64 must parse the value v to float64, or panic.
//
// Notice: it will do the best to parse v.
func MustToFloat64(v interface{}) float64 {
	_v, err := ToFloat64(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToComplex128 does the best to convert a certain value to complex128.
func ToComplex128(_v interface{}) (v complex128, err error) {
	switch _v.(type) {
	case complex64, complex128:
		v = complex128(reflect.ValueOf(_v).Complex())
	case bool:
		v = complex(float64(Bool2Int(_v.(bool))), 0)
	case int, int8, int16, int32, int64:
		v = complex(float64(reflect.ValueOf(_v).Int()), 0)
	case uint, uint8, uint16, uint32, uint64:
		v = complex(float64(reflect.ValueOf(_v).Uint()), 0)
	case float32, float64:
		v = complex(reflect.ValueOf(_v).Float(), 0)
	default:
		err = fmt.Errorf("unknown type of %t", _v)
	}
	return
}

// MustToComplex128 must parse the value v to complex128, or panic.
//
// Notice: it will do the best to parse v.
func MustToComplex128(v interface{}) complex128 {
	_v, err := ToComplex128(v)
	if err != nil {
		panic(err)
	}
	return _v
}

// ToInt does the best to convert a certain value to int.
func ToInt(v interface{}) (int, error) {
	_v, err := ToInt64(v)
	return int(_v), err
}

// ToUInt is the alias of ToUint. This function is DEPRECATED, and please use
// ToUint.
func ToUInt(v interface{}) (uint, error) {
	return ToUint(v)
}

// ToUint does the best to convert a certain value to uint.
func ToUint(v interface{}) (uint, error) {
	_v, err := ToUint64(v)
	return uint(_v), err
}

// ToInt32 does the best to convert a certain value to int32.
func ToInt32(v interface{}) (int32, error) {
	_v, err := ToInt64(v)
	return int32(_v), err
}

// ToUInt32 is the alias of ToUint32. This function is DEPRECATED, and please
// use ToUint32.
func ToUInt32(v interface{}) (uint32, error) {
	return ToUint32(v)
}

// ToUint32 does the best to convert a certain value to uint32.
func ToUint32(v interface{}) (uint32, error) {
	_v, err := ToUint64(v)
	return uint32(_v), err
}
<|endoftext|>


<commit_before>package fixity

import (
	"io"
	"os"
)

const (
	// DefaultAverageChunkSize that the chunker will attempt to produce.
	//
	// See WriteRequest.AverageChunkSize documentation for further explanation
	// of chunk sizes.
	//
	// This value is 1024^2*4 bytes, 4MiB, chosen as a compromise for the
	// small and large files.
	//
	// Ideally it should strike a balance between too many chunks written while
	// still mitigating data duplication caused by frequent changes to files
	// and written data.
	//
	// If written data is commonly editing the first X bytes, this value should
	// be overridden in the WriteRequest itself.
	DefaultAverageChunkSize uint64 = 4194304

	// autoChunkCount is the number of chunks SetChunkFromBytes/etc will set to.
	//
	// Eg, if SetChunkFromBytes is given a byte array that is 1,048,576 bytes,
	// then it will divide 1,048,576 by eg, 10 to set the rollSize to
	// 104,857, effectively rolling the bytes into 10 parts when it's written.
	autoChunkCount = 6

	// 12KiB so that small files/data won't churn with a ton of chunks.
	minAutoChunkSize = 12288
	// 20MiB because chunks too large become hard to store/send/etc. Each
	// chunk should be reasonbly fast to send between nodes.
	maxAutoChunkSize = 20971520
)

// WriteRequest represents a blob to be written alone with metadata.
type WriteRequest struct {
	// Id is the Content Id used to associate this write with previous writes.
	//
	// This association effectively mutates the write from the previous content
	// with the same Id. Important values are inhereted, such as ChunkSize,
	// ensuring consistent writes.
	Id string `json:"id,omitempty"`

	// AverageChunkSize is the average bytes that each chunk is aimed to be.
	//
	// Chunks are separated by Cotent Defined Chunks (CDC) and this value
	// allows mutations of this blob to use the same ChunkSize with each
	// version. This ensures the chunks are chunk'd by the CDC algorithm
	// with the same spacing.
	//
	// Note that the algorithm is decided by the fixity.Store.
	AverageChunkSize uint64 `json:"averageChunkSize,omitempty"`

	// Fields are the indexable fields that the data will be indexed with.
	//
	// This is often metadata like filename, unix permissions, etc. It can
	// also be used to retrieve this data later, as the Fields is stored
	// on the fixity.Content object within the datastore.
	Fields Fields `json:"fields,omitempty"`

	// Blob is the actual data that is being written, and is required.
	//
	// This will be used to build a fixity.Blob type.
	Blob io.ReadCloser `json:"-"`
}

// NewWrite creates a new WriteRequest to be used with Fixity.WriteRequest.
func NewWrite(id string, rc io.ReadCloser, f ...Field) *WriteRequest {
	return &WriteRequest{
		Id:               id,
		AverageChunkSize: DefaultAverageChunkSize,
		Fields:           f,
		Blob:             rc,
	}
}

func (req *WriteRequest) setChunkSize(averageChunkSize uint64) {
	if averageChunkSize < minAutoChunkSize {
		averageChunkSize = minAutoChunkSize
	}
	if averageChunkSize > maxAutoChunkSize {
		averageChunkSize = maxAutoChunkSize
	}
	req.AverageChunkSize = averageChunkSize
}

func (req *WriteRequest) SetChunkSizeFromBytes(b []byte) {
	req.setChunkSize(uint64(len(b)) / autoChunkCount)
}

func (req *WriteRequest) SetChunkSizeFromFileInfo(fi os.FileInfo) {
	req.setChunkSize(uint64(fi.Size()) / autoChunkCount)
}
<commit_msg>feat: lowered the max auto average chunk size<commit_after>package fixity

import (
	"io"
	"os"
)

const (
	// DefaultAverageChunkSize that the chunker will attempt to produce.
	//
	// See WriteRequest.AverageChunkSize documentation for further explanation
	// of chunk sizes.
	//
	// This value is 1024^2*4 bytes, 4MiB, chosen as a compromise for the
	// small and large files.
	//
	// Ideally it should strike a balance between too many chunks written while
	// still mitigating data duplication caused by frequent changes to files
	// and written data.
	//
	// If written data is commonly editing the first X bytes, this value should
	// be overridden in the WriteRequest itself.
	DefaultAverageChunkSize uint64 = 4194304

	// autoChunkCount is the number of chunks SetChunkFromBytes/etc will set to.
	//
	// Eg, if SetChunkFromBytes is given a byte array that is 1,048,576 bytes,
	// then it will divide 1,048,576 by eg, 10 to set the rollSize to
	// 104,857, effectively rolling the bytes into 10 parts when it's written.
	autoChunkCount = 6

	// 12KiB so that small files/data won't churn with a ton of chunks.
	minAutoChunkSize = 12288
	// 4MiB because chunks too large become hard to store/send/etc. Each
	// chunk should be reasonbly fast to send between nodes.
	maxAutoChunkSize = DefaultAverageChunkSize
)

// WriteRequest represents a blob to be written alone with metadata.
type WriteRequest struct {
	// Id is the Content Id used to associate this write with previous writes.
	//
	// This association effectively mutates the write from the previous content
	// with the same Id. Important values are inhereted, such as ChunkSize,
	// ensuring consistent writes.
	Id string `json:"id,omitempty"`

	// AverageChunkSize is the average bytes that each chunk is aimed to be.
	//
	// Chunks are separated by Cotent Defined Chunks (CDC) and this value
	// allows mutations of this blob to use the same ChunkSize with each
	// version. This ensures the chunks are chunk'd by the CDC algorithm
	// with the same spacing.
	//
	// Note that the algorithm is decided by the fixity.Store.
	AverageChunkSize uint64 `json:"averageChunkSize,omitempty"`

	// Fields are the indexable fields that the data will be indexed with.
	//
	// This is often metadata like filename, unix permissions, etc. It can
	// also be used to retrieve this data later, as the Fields is stored
	// on the fixity.Content object within the datastore.
	Fields Fields `json:"fields,omitempty"`

	// Blob is the actual data that is being written, and is required.
	//
	// This will be used to build a fixity.Blob type.
	Blob io.ReadCloser `json:"-"`
}

// NewWrite creates a new WriteRequest to be used with Fixity.WriteRequest.
func NewWrite(id string, rc io.ReadCloser, f ...Field) *WriteRequest {
	return &WriteRequest{
		Id:               id,
		AverageChunkSize: DefaultAverageChunkSize,
		Fields:           f,
		Blob:             rc,
	}
}

func (req *WriteRequest) setChunkSize(averageChunkSize uint64) {
	if averageChunkSize < minAutoChunkSize {
		averageChunkSize = minAutoChunkSize
	}
	if averageChunkSize > maxAutoChunkSize {
		averageChunkSize = maxAutoChunkSize
	}
	req.AverageChunkSize = averageChunkSize
}

func (req *WriteRequest) SetChunkSizeFromBytes(b []byte) {
	req.setChunkSize(uint64(len(b)) / autoChunkCount)
}

func (req *WriteRequest) SetChunkSizeFromFileInfo(fi os.FileInfo) {
	req.setChunkSize(uint64(fi.Size()) / autoChunkCount)
}
<|endoftext|>


<commit_before>package wuxia

//Config is the settings needed by the static generatot. It is inspired by the
//jekyll configuration options.
//
// The format can either be json, yaml or toml
// TODO: add yaml and toml support.
type Config struct {
	Source      string   `json:"source"`
	Destination string   `json:"destination"`
	Safe        bool     `json:"safe"`
	Excluede    []string `json:"exclude"`
	Include     []string `json:"include"`
	KeepFiles   []string `json:"keep_files"`
	TimeZone    string   `json:"timezone"`
	Encoding    string   `json:"encoding"`
	Port        int      `json:"port"`
	Host        string   `json:"host"`
	BaseURL     string   `json:"base_url"`
}

//DefaultConfig retruns *Config with default settings
func DefaultConfig() *Config {
	return &Config{
		Source:      "src",
		Destination: "dest",
		Safe:        true,
		Excluede: []string{
			"CONTRITUTING", "CONTRIBUTING.md",
		},
		Include: []string{
			"LICENCE.md",
		},
	}
}

//System configuration for the whole static generator system.
type System struct {
	Boot   *Boot   `json:"boot"`
	Config *Config `json:"config"`
	Plan   *Plan   `json:"plan"`
}

//Boot necessary info to bootstrap the Generator.
type Boot struct {
	ConfigiFile string            `json:"config_file"`
	PlanFile    string            `json:"plan_file"`
	ENV         map[string]string `json:"env"`
}

//Theme discreption of a theme.
type Theme struct {
	Name   string   `json:"name"`
	Author []Author `json:"author"`
}

//Author description of the author of the project being built.
type Author struct {
	Name     string `json:"name"`
	Github   string `json:"github"`
	Twitter  string `json:"twitter"`
	Linkedin string `json:"linkedin"`
	Email    string `json:"email"`
	Website  string `json:"website"`
}

// Plan is the execution planner object. It states the steps and stages on which
// the execution process should take.
type Plan struct {
	Title string `json:"title"`

	// Modules that are supposed to be loaded before the execution starts. The
	// execution process wont start if one of the dependencies is missing.
	Dependency []string `json:"dependencies"`

	TemplateEngine string   `json:"template_engine"`
	Before         []string `json:"before"`
	Exec           []string `json:"exec"`
	After          []string `json:"after"`
}

//File is a representation of a file unit as it is passed arouund for
//processing.
// File content is passed as a string so as to allow easy trasition between Go
// and javascript boundary.
type File struct {
	Name     string                 `json:"name"`
	Meta     map[string]interface{} `json:"meta"`
	Contents string                 `json:"contents"`
}
<commit_msg>Cleanup Config<commit_after>package wuxia

//Config is the settings needed by the static generatot. It is inspired by the
//jekyll configuration options.
//
// The format can either be json, yaml or toml
// TODO: add yaml and toml support.
type Config struct {
	Source      string   `json:"source"`
	Destination string   `json:"destination"`
	Safe        bool     `json:"safe"`
	Excluede    []string `json:"exclude"`
	Include     []string `json:"include"`
}

//DefaultConfig retruns *Config with default settings
func DefaultConfig() *Config {
	return &Config{
		Source:      "src",
		Destination: "dest",
		Safe:        true,
		Excluede: []string{
			"CONTRITUTING", "CONTRIBUTING.md",
		},
		Include: []string{
			"LICENCE.md",
		},
	}
}

//System configuration for the whole static generator system.
type System struct {
	Boot   *Boot   `json:"boot"`
	Config *Config `json:"config"`
	Plan   *Plan   `json:"plan"`
}

//Boot necessary info to bootstrap the Generator.
type Boot struct {
	ConfigiFile string            `json:"config_file"`
	PlanFile    string            `json:"plan_file"`
	ENV         map[string]string `json:"env"`
}

//Theme discreption of a theme.
type Theme struct {
	Name   string   `json:"name"`
	Author []Author `json:"author"`
}

//Author description of the author of the project being built.
type Author struct {
	Name     string `json:"name"`
	Github   string `json:"github"`
	Twitter  string `json:"twitter"`
	Linkedin string `json:"linkedin"`
	Email    string `json:"email"`
	Website  string `json:"website"`
}

// Plan is the execution planner object. It states the steps and stages on which
// the execution process should take.
type Plan struct {
	Title string `json:"title"`

	// Modules that are supposed to be loaded before the execution starts. The
	// execution process wont start if one of the dependencies is missing.
	Dependency []string `json:"dependencies"`

	TemplateEngine string   `json:"template_engine"`
	Before         []string `json:"before"`
	Exec           []string `json:"exec"`
	After          []string `json:"after"`
}

//File is a representation of a file unit as it is passed arouund for
//processing.
// File content is passed as a string so as to allow easy trasition between Go
// and javascript boundary.
type File struct {
	Name     string                 `json:"name"`
	Meta     map[string]interface{} `json:"meta"`
	Contents string                 `json:"contents"`
}
<|endoftext|>