<commit_before>package statusevaluators

import (
	"errors"
	"strconv"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/common/db"
	"github.com/byuoitav/common/log"
	"github.com/byuoitav/common/structs"
	"github.com/fatih/color"
)

/* ASSUMPTIONS

a) a mic has only one port configuration with the DSP as a destination device

*/

// MutedDSPEvaluator is a constant variable for the name of the evaluator.
const MutedDSPEvaluator = "STATUS_MutedDSP"

// MutedDSPCommand is a constant variable for the name of the command.
const MutedDSPCommand = "STATUS_MutedDSP"

// MutedDSP implements the StatusEvaluator struct.
type MutedDSP struct{}

// GetDevices returns a list of devices in the given room.
func (p *MutedDSP) GetDevices(room structs.Room) ([]structs.Device, error) {

	return room.Devices, nil
}

// GenerateCommands generates a list of commands for the given devices.
func (p *MutedDSP) GenerateCommands(devices []structs.Device) ([]StatusCommand, int, error) {

	log.L.Info("[statusevals] Generating \"Muted\" status commands...")

	//sort mics out of audio devices:w
	var audioDevices, mics, dsp []structs.Device

	for _, device := range devices {

		log.L.Infof("[statusevals] Considering device: %s", device.Name)

		if structs.HasRole(device, "Microphone") {

			mics = append(mics, device)
		} else if structs.HasRole(device, "DSP") {

			dsp = append(dsp, device)
		} else if structs.HasRole(device, "AudioOut") {

			audioDevices = append(audioDevices, device)
		} else {
			continue
		}
	}

	//business as ususal for audioDevices
	commands, count, err := generateStandardStatusCommand(audioDevices, MutedDSPEvaluator, MutedDefaultCommand)
	if err != nil {
		errorMessage := "[statusevals] Could not generate audio device status commands: " + err.Error()
		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	micCommands, c, err := generateMicStatusCommands(mics, MutedDSPEvaluator, MutedDSPCommand)
	if err != nil {
		errorMessage := "[statusevals] Could not generate microphone status commands: " + err.Error()
		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	count += c
	commands = append(commands, micCommands...)

	dspCommands, c, err := generateDSPStatusCommands(dsp, MutedDSPEvaluator, MutedDSPCommand)
	if err != nil {
		return []StatusCommand{}, 0, err
	}

	count += c
	commands = append(commands, dspCommands...)

	log.L.Infof(color.HiYellowString("[STATUS-Muted-DSP] Generated %v commands", len(commands)))
	return commands, count, nil

}

// EvaluateResponse processes the response information that is given.
func (p *MutedDSP) EvaluateResponse(label string, value interface{}, source structs.Device, destintation base.DestinationDevice) (string, interface{}, error) {

	return label, value, nil
}

func generateMicStatusCommands(mics []structs.Device, evaluator string, command string) ([]StatusCommand, int, error) {

	log.L.Infof("[statusevals] Generating %s commands agains mics...", command)

	var commands []StatusCommand

	if len(mics) == 0 {
		errorMessage := "[statusevals] No mics"

		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, nil
	}

	dsp, err := db.GetDB().GetDevicesByRoomAndRole(mics[0].GetDeviceRoomID(), "DSP")
	if err != nil {
		return []StatusCommand{}, 0, err
	}

	if len(dsp) != 1 {
		errorMessage := "[statusevals] Invalid number of DSP devices found in room: " + strconv.Itoa(len(dsp))
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	var count int

	for _, mic := range mics {

		log.L.Infof("[statusevals] Considering mic %s...", mic.Name)

		//find the only DSP the room has

		for _, port := range dsp[0].Ports {

			if port.SourceDevice == mic.ID {
				log.L.Infof("[statusevals] Port configuration identified for mic %s and DSP %s", mic.Name, dsp[0].Name)
				destinationDevice := base.DestinationDevice{
					Device:      mic,
					AudioDevice: true,
				}

				statusCommand := dsp[0].GetCommandByName(command)

				parameters := make(map[string]string)
				parameters["input"] = port.ID
				parameters["address"] = dsp[0].Address

				//issue status command to DSP
				commands = append(commands, StatusCommand{
					Action:            statusCommand,
					Device:            dsp[0],
					Generator:         MutedDSPEvaluator,
					DestinationDevice: destinationDevice,
					Parameters:        parameters,
				})
				count++
			}
		}

	}

	return commands, count, nil
}

func generateDSPStatusCommands(dsp []structs.Device, evaluator string, command string) ([]StatusCommand, int, error) {

	var commands []StatusCommand

	//validate the correct number of dsps
	if dsp == nil || len(dsp) != 1 {
		errorMessage := "[statusevals] Invalid number of DSP devices found in room: " + strconv.Itoa(len(dsp))
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	if !device.HasRole(dsp[0], "AudioOut") {
		//we don't need to get the state of it
		return []StatusCommand{}, 0, nil
	}

	log.L.Infof("[statusevals] Generating DSP status command: %s against device: %s", command, dsp[0])

	parameters := make(map[string]string)
	parameters["address"] = dsp[0].Address

	statusCommand := dsp[0].GetCommandByName(command)

	destinationDevice := base.DestinationDevice{
		Device:      dsp[0],
		AudioDevice: true,
	}
	var count int

	//one command for each port that's not a mic
	for _, port := range dsp[0].Ports {

		device, err := db.GetDB().GetDevice(dsp[0].ID)
		if err != nil {
			return []StatusCommand{}, 0, err
		}

		if !structs.HasRole(device, "Microphone") {

			parameters["input"] = port.ID
			commands = append(commands, StatusCommand{
				Action:            statusCommand,
				Device:            dsp[0],
				Generator:         evaluator,
				DestinationDevice: destinationDevice,
				Parameters:        parameters,
			})
		}
		count++
	}

	return commands, count, nil
}
<commit_msg>fixing dsp command evaluator to only get status of non microphone ports when audio out device<commit_after>package statusevaluators

import (
	"errors"
	"strconv"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/common/db"
	"github.com/byuoitav/common/log"
	"github.com/byuoitav/common/structs"
	"github.com/fatih/color"
)

/* ASSUMPTIONS

a) a mic has only one port configuration with the DSP as a destination device

*/

// MutedDSPEvaluator is a constant variable for the name of the evaluator.
const MutedDSPEvaluator = "STATUS_MutedDSP"

// MutedDSPCommand is a constant variable for the name of the command.
const MutedDSPCommand = "STATUS_MutedDSP"

// MutedDSP implements the StatusEvaluator struct.
type MutedDSP struct{}

// GetDevices returns a list of devices in the given room.
func (p *MutedDSP) GetDevices(room structs.Room) ([]structs.Device, error) {

	return room.Devices, nil
}

// GenerateCommands generates a list of commands for the given devices.
func (p *MutedDSP) GenerateCommands(devices []structs.Device) ([]StatusCommand, int, error) {

	log.L.Info("[statusevals] Generating \"Muted\" status commands...")

	//sort mics out of audio devices:w
	var audioDevices, mics, dsp []structs.Device

	for _, device := range devices {

		log.L.Infof("[statusevals] Considering device: %s", device.Name)

		if structs.HasRole(device, "Microphone") {

			mics = append(mics, device)
		} else if structs.HasRole(device, "DSP") {

			dsp = append(dsp, device)
		} else if structs.HasRole(device, "AudioOut") {

			audioDevices = append(audioDevices, device)
		} else {
			continue
		}
	}

	//business as ususal for audioDevices
	commands, count, err := generateStandardStatusCommand(audioDevices, MutedDSPEvaluator, MutedDefaultCommand)
	if err != nil {
		errorMessage := "[statusevals] Could not generate audio device status commands: " + err.Error()
		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	micCommands, c, err := generateMicStatusCommands(mics, MutedDSPEvaluator, MutedDSPCommand)
	if err != nil {
		errorMessage := "[statusevals] Could not generate microphone status commands: " + err.Error()
		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	count += c
	commands = append(commands, micCommands...)

	dspCommands, c, err := generateDSPStatusCommands(dsp, MutedDSPEvaluator, MutedDSPCommand)
	if err != nil {
		return []StatusCommand{}, 0, err
	}

	count += c
	commands = append(commands, dspCommands...)

	log.L.Infof(color.HiYellowString("[STATUS-Muted-DSP] Generated %v commands", len(commands)))
	return commands, count, nil

}

// EvaluateResponse processes the response information that is given.
func (p *MutedDSP) EvaluateResponse(label string, value interface{}, source structs.Device, destintation base.DestinationDevice) (string, interface{}, error) {

	return label, value, nil
}

func generateMicStatusCommands(mics []structs.Device, evaluator string, command string) ([]StatusCommand, int, error) {

	log.L.Infof("[statusevals] Generating %s commands agains mics...", command)

	var commands []StatusCommand

	if len(mics) == 0 {
		errorMessage := "[statusevals] No mics"

		log.L.Error(errorMessage)
		return []StatusCommand{}, 0, nil
	}

	dsp, err := db.GetDB().GetDevicesByRoomAndRole(mics[0].GetDeviceRoomID(), "DSP")
	if err != nil {
		return []StatusCommand{}, 0, err
	}

	if len(dsp) != 1 {
		errorMessage := "[statusevals] Invalid number of DSP devices found in room: " + strconv.Itoa(len(dsp))
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	var count int

	for _, mic := range mics {

		log.L.Infof("[statusevals] Considering mic %s...", mic.Name)

		//find the only DSP the room has

		for _, port := range dsp[0].Ports {

			if port.SourceDevice == mic.ID {
				log.L.Infof("[statusevals] Port configuration identified for mic %s and DSP %s", mic.Name, dsp[0].Name)
				destinationDevice := base.DestinationDevice{
					Device:      mic,
					AudioDevice: true,
				}

				statusCommand := dsp[0].GetCommandByName(command)

				parameters := make(map[string]string)
				parameters["input"] = port.ID
				parameters["address"] = dsp[0].Address

				//issue status command to DSP
				commands = append(commands, StatusCommand{
					Action:            statusCommand,
					Device:            dsp[0],
					Generator:         MutedDSPEvaluator,
					DestinationDevice: destinationDevice,
					Parameters:        parameters,
				})
				count++
			}
		}

	}

	return commands, count, nil
}

func generateDSPStatusCommands(dsp []structs.Device, evaluator string, command string) ([]StatusCommand, int, error) {

	var commands []StatusCommand

	//validate the correct number of dsps
	if dsp == nil || len(dsp) != 1 {
		errorMessage := "[statusevals] Invalid number of DSP devices found in room: " + strconv.Itoa(len(dsp))
		return []StatusCommand{}, 0, errors.New(errorMessage)
	}

	if !structs.HasRole(dsp[0], "AudioOut") {
		//we don't need to get the state of it
		return []StatusCommand{}, 0, nil
	}

	log.L.Infof("[statusevals] Generating DSP status command: %s against device: %s", command, dsp[0])

	parameters := make(map[string]string)
	parameters["address"] = dsp[0].Address

	statusCommand := dsp[0].GetCommandByName(command)

	destinationDevice := base.DestinationDevice{
		Device:      dsp[0],
		AudioDevice: true,
	}
	var count int

	//one command for each port that's not a mic
	for _, port := range dsp[0].Ports {

		device, err := db.GetDB().GetDevice(port.SourceDevice)
		if err != nil {
			return []StatusCommand{}, 0, err
		}

		if !structs.HasRole(device, "Microphone") {

			parameters["input"] = port.ID
			commands = append(commands, StatusCommand{
				Action:            statusCommand,
				Device:            dsp[0],
				Generator:         evaluator,
				DestinationDevice: destinationDevice,
				Parameters:        parameters,
			})
		}
		count++
	}

	return commands, count, nil
}
<|endoftext|>


<commit_before>// Package unidecode implements a unicode transliterator
// which replaces non-ASCII characters with their ASCII
// approximations.
package unidecode

import (
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"encoding/base64"
	"io"
	"sync"
	"unicode"

	"gopkgs.com/pool.v1"
)

const pooledCapacity = 64

var (
	mutex            sync.Mutex
	transliterations [65536][]rune

	slicePool  = pool.New(0)
	decoded    = false
	transCount = rune(len(transliterations))
	getUint16  = binary.LittleEndian.Uint16
)

func decodeTransliterations() {
	data, err := base64.StdEncoding.DecodeString(tableData)
	if err != nil {
		panic(err)
	}
	r, err := zlib.NewReader(bytes.NewBuffer(data))
	if err != nil {
		panic(err)
	}
	defer r.Close()
	tmp1 := make([]byte, 2)
	tmp2 := tmp1[:1]
	for {
		if _, err := io.ReadAtLeast(r, tmp1, 2); err != nil {
			if err == io.EOF {
				break
			}
			panic(err)
		}
		chr := getUint16(tmp1)
		if _, err := io.ReadAtLeast(r, tmp2, 1); err != nil {
			panic(err)
		}
		b := make([]byte, int(tmp2[0]))
		if _, err := io.ReadFull(r, b); err != nil {
			panic(err)
		}
		transliterations[int(chr)] = []rune(string(b))
	}
}

// Unidecode implements a unicode transliterator, which
// replaces non-ASCII characters with their ASCII
// counterparts.
// Given an unicode encoded string, returns
// another string with non-ASCII characters replaced
// with their closest ASCII counterparts.
// e.g. Unicode("áéíóú") => "aeiou"
func Unidecode(s string) string {
	if !decoded {
		mutex.Lock()
		if !decoded {
			decodeTransliterations()
			decoded = true
		}
		mutex.Unlock()
	}
	l := len(s)
	var r []rune
	if l > pooledCapacity {
		r = make([]rune, 0, len(s))
	} else {
		if x := slicePool.Get(); x != nil {
			r = x.([]rune)[:0]
		} else {
			r = make([]rune, 0, pooledCapacity)
		}
	}
	for _, c := range s {
		if c <= unicode.MaxASCII {
			r = append(r, c)
			continue
		}
		if c > unicode.MaxRune || c > transCount {
			/* Ignore reserved chars */
			continue
		}
		if d := transliterations[c]; d != nil {
			r = append(r, d...)
		}
	}
	res := string(r)
	if l <= pooledCapacity {
		slicePool.Put(r)
	}
	return res
}
<commit_msg>Remove go <1.3 sync.Pool compat<commit_after>// Package unidecode implements a unicode transliterator
// which replaces non-ASCII characters with their ASCII
// approximations.
package unidecode

import (
	"bytes"
	"compress/zlib"
	"encoding/base64"
	"encoding/binary"
	"io"
	"sync"
	"unicode"
)

const pooledCapacity = 64

var (
	mutex            sync.Mutex
	transliterations [65536][]rune

	slicePool  = new(sync.Pool)
	decoded    = false
	transCount = rune(len(transliterations))
	getUint16  = binary.LittleEndian.Uint16
)

func decodeTransliterations() {
	data, err := base64.StdEncoding.DecodeString(tableData)
	if err != nil {
		panic(err)
	}
	r, err := zlib.NewReader(bytes.NewBuffer(data))
	if err != nil {
		panic(err)
	}
	defer r.Close()
	tmp1 := make([]byte, 2)
	tmp2 := tmp1[:1]
	for {
		if _, err := io.ReadAtLeast(r, tmp1, 2); err != nil {
			if err == io.EOF {
				break
			}
			panic(err)
		}
		chr := getUint16(tmp1)
		if _, err := io.ReadAtLeast(r, tmp2, 1); err != nil {
			panic(err)
		}
		b := make([]byte, int(tmp2[0]))
		if _, err := io.ReadFull(r, b); err != nil {
			panic(err)
		}
		transliterations[int(chr)] = []rune(string(b))
	}
}

// Unidecode implements a unicode transliterator, which
// replaces non-ASCII characters with their ASCII
// counterparts.
// Given an unicode encoded string, returns
// another string with non-ASCII characters replaced
// with their closest ASCII counterparts.
// e.g. Unicode("áéíóú") => "aeiou"
func Unidecode(s string) string {
	if !decoded {
		mutex.Lock()
		if !decoded {
			decodeTransliterations()
			decoded = true
		}
		mutex.Unlock()
	}
	l := len(s)
	var r []rune
	if l > pooledCapacity {
		r = make([]rune, 0, len(s))
	} else {
		if x := slicePool.Get(); x != nil {
			r = x.([]rune)[:0]
		} else {
			r = make([]rune, 0, pooledCapacity)
		}
	}
	for _, c := range s {
		if c <= unicode.MaxASCII {
			r = append(r, c)
			continue
		}
		if c > unicode.MaxRune || c > transCount {
			/* Ignore reserved chars */
			continue
		}
		if d := transliterations[c]; d != nil {
			r = append(r, d...)
		}
	}
	res := string(r)
	if l <= pooledCapacity {
		slicePool.Put(r)
	}
	return res
}
<|endoftext|>


<commit_before>// uniq: remove repeated adjacent lines
package main

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

var (
	counter int = 1 // default to 1 as this is the minimum value
	c       *bool
)

func printLine(out io.Writer, line string) {
	if *c {
		fmt.Fprintf(out, "%d %s", counter, line)
	} else {
		fmt.Fprintf(out, "%s", line)
	}
}

// Open the input and output file descriptors
func openFiles(args []string) (*bufio.Reader, *os.File) {
	var reader *bufio.Reader
	var out = os.Stdout

	if len(args) == 0 {
		return bufio.NewReader(os.Stdin), out
	}

	if len(args) > 1 {
		f, err := os.OpenFile(args[1],
			os.O_CREATE|os.O_WRONLY|os.O_TRUNC,
			os.FileMode(0666))
		if err != nil {
			log.Fatalf("Error: %v\n", err)
		}
		out = f
	}

	f, err := os.Open(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}
	reader = bufio.NewReader(f)

	return reader, out
}

func isSpecialOperation(u, d bool) bool {
	return !(d && u) // one of d and u are true, but not both
}

func isPrintLastLine(u, d bool, counter int) bool {
	return isSpecialOperation(u, d) && !(u && counter > 1) && !(d && counter == 1)
}

func main() {
	var reader *bufio.Reader
	var out *os.File
	var lastLine string

	c = flag.Bool("c", false, "precede each output line with a count of the number of times it occurred")
	d := flag.Bool("d", false, "only print duplicate lines, one for each group")
	u := flag.Bool("u", false, "only print non duplicate lines")

	flag.Parse()
	args := flag.Args()

	// Operation
	var defaultOperation = !*d && !*u

	// Open stdin or provided file as input, and stdout or provided file as output
	reader, out = openFiles(args)

	// Buffer the 1st line
	line, err := reader.ReadString('\n')
	if err != nil && err != io.EOF {
		log.Fatalf("error: %v\n", err)
	}
	lastLine = line

	// Loop over the rest of the provided input
	for {
		line, err := reader.ReadString('\n')

		if err == io.EOF {
			if len(line) == 0 {
				if isPrintLastLine(*u, *d, counter) {
					printLine(out, lastLine)
				}
				break
			}
		} else if err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		if line != lastLine {
			if defaultOperation {
				printLine(out, lastLine)
			} else if isSpecialOperation(*u, *d) {
				if *d && counter > 1 {
					printLine(out, lastLine)
				} else if *u && counter == 1 {
					printLine(out, lastLine)
				}
			}
			counter = 0 // reset to the minimum value -1
		}

		counter++
		lastLine = line
	}

	if err := out.Close(); err != nil {
		log.Fatalf("Error %v\n", err)
	}

	os.Exit(0)
}
<commit_msg>Simplify uniq's main() function further<commit_after>// uniq: remove repeated adjacent lines
package main

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

var (
	counter int = 1 // default to 1 as this is the minimum value
	c       *bool
)

func printLine(out io.Writer, line string) {
	if *c {
		fmt.Fprintf(out, "%d %s", counter, line)
	} else {
		fmt.Fprintf(out, "%s", line)
	}
}

// Open the input and output file descriptors
func openFiles(args []string) (*bufio.Reader, *os.File) {
	var reader *bufio.Reader
	var out = os.Stdout

	if len(args) == 0 {
		return bufio.NewReader(os.Stdin), out
	}

	if len(args) > 1 {
		f, err := os.OpenFile(args[1],
			os.O_CREATE|os.O_WRONLY|os.O_TRUNC,
			os.FileMode(0666))
		if err != nil {
			log.Fatalf("Error: %v\n", err)
		}
		out = f
	}

	f, err := os.Open(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}
	reader = bufio.NewReader(f)

	return reader, out
}

func isDefaultOperation(u, d bool) bool {
	return !d && !u
}

func isSpecialOperation(u, d bool) bool {
	return !(d && u) // one of d and u are true, but not both
}

func isPrintLastLine(u, d bool, counter int) bool {
	return isSpecialOperation(u, d) && !(u && counter > 1) && !(d && counter == 1)
}

func printLineOnChange(out *os.File, line string, u, d bool, counter int) {
	if isDefaultOperation(u, d) {
		printLine(out, line)
	} else if isSpecialOperation(u, d) {
		if d && counter > 1 {
			printLine(out, line)
		} else if u && counter == 1 {
			printLine(out, line)
		}
	}
}

func main() {
	var reader *bufio.Reader
	var out *os.File
	var lastLine string

	c = flag.Bool("c", false, "precede each output line with a count of the number of times it occurred")
	d := flag.Bool("d", false, "only print duplicate lines, one for each group")
	u := flag.Bool("u", false, "only print non duplicate lines")

	flag.Parse()
	args := flag.Args()

	// Open stdin or provided file as input, and stdout or provided file as output
	reader, out = openFiles(args)

	// Buffer the 1st line
	line, err := reader.ReadString('\n')
	if err != nil && err != io.EOF {
		log.Fatalf("error: %v\n", err)
	}
	lastLine = line

	// Loop over the rest of the provided input
	for {
		line, err := reader.ReadString('\n')

		if err == io.EOF {
			if len(line) == 0 {
				if isPrintLastLine(*u, *d, counter) {
					printLine(out, lastLine)
				}
				break
			}
		} else if err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		if line != lastLine {
			printLineOnChange(out, lastLine, *u, *d, counter)
			counter = 0 // reset to the minimum value -1
		}

		counter++
		lastLine = line
	}

	if err := out.Close(); err != nil {
		log.Fatalf("Error %v\n", err)
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

func LogicalLines([]byte) [][]byte {
	return nil
}

func Parse(args []byte) (*Statement, error) {
	return nil, nil
}

func ParseFrom(body []byte) (*From, error) {
	return nil, nil
}

func ParseMaintainer(body []byte) (*Maintainer, error) {
	return nil, nil
}

func ParseRun(body []byte) (*Run, error) {
	return nil, nil
}

func ParseCmd(body []byte) (*Cmd, error) {
	return nil, nil
}

func ParseLable(body []byte) (*Label, error) {
	return nil, nil
}

func ParseExpose(body []byte) (*Expose, error) {
	return nil, nil
}

func ParseEnv(body []byte) (*Env, error) {
	return nil, nil
}

func ParseAdd(body []byte) (*Add, error) {
	return nil, nil
}

func ParseCopy(body []byte) (*Copy, error) {
	return nil, nil
}

func ParseEntrypoint(body []byte) (*Entrypoint, error) {
	return nil, nil
}

func ParseVolume(body []byte) (*Volume, error) {
	return nil, nil
}

func ParseUser(body []byte) (*User, error) {
	return nil, nil
}

func ParseWorkdir(body []byte) (*Workdir, error) {
	return nil, nil
}

func ParseOnbuild(body []byte) (*Onbuild, error) {
	return nil, nil
}

func (df *Dockerfile) Unmarshal(src []byte) error {
	return nil
}
<commit_msg>Implement MAINTAINER parsing<commit_after>package main

import (
	"strings"
)

func LogicalLines([]byte) [][]byte {
	return nil
}

func Parse(args []byte) (*Statement, error) {
	return nil, nil
}

func ParseFrom(body []byte) (*From, error) {
	return nil, nil
}

func ParseMaintainer(body []byte) (*Maintainer, error) {
	s := strings.TrimSpace(string(body))
	return &Maintainer{Name: s}, nil
}

func ParseRun(body []byte) (*Run, error) {
	return nil, nil
}

func ParseCmd(body []byte) (*Cmd, error) {
	return nil, nil
}

func ParseLable(body []byte) (*Label, error) {
	return nil, nil
}

func ParseExpose(body []byte) (*Expose, error) {
	return nil, nil
}

func ParseEnv(body []byte) (*Env, error) {
	return nil, nil
}

func ParseAdd(body []byte) (*Add, error) {
	return nil, nil
}

func ParseCopy(body []byte) (*Copy, error) {
	return nil, nil
}

func ParseEntrypoint(body []byte) (*Entrypoint, error) {
	return nil, nil
}

func ParseVolume(body []byte) (*Volume, error) {
	return nil, nil
}

func ParseUser(body []byte) (*User, error) {
	return nil, nil
}

func ParseWorkdir(body []byte) (*Workdir, error) {
	return nil, nil
}

func ParseOnbuild(body []byte) (*Onbuild, error) {
	return nil, nil
}

func (df *Dockerfile) Unmarshal(src []byte) error {
	return nil
}
<|endoftext|>


<commit_before>package main

import "strings"

// platformStrings is a list of platform names to look for in User-Agent
// strings. The order matters; the first one found will be considered the
// correct result.
var platformStrings = []string{
	"Android",
	"Linux",
	"Macintosh",
	"iPad",
	"iPod",
	"iPhone",
	"iOS",
	"Darwin",
	"Windows",
	"Blackberry",
	"MAC",
	"Mac",
	"Microsoft",
	"MICROSOFT",
	"WIN",
	"Win",
	"GoogleAuth",
	"okhttp",
	"CaptiveNetworkSupport",
	"MobileAsset",
}

var platformAliases = map[string]string{
	"MAC":                   "Macintosh",
	"Mac":                   "Macintosh",
	"MICROSOFT":             "Windows",
	"Microsoft":             "Windows",
	"WIN":                   "Windows",
	"Win":                   "Windows",
	"GoogleAuth":            "Android",
	"okhttp":                "Android",
	"CaptiveNetworkSupport": "Darwin",
	"MobileAsset":           "Darwin",
	"iOS":                   "Darwin",
}

var darwinPlatforms = map[string]bool{
	"Macintosh": true,
	"iPhone":    true,
	"iPad":      true,
	"iPod":      true,
	"Darwin":    true,
}

// platform examines a User-Agent string and attempts to return
// the platform that the client is running on. If it can't detect the platform,
// it returns the empty string. Apple products are distinguished if possible
// (Macintosh, iPad, etc.), but often will be just Darwin.
func platform(ua string) string {
	for _, p := range platformStrings {
		if strings.Contains(ua, p) {
			if p2, ok := platformAliases[p]; ok {
				p = p2
			}
			return p
		}
	}

	return ""
}
<commit_msg>Recognize more User-Agent strings.<commit_after>package main

import "strings"

// platformStrings is a list of platform names to look for in User-Agent
// strings. The order matters; the first one found will be considered the
// correct result.
var platformStrings = []string{
	"Android",
	"Linux",
	"Macintosh",
	"iPad",
	"iPod",
	"iPhone",
	"iOS",
	"Darwin",
        "dataaccessd",
	"Windows",
	"Blackberry",
	"BlackBerry",
	"BB10",
	"MAC",
	"Mac",
	"Microsoft",
	"MICROSOFT",
	"MS Web Service",
	"WIN",
	"Win",
	"GoogleAuth",
        "Gms-Backup",
        "GmsCore",
	"okhttp",
	"CaptiveNetworkSupport",
        "CloudKit",
	"CFNetwork",
}

var platformAliases = map[string]string{
	"BB10":                  "Blackberry",
	"BlackBerry":            "Blackberry",
	"MAC":                   "Macintosh",
	"Mac":                   "Macintosh",
	"MICROSOFT":             "Windows",
	"Microsoft":             "Windows",
	"MS Web Service":        "Windows",
	"WIN":                   "Windows",
	"Win":                   "Windows",
	"GoogleAuth":            "Android",
	"Gms-Backup":            "Android",
	"Gms-Core":              "Android",
	"okhttp":                "Android",
	"CaptiveNetworkSupport": "Darwin",
	"CloudKit":              "Darwin",
	"CFNetwork":             "Darwin",
	"dataaccessd":           "Darwin",
	"iOS":                   "Darwin",
}

var darwinPlatforms = map[string]bool{
	"Macintosh": true,
	"iPhone":    true,
	"iPad":      true,
	"iPod":      true,
	"Darwin":    true,
}

// platform examines a User-Agent string and attempts to return
// the platform that the client is running on. If it can't detect the platform,
// it returns the empty string. Apple products are distinguished if possible
// (Macintosh, iPad, etc.), but often will be just Darwin.
func platform(ua string) string {
	for _, p := range platformStrings {
		if strings.Contains(ua, p) {
			if p2, ok := platformAliases[p]; ok {
				p = p2
			}
			return p
		}
	}

	return ""
}
<|endoftext|>


<commit_before>package util

import (
	"crypto"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	s "github.com/fullsailor/pkcs7"
	"github.com/mundipagg/boleto-api/config"
)

var defaultDialer = &net.Dialer{Timeout: 16 * time.Second, KeepAlive: 16 * time.Second}

var cfg *tls.Config = &tls.Config{
	InsecureSkipVerify: true,
}
var client *http.Client = &http.Client{
	Transport: &http.Transport{
		TLSClientConfig:     cfg,
		Dial:                defaultDialer.Dial,
		TLSHandshakeTimeout: 16 * time.Second,
	},
}

// DefaultHTTPClient retorna um cliente http configurado para dar um skip na validação do certificado digital
func DefaultHTTPClient() *http.Client {
	return client
}

//Post faz um requisição POST para uma URL e retorna o response, status e erro
func Post(url, body, timeout string, header map[string]string) (string, int, error) {
	return doRequest("POST", url, body, timeout, header)
}

//Get faz um requisição GET para uma URL e retorna o response, status e erro
func Get(url, body, timeout string, header map[string]string) (string, int, error) {
	return doRequest("GET", url, body, timeout, header)
}

func doRequest(method, url, body, timeout string, header map[string]string) (string, int, error) {
	client := DefaultHTTPClient()
	client.Timeout = GetDurationTimeoutRequest(timeout) * time.Second
	message := strings.NewReader(body)
	req, err := http.NewRequest(method, url, message)
	if err != nil {
		return "", http.StatusInternalServerError, err
	}
	if header != nil {
		for k, v := range header {
			req.Header.Add(k, v)
		}
	}
	resp, errResp := client.Do(req)
	if errResp != nil {
		return "", 0, errResp
	}
	defer resp.Body.Close()
	data, errResponse := ioutil.ReadAll(resp.Body)
	if errResponse != nil {
		return "", resp.StatusCode, errResponse
	}
	sData := string(data)
	return sData, resp.StatusCode, nil
}

//BuildTLSTransport creates a TLS Client Transport from crt, ca and key files
func BuildTLSTransport(crtPath string, keyPath string, caPath string) (*http.Transport, error) {
	cert, err := tls.LoadX509KeyPair(crtPath, keyPath)
	if err != nil {
		return nil, err
	}

	caCert, err := ioutil.ReadFile(caPath)
	if err != nil {
		return nil, err
	}

	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	tlsConfig := &tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	}
	return &http.Transport{TLSClientConfig: tlsConfig}, nil
}

//Sigs request
func SignRequest(request string) (string, error) {

	pkey, err := parsePrivateKey()
	if err != nil {
		return "", err
	}

	chainCertificates, err := parseChainCertificates()
	if err != nil {
		return "", err
	}

	signedData, err := s.NewSignedData([]byte(request))
	if err != nil {
		return "", err
	}

	err = signedData.AddSigner(chainCertificates, pkey, s.SignerInfoConfig{})
	if err != nil {
		return "", err
	}

	detachedSignature, err := signedData.Finish()
	if err != nil {
		return "", err
	}

	signedRequest := base64.StdEncoding.EncodeToString(detachedSignature)

	return signedRequest, nil
}

//Read privatekey and parse to PKCS#1
func parsePrivateKey() (crypto.PrivateKey, error) {

	pkeyBytes, err := ioutil.ReadFile(config.Get().CertICP_PathPkey)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(pkeyBytes)
	if block == nil {
		return nil, errors.New("Key Not Found")
	}

	switch block.Type {
	case "RSA PRIVATE KEY":
		rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes)
		if err != nil {
			return nil, err
		}
		return rsa, nil
	default:
		return nil, fmt.Errorf("SSH: Unsupported key type %q", block.Type)
	}

}

///Read chainCertificates and adapter to x509.Certificate
func parseChainCertificates() (*x509.Certificate, error) {

	chainCertsBytes, err := ioutil.ReadFile(config.Get().CertICP_PathChainCertificates)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(chainCertsBytes)
	if block == nil {
		return nil, errors.New("Key Not Found")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, err
	}

	return cert, nil
}

func doRequestTLS(method, url, body, timeout string, header map[string]string, transport *http.Transport) (string, int, error) {
	var client *http.Client = &http.Client{
		Transport: transport,
	}
	client.Timeout = GetDurationTimeoutRequest(timeout) * time.Second
	b := strings.NewReader(body)
	req, err := http.NewRequest(method, url, b)
	if err != nil {
		return "", 0, err
	}

	if header != nil {
		for k, v := range header {
			req.Header.Add(k, v)
		}
	}
	resp, err := client.Do(req)
	if err != nil {
		return "", 0, err
	}
	defer resp.Body.Close()
	// Dump response
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", 0, err
	}
	sData := string(data)
	return sData, resp.StatusCode, nil
}

func PostTLS(url, body, timeout string, header map[string]string, transport *http.Transport) (string, int, error) {
	return doRequestTLS("POST", url, body, timeout, header, transport)
}

//HeaderToMap converte um http Header para um dicionário string -> string
func HeaderToMap(h http.Header) map[string]string {
	m := make(map[string]string)
	for k, v := range h {
		m[k] = v[0]
	}
	return m
}
<commit_msg>:fire: Remove atualização de signedData<commit_after>package util

import (
	"crypto"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	s "github.com/fullsailor/pkcs7"
	"github.com/mundipagg/boleto-api/config"
)

var defaultDialer = &net.Dialer{Timeout: 16 * time.Second, KeepAlive: 16 * time.Second}

var cfg *tls.Config = &tls.Config{
	InsecureSkipVerify: true,
}
var client *http.Client = &http.Client{
	Transport: &http.Transport{
		TLSClientConfig:     cfg,
		Dial:                defaultDialer.Dial,
		TLSHandshakeTimeout: 16 * time.Second,
	},
}

// DefaultHTTPClient retorna um cliente http configurado para dar um skip na validação do certificado digital
func DefaultHTTPClient() *http.Client {
	return client
}

//Post faz um requisição POST para uma URL e retorna o response, status e erro
func Post(url, body, timeout string, header map[string]string) (string, int, error) {
	return doRequest("POST", url, body, timeout, header)
}

//Get faz um requisição GET para uma URL e retorna o response, status e erro
func Get(url, body, timeout string, header map[string]string) (string, int, error) {
	return doRequest("GET", url, body, timeout, header)
}

func doRequest(method, url, body, timeout string, header map[string]string) (string, int, error) {
	client := DefaultHTTPClient()
	client.Timeout = GetDurationTimeoutRequest(timeout) * time.Second
	message := strings.NewReader(body)
	req, err := http.NewRequest(method, url, message)
	if err != nil {
		return "", http.StatusInternalServerError, err
	}
	if header != nil {
		for k, v := range header {
			req.Header.Add(k, v)
		}
	}
	resp, errResp := client.Do(req)
	if errResp != nil {
		return "", 0, errResp
	}
	defer resp.Body.Close()
	data, errResponse := ioutil.ReadAll(resp.Body)
	if errResponse != nil {
		return "", resp.StatusCode, errResponse
	}
	sData := string(data)
	return sData, resp.StatusCode, nil
}

//BuildTLSTransport creates a TLS Client Transport from crt, ca and key files
func BuildTLSTransport(crtPath string, keyPath string, caPath string) (*http.Transport, error) {
	cert, err := tls.LoadX509KeyPair(crtPath, keyPath)
	if err != nil {
		return nil, err
	}

	caCert, err := ioutil.ReadFile(caPath)
	if err != nil {
		return nil, err
	}

	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	tlsConfig := &tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	}
	return &http.Transport{TLSClientConfig: tlsConfig}, nil
}

//Sigs request
func SignRequest(request string) (string, error) {

	pkey, err := parsePrivateKey()
	if err != nil {
		return "", err
	}

	chainCertificates, err := parseChainCertificates()
	if err != nil {
		return "", err
	}

	signedData, err := s.NewSignedData([]byte(request))
	if err != nil {
		return "", err
	}

	if err := signedData.AddSigner(chainCertificates, pkey, s.SignerInfoConfig{}); err != nil {
		return "", err
	}

	detachedSignature, err := signedData.Finish()
	if err != nil {
		return "", err
	}

	signedRequest := base64.StdEncoding.EncodeToString(detachedSignature)

	return signedRequest, nil
}

//Read privatekey and parse to PKCS#1
func parsePrivateKey() (crypto.PrivateKey, error) {

	pkeyBytes, err := ioutil.ReadFile(config.Get().CertICP_PathPkey)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(pkeyBytes)
	if block == nil {
		return nil, errors.New("Key Not Found")
	}

	switch block.Type {
	case "RSA PRIVATE KEY":
		rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes)
		if err != nil {
			return nil, err
		}
		return rsa, nil
	default:
		return nil, fmt.Errorf("SSH: Unsupported key type %q", block.Type)
	}

}

///Read chainCertificates and adapter to x509.Certificate
func parseChainCertificates() (*x509.Certificate, error) {

	chainCertsBytes, err := ioutil.ReadFile(config.Get().CertICP_PathChainCertificates)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(chainCertsBytes)
	if block == nil {
		return nil, errors.New("Key Not Found")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, err
	}

	return cert, nil
}

func doRequestTLS(method, url, body, timeout string, header map[string]string, transport *http.Transport) (string, int, error) {
	var client *http.Client = &http.Client{
		Transport: transport,
	}
	client.Timeout = GetDurationTimeoutRequest(timeout) * time.Second
	b := strings.NewReader(body)
	req, err := http.NewRequest(method, url, b)
	if err != nil {
		return "", 0, err
	}

	if header != nil {
		for k, v := range header {
			req.Header.Add(k, v)
		}
	}
	resp, err := client.Do(req)
	if err != nil {
		return "", 0, err
	}
	defer resp.Body.Close()
	// Dump response
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", 0, err
	}
	sData := string(data)
	return sData, resp.StatusCode, nil
}

func PostTLS(url, body, timeout string, header map[string]string, transport *http.Transport) (string, int, error) {
	return doRequestTLS("POST", url, body, timeout, header, transport)
}

//HeaderToMap converte um http Header para um dicionário string -> string
func HeaderToMap(h http.Header) map[string]string {
	m := make(map[string]string)
	for k, v := range h {
		m[k] = v[0]
	}
	return m
}
<|endoftext|>


<commit_before>package util

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"

	"code.google.com/p/go.crypto/ssh"

	"github.com/coreos/shortbread/api"
)

const (
	SHORTBREADCTL_URL = "SHORTBREADCTL_URL"
	defaultURL        = "http://localhost:8080/v1/"
)

func GetHTTPClientService() (*api.Service, error) {
	return getHTTPClientService(GetenvWithDefault(SHORTBREADCTL_URL, defaultURL))
}

func getHTTPClientService(basePath string) (*api.Service, error) {
	dialFunc := func(string, string) (net.Conn, error) {
		addr, err := setAddress(basePath)
		if err != nil {
			return nil, err
		}
		return net.Dial("tcp", addr)
	}

	trans := http.Transport{
		Dial: dialFunc,
	}

	hc := &http.Client{
		Transport: &trans,
	}

	svc, err := api.New(hc)
	if err != nil {
		return nil, err
	}

	(*svc).BasePath = basePath
	return svc, nil
}

func LoadPublicKey(path string) string {
	keyToSignBytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}

	return string(keyToSignBytes)
}

func ParseSSHCert(rawCert []byte) (*ssh.Certificate, error) {
	certPubKey, _, _, _, err := ssh.ParseAuthorizedKey(rawCert)
	if err != nil {
		return nil, err
	}
	cert := certPubKey.(*ssh.Certificate)
	return cert, nil
}

// setAddress accepts the basepath as input and extracts the hostname and port number from the url.
func setAddress(basePath string) (string, error) {
	addr, err := url.Parse(basePath)
	if err != nil {
		return "", err
	}
	return addr.Host, nil
}

// GetenvWithDefault reads in the value of an environment variable and if it is undefined retuns the default value.
func GetenvWithDefault(variable, defaultValue string) string {
	v := os.Getenv(variable)
	if v != "" {
		return v
	}
	return defaultValue
}

// ParseDate converts the date into Unix Time (time since 1st Jan 1970 in seconds)
func ParseDate(layout, value string) (uint64, error) {
	if value == "0" {
		return 0, nil
	}

	t, err := time.Parse(layout, value)
	if err != nil {
		return 0, err
	}

	return uint64(t.Unix()), nil
}<commit_msg>util: change default for SHORTBREADCTL_URL<commit_after>package util

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"

	"code.google.com/p/go.crypto/ssh"

	"github.com/coreos/shortbread/api"
)

const (
	SHORTBREADCTL_URL = "SHORTBREADCTL_URL"
	defaultURL        = "http://localhost:8889/v1/"
)

func GetHTTPClientService() (*api.Service, error) {
	return getHTTPClientService(GetenvWithDefault(SHORTBREADCTL_URL, defaultURL))
}

func getHTTPClientService(basePath string) (*api.Service, error) {
	dialFunc := func(string, string) (net.Conn, error) {
		addr, err := setAddress(basePath)
		if err != nil {
			return nil, err
		}
		return net.Dial("tcp", addr)
	}

	trans := http.Transport{
		Dial: dialFunc,
	}

	hc := &http.Client{
		Transport: &trans,
	}

	svc, err := api.New(hc)
	if err != nil {
		return nil, err
	}

	(*svc).BasePath = basePath
	return svc, nil
}

func LoadPublicKey(path string) string {
	keyToSignBytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}

	return string(keyToSignBytes)
}

func ParseSSHCert(rawCert []byte) (*ssh.Certificate, error) {
	certPubKey, _, _, _, err := ssh.ParseAuthorizedKey(rawCert)
	if err != nil {
		return nil, err
	}
	cert := certPubKey.(*ssh.Certificate)
	return cert, nil
}

// setAddress accepts the basepath as input and extracts the hostname and port number from the url.
func setAddress(basePath string) (string, error) {
	addr, err := url.Parse(basePath)
	if err != nil {
		return "", err
	}
	return addr.Host, nil
}

// GetenvWithDefault reads in the value of an environment variable and if it is undefined retuns the default value.
func GetenvWithDefault(variable, defaultValue string) string {
	v := os.Getenv(variable)
	if v != "" {
		return v
	}
	return defaultValue
}

// ParseDate converts the date into Unix Time (time since 1st Jan 1970 in seconds)
func ParseDate(layout, value string) (uint64, error) {
	if value == "0" {
		return 0, nil
	}

	t, err := time.Parse(layout, value)
	if err != nil {
		return 0, err
	}

	return uint64(t.Unix()), nil
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"testing"
)

func TestParseLine(t *testing.T) {
	line1 := "http://example.com\t1"
	e, err := ParseLine(line1)

	if err != nil {
		t.Error("cannot parse line1")
	}
	if e.Label != POSITIVE {
		t.Error("Label must be POSITIVE")
	}

	line2 := "http://example.com\t-1"
	e, err = ParseLine(line2)

	if err != nil {
		t.Error("cannot parse line2")
	}
	if e.Label != NEGATIVE {
		t.Error("Label must be NEGATIVE")
	}

	line3 := "http://example.com"
	e, err = ParseLine(line3)

	if err != nil {
		t.Error("cannot parse line3")
	}
	if e.Label != UNLABELED {
		t.Error("Label must be UNLABELED")
	}

	line4 := "http://example.com\t2"
	e, err = ParseLine(line4)

	if e != nil {
		t.Error("wrong line format")
	}
}

func TestReadExamples(t *testing.T) {
	filename := "tech_input_example.txt"
	examples, err := ReadExamples(filename)

	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 0 {
		t.Error(fmt.Printf("%s should contain more than one examples", filename))
	}
}

func TestWriteExamples(t *testing.T) {
	filename := ".write_test.txt"
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	err := WriteExamples(Examples{e1, e2}, filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot write examples to %s", filename))
	}

	examples, err := ReadExamples(filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 2 {
		t.Error(fmt.Printf("%s should contain two examples", filename))
	}
}

func TestFilterLabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)

	examples := FilterLabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 2 {
		t.Error("Number of labeled examples should be 2")
	}
}

func TestFilterUnlabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e3.Title = "Google"

	examples := FilterUnlabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of unlabeled examples should be 1")
	}
}

func TestFilterStatusCodeOkExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e1.StatusCode = 200
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e2.StatusCode = 404
	e3 := NewExample("http://google.com", UNLABELED)
	e3.StatusCode = 304

	examples := FilterStatusCodeOkExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of examples (status code = 200) should be 1")
	}
}

func TestRemoveDuplicate(t *testing.T) {
	args := []string{"hoge", "fuga", "piyo", "hoge"}

	result := removeDuplicate(args)
	if len(result) != 3 {
		t.Error("Number of unique string in args should be 3")
	}
}

func TestSplitTrainAndDev(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e4 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e5 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e6 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e7 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e8 := NewExample("http://google.com", UNLABELED)
	e9 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e10 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	train, dev := splitTrainAndDev(Examples{e1, e2, e3, e4, e5, e6, e7, e8, e9, e10})
	if len(train) != 8 {
		t.Error("Number of training examples should be 8")
	}
	if len(dev) != 2 {
		t.Error("Number of dev examples should be 2")
	}
}

func TestAttachMetaData(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	examples := Examples{e1, e2, e3}
	AttachMetaData(NewCache(), examples)

	if examples[0].Title == "" {
		t.Error("Title must not be empty")
	}
	if examples[0].Body == "" {
		t.Error("Body must not be empty")
	}
	if len(examples[0].Fv) == 0 {
		t.Error("Feature vector must not be empty")
	}
}
<commit_msg>bodyはなくてもよい<commit_after>package main

import (
	"fmt"
	"testing"
)

func TestParseLine(t *testing.T) {
	line1 := "http://example.com\t1"
	e, err := ParseLine(line1)

	if err != nil {
		t.Error("cannot parse line1")
	}
	if e.Label != POSITIVE {
		t.Error("Label must be POSITIVE")
	}

	line2 := "http://example.com\t-1"
	e, err = ParseLine(line2)

	if err != nil {
		t.Error("cannot parse line2")
	}
	if e.Label != NEGATIVE {
		t.Error("Label must be NEGATIVE")
	}

	line3 := "http://example.com"
	e, err = ParseLine(line3)

	if err != nil {
		t.Error("cannot parse line3")
	}
	if e.Label != UNLABELED {
		t.Error("Label must be UNLABELED")
	}

	line4 := "http://example.com\t2"
	e, err = ParseLine(line4)

	if e != nil {
		t.Error("wrong line format")
	}
}

func TestReadExamples(t *testing.T) {
	filename := "tech_input_example.txt"
	examples, err := ReadExamples(filename)

	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 0 {
		t.Error(fmt.Printf("%s should contain more than one examples", filename))
	}
}

func TestWriteExamples(t *testing.T) {
	filename := ".write_test.txt"
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	err := WriteExamples(Examples{e1, e2}, filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot write examples to %s", filename))
	}

	examples, err := ReadExamples(filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 2 {
		t.Error(fmt.Printf("%s should contain two examples", filename))
	}
}

func TestFilterLabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)

	examples := FilterLabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 2 {
		t.Error("Number of labeled examples should be 2")
	}
}

func TestFilterUnlabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e3.Title = "Google"

	examples := FilterUnlabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of unlabeled examples should be 1")
	}
}

func TestFilterStatusCodeOkExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e1.StatusCode = 200
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e2.StatusCode = 404
	e3 := NewExample("http://google.com", UNLABELED)
	e3.StatusCode = 304

	examples := FilterStatusCodeOkExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of examples (status code = 200) should be 1")
	}
}

func TestRemoveDuplicate(t *testing.T) {
	args := []string{"hoge", "fuga", "piyo", "hoge"}

	result := removeDuplicate(args)
	if len(result) != 3 {
		t.Error("Number of unique string in args should be 3")
	}
}

func TestSplitTrainAndDev(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e4 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e5 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e6 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e7 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e8 := NewExample("http://google.com", UNLABELED)
	e9 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e10 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	train, dev := splitTrainAndDev(Examples{e1, e2, e3, e4, e5, e6, e7, e8, e9, e10})
	if len(train) != 8 {
		t.Error("Number of training examples should be 8")
	}
	if len(dev) != 2 {
		t.Error("Number of dev examples should be 2")
	}
}

func TestAttachMetaData(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	examples := Examples{e1, e2, e3}
	AttachMetaData(NewCache(), examples)

	if examples[0].Title == "" {
		t.Error("Title must not be empty")
	}
	if len(examples[0].Fv) == 0 {
		t.Error("Feature vector must not be empty")
	}
}
<|endoftext|>


<commit_before>package mrT

import (
	"bytes"
	"encoding/binary"

	"github.com/itsmontoya/seeker"
)

// ForEachFn is used for iterating through entries
type ForEachFn func(lineType byte, key, value []byte) (err error)

// ForEachRawFn is used for iterating through raw entries
type ForEachRawFn func(line []byte) (err error)

// ForEachTxnFn is used for iterating through transactions
type ForEachTxnFn func(ti *TxnInfo) (err error)

// TxnFn is used for transactions
type TxnFn func(txn *Txn) error

// TxnInfo is information about a transaction
type TxnInfo struct {
	// Transaction id
	ID string `json:"id"`
	// Timestamp of transaction
	TS int64 `json:"ts"`
	// List of actions
	Actions []*ActionInfo `json:"actions"`
}

func newActionInfo(put bool, key, value []byte) *ActionInfo {
	var a ActionInfo
	a.Put = put
	a.Key = string(key)
	a.Value = string(value)
	return &a
}

// ActionInfo is information about an action
type ActionInfo struct {
	Put   bool   `json:"put"`
	Key   string `json:"key"`
	Value string `json:"value"`
}

func getFirstCommit(buf *bytes.Buffer) (err error) {
	if buf.Bytes()[0] == TransactionLine {
		return seeker.ErrEndEarly
	}

	return
}

// getKV will extract the key and value from a payload
func getKV(b []byte) (key, value []byte) {
	// Set index at 8 to accommodate 8 bytes for key length
	idx := uint64(8)
	// Get key length
	lv := binary.LittleEndian.Uint64(b[0:idx])
	key = b[idx : lv+idx]

	// Increment index past our key bytes
	idx += lv
	// Get value length
	lv = binary.LittleEndian.Uint64(b[idx : idx+8])
	// Increment our index past the value length
	idx += 8

	// Get upper range in case we need to pack in data after the value
	value = b[idx : lv+idx]
	return
}

// getKVSafe will extract the key and value from a payload and apply copy on read
func getKVSafe(b []byte) (key, value []byte) {
	key, value = getKV(b)
	key = append([]byte{}, key...)
	value = append([]byte{}, value...)
	return
}

func getKey(b []byte) string {
	kb, _ := getKV(b)
	return string(kb)
}

func getLineType(buf *bytes.Buffer) (lineType byte, err error) {
	if lineType, err = buf.ReadByte(); err != nil {
		return
	}

	// Unread the byte we just read
	err = buf.UnreadByte()
	return
}

func endOnMatch(buf *bytes.Buffer) (err error) {
	return seeker.ErrEndEarly
}
<commit_msg>Add bounds check for getKV<commit_after>package mrT

import (
	"bytes"
	"encoding/binary"

	"github.com/itsmontoya/seeker"
)

// ForEachFn is used for iterating through entries
type ForEachFn func(lineType byte, key, value []byte) (err error)

// ForEachRawFn is used for iterating through raw entries
type ForEachRawFn func(line []byte) (err error)

// ForEachTxnFn is used for iterating through transactions
type ForEachTxnFn func(ti *TxnInfo) (err error)

// TxnFn is used for transactions
type TxnFn func(txn *Txn) error

// TxnInfo is information about a transaction
type TxnInfo struct {
	// Transaction id
	ID string `json:"id"`
	// Timestamp of transaction
	TS int64 `json:"ts"`
	// List of actions
	Actions []*ActionInfo `json:"actions"`
}

func newActionInfo(put bool, key, value []byte) *ActionInfo {
	var a ActionInfo
	a.Put = put
	a.Key = string(key)
	a.Value = string(value)
	return &a
}

// ActionInfo is information about an action
type ActionInfo struct {
	Put   bool   `json:"put"`
	Key   string `json:"key"`
	Value string `json:"value"`
}

func getFirstCommit(buf *bytes.Buffer) (err error) {
	if buf.Bytes()[0] == TransactionLine {
		return seeker.ErrEndEarly
	}

	return
}

// getKV will extract the key and value from a payload
func getKV(b []byte) (key, value []byte) {
	// Set index at 8 to accommodate 8 bytes for key length
	idx := uint64(8)
	blen := uint64(len(b))
	if blen < idx {
		return
	}

	// Get key length
	lv := binary.LittleEndian.Uint64(b[0:idx])
	if blen < idx+lv {
		return
	}

	key = b[idx : lv+idx]

	// Increment index past our key bytes
	idx += lv
	if blen < idx {
		return
	}

	// Get value length
	lv = binary.LittleEndian.Uint64(b[idx : idx+8])
	// Increment our index past the value length
	idx += 8
	if blen < lv+idx {
		return
	}

	// Get upper range in case we need to pack in data after the value
	value = b[idx : lv+idx]
	return
}

// getKVSafe will extract the key and value from a payload and apply copy on read
func getKVSafe(b []byte) (key, value []byte) {
	key, value = getKV(b)
	key = append([]byte{}, key...)
	value = append([]byte{}, value...)
	return
}

func getKey(b []byte) string {
	kb, _ := getKV(b)
	return string(kb)
}

func getLineType(buf *bytes.Buffer) (lineType byte, err error) {
	if lineType, err = buf.ReadByte(); err != nil {
		return
	}

	// Unread the byte we just read
	err = buf.UnreadByte()
	return
}

func endOnMatch(buf *bytes.Buffer) (err error) {
	return seeker.ErrEndEarly
}
<|endoftext|>


<commit_before>package v2

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/golang/glog"
)

const (
	// APIVersionHeader is the header value associated with the version of the Open
	// Service Broker API version.
	APIVersionHeader = "X-Broker-API-Version"
	// OriginatingIdentityHeader is the header associated with originating
	// identity.
	OriginatingIdentityHeader = "X-Broker-API-Originating-Identity"

	catalogURL                 = "%s/v2/catalog"
	serviceInstanceURLFmt      = "%s/v2/service_instances/%s"
	lastOperationURLFmt        = "%s/v2/service_instances/%s/last_operation"
	bindingLastOperationURLFmt = "%s/v2/service_instances/%s/service_bindings/%s/last_operation"
	bindingURLFmt              = "%s/v2/service_instances/%s/service_bindings/%s"
)

// NewClient is a CreateFunc for creating a new functional Client and
// implements the CreateFunc interface.
func NewClient(config *ClientConfiguration) (Client, error) {
	httpClient := &http.Client{
		Timeout: time.Duration(config.TimeoutSeconds) * time.Second,
	}
	transport := &http.Transport{}
	if config.TLSConfig != nil {
		transport.TLSClientConfig = config.TLSConfig
	} else {
		transport.TLSClientConfig = &tls.Config{}
	}
	if config.Insecure {
		transport.TLSClientConfig.InsecureSkipVerify = true
	}
	if len(config.CAData) != 0 {
		if transport.TLSClientConfig.RootCAs == nil {
			transport.TLSClientConfig.RootCAs = x509.NewCertPool()
		}
		transport.TLSClientConfig.RootCAs.AppendCertsFromPEM(config.CAData)
	}
	if transport.TLSClientConfig.InsecureSkipVerify && transport.TLSClientConfig.RootCAs != nil {
		return nil, errors.New("Cannot specify root CAs and to skip TLS verification")
	}
	httpClient.Transport = transport

	c := &client{
		Name:                config.Name,
		URL:                 strings.TrimRight(config.URL, "/"),
		APIVersion:          config.APIVersion,
		EnableAlphaFeatures: config.EnableAlphaFeatures,
		Verbose:             config.Verbose,
		httpClient:          httpClient,
	}
	c.doRequestFunc = c.doRequest

	if config.AuthConfig != nil {
		if config.AuthConfig.BasicAuthConfig == nil && config.AuthConfig.BearerConfig == nil {
			return nil, errors.New("Non-nil AuthConfig cannot be empty")
		}
		if config.AuthConfig.BasicAuthConfig != nil && config.AuthConfig.BearerConfig != nil {
			return nil, errors.New("Only one AuthConfig implementation must be set at a time")
		}

		c.AuthConfig = config.AuthConfig
	}

	return c, nil
}

var _ CreateFunc = NewClient

type doRequestFunc func(request *http.Request) (*http.Response, error)

// client provides a functional implementation of the Client interface.
type client struct {
	Name                string
	URL                 string
	APIVersion          APIVersion
	AuthConfig          *AuthConfig
	EnableAlphaFeatures bool
	Verbose             bool

	httpClient    *http.Client
	doRequestFunc doRequestFunc
}

var _ Client = &client{}

// This file contains shared methods used by each interface method of the
// Client interface.  Individual interface methods are in the following files:
//
// GetCatalog: get_catalog.go
// ProvisionInstance: provision_instance.go
// UpdateInstance: update_instance.go
// DeprovisionInstance: deprovision_instance.go
// PollLastOperation: poll_last_operation.go
// Bind: bind.go
// Unbind: unbind.go

const (
	contentType = "Content-Type"
	jsonType    = "application/json"
)

// prepareAndDo prepares a request for the given method, URL, and
// message body, and executes the request, returning an http.Response or an
// error.  Errors returned from this function represent http-layer errors and
// not errors in the Open Service Broker API.
func (c *client) prepareAndDo(method, URL string, params map[string]string, body interface{}, originatingIdentity *OriginatingIdentity) (*http.Response, error) {
	var bodyReader io.Reader

	if body != nil {
		bodyBytes, err := json.Marshal(body)
		if err != nil {
			return nil, err
		}

		bodyReader = bytes.NewReader(bodyBytes)
	}

	request, err := http.NewRequest(method, URL, bodyReader)
	if err != nil {
		return nil, err
	}

	request.Header.Set(APIVersionHeader, c.APIVersion.HeaderValue())
	if bodyReader != nil {
		request.Header.Set(contentType, jsonType)
	}

	if c.AuthConfig != nil {
		if c.AuthConfig.BasicAuthConfig != nil {
			basicAuth := c.AuthConfig.BasicAuthConfig
			request.SetBasicAuth(basicAuth.Username, basicAuth.Password)
		} else if c.AuthConfig.BearerConfig != nil {
			bearer := c.AuthConfig.BearerConfig
			request.Header.Set("Authorization", "Bearer "+bearer.Token)
		}
	}

	if c.APIVersion.AtLeast(Version2_13()) && originatingIdentity != nil {
		headerValue, err := buildOriginatingIdentityHeaderValue(originatingIdentity)
		if err != nil {
			return nil, err
		}
		request.Header.Set(OriginatingIdentityHeader, headerValue)
	}

	if params != nil {
		q := request.URL.Query()
		for k, v := range params {
			q.Set(k, v)
		}
		request.URL.RawQuery = q.Encode()
	}

	if c.Verbose {
		glog.Infof("broker %q: doing request to %q", c.Name, URL)
	}

	return c.doRequestFunc(request)
}

func (c *client) doRequest(request *http.Request) (*http.Response, error) {
	return c.httpClient.Do(request)
}

// unmarshalResponse unmartials the response body of the given response into
// the given object or returns an error.
func (c *client) unmarshalResponse(response *http.Response, obj interface{}) error {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	if c.Verbose {
		glog.Infof("broker %q: response body: %v, type: %T", c.Name, string(body), obj)
	}

	err = json.Unmarshal(body, obj)
	if err != nil {
		return err
	}

	return nil
}

// handleFailureResponse returns an HTTPStatusCodeError for the given
// response.
func (c *client) handleFailureResponse(response *http.Response) error {
	glog.Info("handling failure responses")

	httpErr := HTTPStatusCodeError{
		StatusCode: response.StatusCode,
	}

	brokerResponse := make(map[string]interface{})
	if err := c.unmarshalResponse(response, &brokerResponse); err != nil {
		httpErr.ResponseError = err
		return httpErr
	}

	if errorMessage, ok := brokerResponse["error"].(string); ok {
		httpErr.ErrorMessage = &errorMessage
	}

	if description, ok := brokerResponse["description"].(string); ok {
		httpErr.Description = &description
	}

	return httpErr
}

func buildOriginatingIdentityHeaderValue(i *OriginatingIdentity) (string, error) {
	if i == nil {
		return "", nil
	}
	if i.Platform == "" {
		return "", errors.New("originating identity platform must not be empty")
	}
	if i.Value == "" {
		return "", errors.New("originating identity value must not be empty")
	}
	if err := isValidJSON(i.Value); err != nil {
		return "", fmt.Errorf("originating identity value must be valid JSON: %v", err)
	}
	encodedValue := base64.StdEncoding.EncodeToString([]byte(i.Value))
	headerValue := fmt.Sprintf("%v %v", i.Platform, encodedValue)
	return headerValue, nil
}

func isValidJSON(s string) error {
	var js json.RawMessage
	return json.Unmarshal([]byte(s), &js)
}

// validateAlphaAPIMethodsAllowed returns an error if alpha API methods are not
// allowed for this client.
func (c *client) validateAlphaAPIMethodsAllowed() error {
	if !c.EnableAlphaFeatures {
		return AlphaAPIMethodsNotAllowedError{
			reason: fmt.Sprintf("alpha features must be enabled"),
		}
	}

	if !c.APIVersion.AtLeast(LatestAPIVersion()) {
		return AlphaAPIMethodsNotAllowedError{
			reason: fmt.Sprintf(
				"must have latest API Version. Current: %s, Expected: %s",
				c.APIVersion.label,
				LatestAPIVersion().label,
			),
		}
	}

	return nil
}

// drainReader reads and discards the remaining data in reader (for example
// response body data) For HTTP this ensures that the http connection
// could be reused for another request if the keepalive is enabled.
// see https://gist.github.com/mholt/eba0f2cc96658be0f717#gistcomment-2605879
// Not certain this is really needed here for the Broker vs a http server
// but seems safe and worth including at this point
func drainReader(reader io.Reader) error {
	if reader == nil {
		return nil
	}
	_, drainError := io.Copy(ioutil.Discard, io.LimitReader(reader, 4096))
	return drainError
}

// internal message body types

type asyncSuccessResponseBody struct {
	Operation *string `json:"operation"`
}

type failureResponseBody struct {
	Err         *string `json:"error,omitempty"`
	Description *string `json:"description,omitempty"`
}
<commit_msg>use defaults from DefaultTransport for our custom transport (ie timeouts) (#133)<commit_after>package v2

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/golang/glog"
)

const (
	// APIVersionHeader is the header value associated with the version of the Open
	// Service Broker API version.
	APIVersionHeader = "X-Broker-API-Version"
	// OriginatingIdentityHeader is the header associated with originating
	// identity.
	OriginatingIdentityHeader = "X-Broker-API-Originating-Identity"

	catalogURL                 = "%s/v2/catalog"
	serviceInstanceURLFmt      = "%s/v2/service_instances/%s"
	lastOperationURLFmt        = "%s/v2/service_instances/%s/last_operation"
	bindingLastOperationURLFmt = "%s/v2/service_instances/%s/service_bindings/%s/last_operation"
	bindingURLFmt              = "%s/v2/service_instances/%s/service_bindings/%s"
)

// NewClient is a CreateFunc for creating a new functional Client and
// implements the CreateFunc interface.
func NewClient(config *ClientConfiguration) (Client, error) {
	httpClient := &http.Client{
		Timeout: time.Duration(config.TimeoutSeconds) * time.Second,
	}

	// use default values lifted from DefaultTransport
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
			DualStack: true,
		}).DialContext,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}

	if config.TLSConfig != nil {
		transport.TLSClientConfig = config.TLSConfig
	} else {
		transport.TLSClientConfig = &tls.Config{}
	}
	if config.Insecure {
		transport.TLSClientConfig.InsecureSkipVerify = true
	}
	if len(config.CAData) != 0 {
		if transport.TLSClientConfig.RootCAs == nil {
			transport.TLSClientConfig.RootCAs = x509.NewCertPool()
		}
		transport.TLSClientConfig.RootCAs.AppendCertsFromPEM(config.CAData)
	}
	if transport.TLSClientConfig.InsecureSkipVerify && transport.TLSClientConfig.RootCAs != nil {
		return nil, errors.New("Cannot specify root CAs and to skip TLS verification")
	}
	httpClient.Transport = transport

	c := &client{
		Name:                config.Name,
		URL:                 strings.TrimRight(config.URL, "/"),
		APIVersion:          config.APIVersion,
		EnableAlphaFeatures: config.EnableAlphaFeatures,
		Verbose:             config.Verbose,
		httpClient:          httpClient,
	}
	c.doRequestFunc = c.doRequest

	if config.AuthConfig != nil {
		if config.AuthConfig.BasicAuthConfig == nil && config.AuthConfig.BearerConfig == nil {
			return nil, errors.New("Non-nil AuthConfig cannot be empty")
		}
		if config.AuthConfig.BasicAuthConfig != nil && config.AuthConfig.BearerConfig != nil {
			return nil, errors.New("Only one AuthConfig implementation must be set at a time")
		}

		c.AuthConfig = config.AuthConfig
	}

	return c, nil
}

var _ CreateFunc = NewClient

type doRequestFunc func(request *http.Request) (*http.Response, error)

// client provides a functional implementation of the Client interface.
type client struct {
	Name                string
	URL                 string
	APIVersion          APIVersion
	AuthConfig          *AuthConfig
	EnableAlphaFeatures bool
	Verbose             bool

	httpClient    *http.Client
	doRequestFunc doRequestFunc
}

var _ Client = &client{}

// This file contains shared methods used by each interface method of the
// Client interface.  Individual interface methods are in the following files:
//
// GetCatalog: get_catalog.go
// ProvisionInstance: provision_instance.go
// UpdateInstance: update_instance.go
// DeprovisionInstance: deprovision_instance.go
// PollLastOperation: poll_last_operation.go
// Bind: bind.go
// Unbind: unbind.go

const (
	contentType = "Content-Type"
	jsonType    = "application/json"
)

// prepareAndDo prepares a request for the given method, URL, and
// message body, and executes the request, returning an http.Response or an
// error.  Errors returned from this function represent http-layer errors and
// not errors in the Open Service Broker API.
func (c *client) prepareAndDo(method, URL string, params map[string]string, body interface{}, originatingIdentity *OriginatingIdentity) (*http.Response, error) {
	var bodyReader io.Reader

	if body != nil {
		bodyBytes, err := json.Marshal(body)
		if err != nil {
			return nil, err
		}

		bodyReader = bytes.NewReader(bodyBytes)
	}

	request, err := http.NewRequest(method, URL, bodyReader)
	if err != nil {
		return nil, err
	}

	request.Header.Set(APIVersionHeader, c.APIVersion.HeaderValue())
	if bodyReader != nil {
		request.Header.Set(contentType, jsonType)
	}

	if c.AuthConfig != nil {
		if c.AuthConfig.BasicAuthConfig != nil {
			basicAuth := c.AuthConfig.BasicAuthConfig
			request.SetBasicAuth(basicAuth.Username, basicAuth.Password)
		} else if c.AuthConfig.BearerConfig != nil {
			bearer := c.AuthConfig.BearerConfig
			request.Header.Set("Authorization", "Bearer "+bearer.Token)
		}
	}

	if c.APIVersion.AtLeast(Version2_13()) && originatingIdentity != nil {
		headerValue, err := buildOriginatingIdentityHeaderValue(originatingIdentity)
		if err != nil {
			return nil, err
		}
		request.Header.Set(OriginatingIdentityHeader, headerValue)
	}

	if params != nil {
		q := request.URL.Query()
		for k, v := range params {
			q.Set(k, v)
		}
		request.URL.RawQuery = q.Encode()
	}

	if c.Verbose {
		glog.Infof("broker %q: doing request to %q", c.Name, URL)
	}

	return c.doRequestFunc(request)
}

func (c *client) doRequest(request *http.Request) (*http.Response, error) {
	return c.httpClient.Do(request)
}

// unmarshalResponse unmartials the response body of the given response into
// the given object or returns an error.
func (c *client) unmarshalResponse(response *http.Response, obj interface{}) error {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	if c.Verbose {
		glog.Infof("broker %q: response body: %v, type: %T", c.Name, string(body), obj)
	}

	err = json.Unmarshal(body, obj)
	if err != nil {
		return err
	}

	return nil
}

// handleFailureResponse returns an HTTPStatusCodeError for the given
// response.
func (c *client) handleFailureResponse(response *http.Response) error {
	glog.Info("handling failure responses")

	httpErr := HTTPStatusCodeError{
		StatusCode: response.StatusCode,
	}

	brokerResponse := make(map[string]interface{})
	if err := c.unmarshalResponse(response, &brokerResponse); err != nil {
		httpErr.ResponseError = err
		return httpErr
	}

	if errorMessage, ok := brokerResponse["error"].(string); ok {
		httpErr.ErrorMessage = &errorMessage
	}

	if description, ok := brokerResponse["description"].(string); ok {
		httpErr.Description = &description
	}

	return httpErr
}

func buildOriginatingIdentityHeaderValue(i *OriginatingIdentity) (string, error) {
	if i == nil {
		return "", nil
	}
	if i.Platform == "" {
		return "", errors.New("originating identity platform must not be empty")
	}
	if i.Value == "" {
		return "", errors.New("originating identity value must not be empty")
	}
	if err := isValidJSON(i.Value); err != nil {
		return "", fmt.Errorf("originating identity value must be valid JSON: %v", err)
	}
	encodedValue := base64.StdEncoding.EncodeToString([]byte(i.Value))
	headerValue := fmt.Sprintf("%v %v", i.Platform, encodedValue)
	return headerValue, nil
}

func isValidJSON(s string) error {
	var js json.RawMessage
	return json.Unmarshal([]byte(s), &js)
}

// validateAlphaAPIMethodsAllowed returns an error if alpha API methods are not
// allowed for this client.
func (c *client) validateAlphaAPIMethodsAllowed() error {
	if !c.EnableAlphaFeatures {
		return AlphaAPIMethodsNotAllowedError{
			reason: fmt.Sprintf("alpha features must be enabled"),
		}
	}

	if !c.APIVersion.AtLeast(LatestAPIVersion()) {
		return AlphaAPIMethodsNotAllowedError{
			reason: fmt.Sprintf(
				"must have latest API Version. Current: %s, Expected: %s",
				c.APIVersion.label,
				LatestAPIVersion().label,
			),
		}
	}

	return nil
}

// drainReader reads and discards the remaining data in reader (for example
// response body data) For HTTP this ensures that the http connection
// could be reused for another request if the keepalive is enabled.
// see https://gist.github.com/mholt/eba0f2cc96658be0f717#gistcomment-2605879
// Not certain this is really needed here for the Broker vs a http server
// but seems safe and worth including at this point
func drainReader(reader io.Reader) error {
	if reader == nil {
		return nil
	}
	_, drainError := io.Copy(ioutil.Discard, io.LimitReader(reader, 4096))
	return drainError
}

// internal message body types

type asyncSuccessResponseBody struct {
	Operation *string `json:"operation"`
}

type failureResponseBody struct {
	Err         *string `json:"error,omitempty"`
	Description *string `json:"description,omitempty"`
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"log"
	"os"
	"sort"

	"github.com/golang/protobuf/proto"
	"github.com/xeipuuv/gojsonschema"
)

var errInvalidPayload = errors.New("invalid JSON payload")
var errNoSuchRef = errors.New("no such $ref")

type sid = uint32
type schemaJSON = map[string]interface{}
type schemasJSON = map[string]schemaJSON

type validator struct {
	Spec *SpecIR
	Refs map[string]sid
	Refd *gojsonschema.SchemaLoader
	Anon map[sid]schemaJSON
}

func newValidator(capaEndpoints, capaSchemas int) *validator {
	return &validator{
		Refs: make(map[string]sid, capaSchemas),
		Anon: make(map[sid]schemaJSON, capaEndpoints),
		Spec: &SpecIR{
			Endpoints: make([]*Endpoint, 0, capaEndpoints),
			Schemas:   &Schemas{Json: make(map[sid]*RefOrSchemaJSON, capaSchemas)},
		},
		Refd: gojsonschema.NewSchemaLoader(),
	}
}

func (vald *validator) newSID() sid {
	return sid(1 + len(vald.Spec.Schemas.Json))
}

func (vald *validator) seed(base string, schemas schemasJSON, skipped ...schemasJSON) (err error) {
	anyQueued := len(skipped) == 1 && len(skipped[0]) != 0
	i, names := 0, make([]string, len(schemas))
	for name := range schemas {
		names[i] = name
		i++
	}
	if anyQueued {
		for name := range skipped[0] {
			names[i] = name
			i++
		}
	}
	sort.Strings(names)

	for j := 0; j != i; j++ {
		name := names[j]
		absRef := base + name
		schema, ok := schemas[name]
		if !ok && anyQueued {
			schema = skipped[0][name]
		}
		log.Printf("[DBG] seeding schema '%s'", absRef)

		sl := gojsonschema.NewGoLoader(schema)
		if err = vald.Refd.AddSchema(absRef, sl); err != nil {
			log.Println("[ERR]", err)
			return
		}

		if sid := vald.ensureMapped("", schema); sid != 0 {
			vald.Refs[absRef] = sid
			schemaPtr := &SchemaPtr{Ref: absRef, SID: sid}
			vald.Spec.Schemas.Json[vald.newSID()] = &RefOrSchemaJSON{
				PtrOrSchema: &RefOrSchemaJSON_Ptr{schemaPtr},
			}
		} else {
			skipped[0][name] = schema
			anyQueued = true
		}
	}
	if anyQueued {
		return vald.seed(base, skipped[0])
	}
	return
}

func (vald *validator) ensureMapped(ref string, goSchema schemaJSON) sid {
	if ref == "" {
		schema := vald.fromGo(goSchema)
		for SID, schemaPtr := range vald.Spec.Schemas.Json {
			if s := schemaPtr.GetSchema(); s != nil && proto.Equal(&schema, s) {
				return SID
			}
		}
		SID := vald.newSID()
		vald.Spec.Schemas.Json[SID] = &RefOrSchemaJSON{
			PtrOrSchema: &RefOrSchemaJSON_Schema{&schema},
		}
		return SID
	}

	mappedSID, ok := vald.Refs[ref]
	if !ok {
		return 0
	}
	schemaPtr := &SchemaPtr{Ref: ref, SID: mappedSID}
	SID := vald.newSID()
	vald.Spec.Schemas.Json[SID] = &RefOrSchemaJSON{
		PtrOrSchema: &RefOrSchemaJSON_Ptr{schemaPtr},
	}
	return SID
}

func (vald *validator) fromGo(s schemaJSON) (schema Schema_JSON) {
	// "enum"
	if v, ok := s["enum"]; ok {
		enum := v.([]interface{})
		schema.Enum = make([]*ValueJSON, len(enum))
		for i, vv := range enum {
			schema.Enum[i] = enumFromGo(vv)
		}
	}

	// "type"
	if v, ok := s["type"]; ok {
		types := v.([]string)
		schema.Types = make([]Schema_JSON_Type, len(types))
		for i, vv := range types {
			schema.Types[i] = Schema_JSON_Type(Schema_JSON_Type_value[vv])
		}
	}

	// "format"
	if v, ok := s["format"]; ok {
		schema.Format = formatFromGo(v.(string))
	}
	// "minLength"
	if v, ok := s["minLength"]; ok {
		schema.MinLength = v.(uint64)
	}
	// "maxLength"
	if v, ok := s["maxLength"]; ok {
		schema.MaxLength = v.(uint64)
		schema.HasMaxLength = true
	}
	// "pattern"
	if v, ok := s["pattern"]; ok {
		schema.Pattern = v.(string)
	}

	// "minimum"
	if v, ok := s["minimum"]; ok {
		schema.Minimum = v.(float64)
		schema.HasMinimum = true
	}
	// "maximum"
	if v, ok := s["maximum"]; ok {
		schema.Maximum = v.(float64)
		schema.HasMaximum = true
	}
	// "exclusiveMinimum", "exclusiveMaximum"
	if v, ok := s["exclusiveMinimum"]; ok {
		schema.ExclusiveMinimum = v.(bool)
	}
	if v, ok := s["exclusiveMaximum"]; ok {
		schema.ExclusiveMaximum = v.(bool)
	}
	// "multipleOf"
	if v, ok := s["multipleOf"]; ok {
		schema.TranslatedMultipleOf = v.(float64) - 1.0
	}

	// "uniqueItems"
	if v, ok := s["uniqueItems"]; ok {
		schema.UniqueItems = v.(bool)
	}
	// "minItems"
	if v, ok := s["minItems"]; ok {
		schema.MinItems = v.(uint64)
	}
	// "maxItems"
	if v, ok := s["maxItems"]; ok {
		schema.MaxItems = v.(uint64)
		schema.HasMaxItems = true
	}
	// "items"
	if v, ok := s["items"]; ok {
		items := v.([]schemaJSON)
		schema.Items = make([]sid, len(items))
		for i, ss := range items {
			if v, ok := ss["$ref"]; ok {
				schema.Items[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.Items[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "minProperties"
	if v, ok := s["minProperties"]; ok {
		schema.MinProperties = v.(uint64)
	}
	// "maxProperties"
	if v, ok := s["maxProperties"]; ok {
		schema.MaxProperties = v.(uint64)
		schema.HasMaxProperties = true
	}
	// "required"
	if v, ok := s["required"]; ok {
		schema.Required = v.([]string)
	}
	// "properties"
	if v, ok := s["properties"]; ok {
		properties := v.(schemasJSON)
		if count := len(properties); count != 0 {
			schema.Properties = make(map[string]sid, count)
			i, props := 0, make([]string, count)
			for propName := range properties {
				props[i] = propName
				i++
			}
			sort.Strings(props)

			for j := 0; j != i; j++ {
				propName := props[j]
				ss := properties[propName]
				if v, ok := ss["$ref"]; ok {
					schema.Properties[propName] = vald.ensureMapped(v.(string), ss)
				} else {
					schema.Properties[propName] = vald.ensureMapped("", ss)
				}
			}
		}
	}
	//FIXME: "additionalProperties"

	// "allOf"
	if v, ok := s["allOf"]; ok {
		of := v.([]schemaJSON)
		schema.AllOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.AllOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.AllOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "anyOf"
	if v, ok := s["anyOf"]; ok {
		of := v.([]schemaJSON)
		schema.AnyOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.AnyOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.AnyOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "oneOf"
	if v, ok := s["oneOf"]; ok {
		of := v.([]schemaJSON)
		schema.OneOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.OneOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.OneOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "not"
	if v, ok := s["not"]; ok {
		ss := v.(schemaJSON)
		if vv, ok := ss["$ref"]; ok {
			schema.Not = vald.ensureMapped(vv.(string), ss)
		} else {
			schema.Not = vald.ensureMapped("", ss)
		}
	}

	return
}

func formatFromGo(format string) Schema_JSON_Format {
	switch format {
	case "date-time":
		return Schema_JSON_date_time
	case "uriref", "uri-reference":
		return Schema_JSON_uri_reference
	default:
		v, ok := Schema_JSON_Format_value[format]
		if ok {
			return Schema_JSON_Format(v)
		}
		return Schema_JSON_NONE
	}
}

func enumFromGo(value interface{}) *ValueJSON {
	if value == nil {
		return &ValueJSON{Value: &ValueJSON_IsNull{true}}
	}
	switch value.(type) {
	case bool:
		return &ValueJSON{Value: &ValueJSON_Boolean{value.(bool)}}
	case float64:
		return &ValueJSON{Value: &ValueJSON_Number{value.(float64)}}
	case string:
		return &ValueJSON{Value: &ValueJSON_Text{value.(string)}}
	case []interface{}:
		val := value.([]interface{})
		vs := make([]*ValueJSON, len(val))
		for i, v := range val {
			vs[i] = enumFromGo(v)
		}
		return &ValueJSON{Value: &ValueJSON_Array{&ArrayJSON{Values: vs}}}
	case map[string]interface{}:
		val := value.(map[string]interface{})
		vs := make(map[string]*ValueJSON, len(val))
		for n, v := range val {
			vs[n] = enumFromGo(v)
		}
		return &ValueJSON{Value: &ValueJSON_Object{&ObjectJSON{Values: vs}}}
	default:
		panic("unreachable")
	}
}

// //FIXME: build schemaJSON from SID & SIDs then compile against schemaLoader
// func (vald *validator) validationErrors(spec *SpecIR, SID sid) (errs []error) {
// 	return
// }

func (vald *validator) validateAgainstSchema(absRef string) (err error) {
	if _, ok := vald.Refs[absRef]; !ok {
		err = errNoSuchRef
		return
	}

	var value interface{}
	if err = json.NewDecoder(os.Stdin).Decode(&value); err != nil {
		log.Println("[ERR]", err)
		return
	}

	// NOTE Compile errs on bad refs only, MUST do this step in `lint`
	schema, err := vald.Refd.Compile(
		gojsonschema.NewGoLoader(schemaJSON{"$ref": absRef}))
	if err != nil {
		log.Println("[ERR]", err)
		return
	}

	res, err := schema.Validate(gojsonschema.NewGoLoader(value))
	if err != nil {
		log.Println("[ERR]", err)
		return
	}

	errs := res.Errors()
	for _, e := range errs {
		// ResultError interface
		colorERR.Println(e)
	}
	if len(errs) > 0 {
		err = errInvalidPayload
	}
	return
}
<commit_msg>reuse processed schema refs<commit_after>package main

import (
	"encoding/json"
	"errors"
	"log"
	"os"
	"sort"

	"github.com/golang/protobuf/proto"
	"github.com/xeipuuv/gojsonschema"
)

var errInvalidPayload = errors.New("invalid JSON payload")
var errNoSuchRef = errors.New("no such $ref")

type sid = uint32
type schemaJSON = map[string]interface{}
type schemasJSON = map[string]schemaJSON

type validator struct {
	Spec *SpecIR
	Refs map[string]sid
	Refd *gojsonschema.SchemaLoader
	Anon map[sid]schemaJSON
}

func newValidator(capaEndpoints, capaSchemas int) *validator {
	return &validator{
		Refs: make(map[string]sid, capaSchemas),
		Anon: make(map[sid]schemaJSON, capaEndpoints),
		Spec: &SpecIR{
			Endpoints: make([]*Endpoint, 0, capaEndpoints),
			Schemas:   &Schemas{Json: make(map[sid]*RefOrSchemaJSON, capaSchemas)},
		},
		Refd: gojsonschema.NewSchemaLoader(),
	}
}

func (vald *validator) newSID() sid {
	return sid(1 + len(vald.Spec.Schemas.Json))
}

func (vald *validator) seed(base string, schemas schemasJSON, skipped ...schemasJSON) (err error) {
	anyQueued := len(skipped) == 1 && len(skipped[0]) != 0
	i, names := 0, make([]string, len(schemas))
	for name := range schemas {
		names[i] = name
		i++
	}
	if anyQueued {
		for name := range skipped[0] {
			names[i] = name
			i++
		}
	}
	sort.Strings(names)

	for j := 0; j != i; j++ {
		name := names[j]
		absRef := base + name
		schema, ok := schemas[name]
		if !ok && anyQueued {
			schema = skipped[0][name]
		}
		log.Printf("[DBG] seeding schema '%s'", absRef)

		sl := gojsonschema.NewGoLoader(schema)
		if err = vald.Refd.AddSchema(absRef, sl); err != nil {
			log.Println("[ERR]", err)
			return
		}

		if sid := vald.ensureMapped("", schema); sid != 0 {
			vald.Refs[absRef] = sid
			schemaPtr := &SchemaPtr{Ref: absRef, SID: sid}
			vald.Spec.Schemas.Json[vald.newSID()] = &RefOrSchemaJSON{
				PtrOrSchema: &RefOrSchemaJSON_Ptr{schemaPtr},
			}
		} else {
			skipped[0][name] = schema
			anyQueued = true
		}
	}
	if anyQueued {
		return vald.seed(base, skipped[0])
	}
	return
}

func (vald *validator) ensureMapped(ref string, goSchema schemaJSON) sid {
	if ref == "" {
		schema := vald.fromGo(goSchema)
		for SID, schemaPtr := range vald.Spec.Schemas.Json {
			if s := schemaPtr.GetSchema(); s != nil && proto.Equal(&schema, s) {
				return SID
			}
		}
		SID := vald.newSID()
		vald.Spec.Schemas.Json[SID] = &RefOrSchemaJSON{
			PtrOrSchema: &RefOrSchemaJSON_Schema{&schema},
		}
		return SID
	}

	mappedSID, ok := vald.Refs[ref]
	if !ok {
		return 0
	}
	schemaPtr := &SchemaPtr{Ref: ref, SID: mappedSID}
	SID := sid(0)
	for refSID, schemaPtr := range vald.Spec.Schemas.Json {
		if ptr := schemaPtr.GetPtr(); ptr != nil && ptr.GetRef() == ref {
			SID = refSID
		}
	}
	if SID == 0 {
		panic(`impossible`)
	}
	vald.Spec.Schemas.Json[SID] = &RefOrSchemaJSON{
		PtrOrSchema: &RefOrSchemaJSON_Ptr{schemaPtr},
	}
	return SID
}

func (vald *validator) fromGo(s schemaJSON) (schema Schema_JSON) {
	// "enum"
	if v, ok := s["enum"]; ok {
		enum := v.([]interface{})
		schema.Enum = make([]*ValueJSON, len(enum))
		for i, vv := range enum {
			schema.Enum[i] = enumFromGo(vv)
		}
	}

	// "type"
	if v, ok := s["type"]; ok {
		types := v.([]string)
		schema.Types = make([]Schema_JSON_Type, len(types))
		for i, vv := range types {
			schema.Types[i] = Schema_JSON_Type(Schema_JSON_Type_value[vv])
		}
	}

	// "format"
	if v, ok := s["format"]; ok {
		schema.Format = formatFromGo(v.(string))
	}
	// "minLength"
	if v, ok := s["minLength"]; ok {
		schema.MinLength = v.(uint64)
	}
	// "maxLength"
	if v, ok := s["maxLength"]; ok {
		schema.MaxLength = v.(uint64)
		schema.HasMaxLength = true
	}
	// "pattern"
	if v, ok := s["pattern"]; ok {
		schema.Pattern = v.(string)
	}

	// "minimum"
	if v, ok := s["minimum"]; ok {
		schema.Minimum = v.(float64)
		schema.HasMinimum = true
	}
	// "maximum"
	if v, ok := s["maximum"]; ok {
		schema.Maximum = v.(float64)
		schema.HasMaximum = true
	}
	// "exclusiveMinimum", "exclusiveMaximum"
	if v, ok := s["exclusiveMinimum"]; ok {
		schema.ExclusiveMinimum = v.(bool)
	}
	if v, ok := s["exclusiveMaximum"]; ok {
		schema.ExclusiveMaximum = v.(bool)
	}
	// "multipleOf"
	if v, ok := s["multipleOf"]; ok {
		schema.TranslatedMultipleOf = v.(float64) - 1.0
	}

	// "uniqueItems"
	if v, ok := s["uniqueItems"]; ok {
		schema.UniqueItems = v.(bool)
	}
	// "minItems"
	if v, ok := s["minItems"]; ok {
		schema.MinItems = v.(uint64)
	}
	// "maxItems"
	if v, ok := s["maxItems"]; ok {
		schema.MaxItems = v.(uint64)
		schema.HasMaxItems = true
	}
	// "items"
	if v, ok := s["items"]; ok {
		items := v.([]schemaJSON)
		schema.Items = make([]sid, len(items))
		for i, ss := range items {
			if v, ok := ss["$ref"]; ok {
				schema.Items[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.Items[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "minProperties"
	if v, ok := s["minProperties"]; ok {
		schema.MinProperties = v.(uint64)
	}
	// "maxProperties"
	if v, ok := s["maxProperties"]; ok {
		schema.MaxProperties = v.(uint64)
		schema.HasMaxProperties = true
	}
	// "required"
	if v, ok := s["required"]; ok {
		schema.Required = v.([]string)
	}
	// "properties"
	if v, ok := s["properties"]; ok {
		properties := v.(schemasJSON)
		if count := len(properties); count != 0 {
			schema.Properties = make(map[string]sid, count)
			i, props := 0, make([]string, count)
			for propName := range properties {
				props[i] = propName
				i++
			}
			sort.Strings(props)

			for j := 0; j != i; j++ {
				propName := props[j]
				ss := properties[propName]
				if v, ok := ss["$ref"]; ok {
					schema.Properties[propName] = vald.ensureMapped(v.(string), ss)
				} else {
					schema.Properties[propName] = vald.ensureMapped("", ss)
				}
			}
		}
	}
	//FIXME: "additionalProperties"

	// "allOf"
	if v, ok := s["allOf"]; ok {
		of := v.([]schemaJSON)
		schema.AllOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.AllOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.AllOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "anyOf"
	if v, ok := s["anyOf"]; ok {
		of := v.([]schemaJSON)
		schema.AnyOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.AnyOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.AnyOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "oneOf"
	if v, ok := s["oneOf"]; ok {
		of := v.([]schemaJSON)
		schema.OneOf = make([]sid, len(of))
		for i, ss := range of {
			if v, ok := ss["$ref"]; ok {
				schema.OneOf[i] = vald.ensureMapped(v.(string), ss)
			} else {
				schema.OneOf[i] = vald.ensureMapped("", ss)
			}
		}
	}

	// "not"
	if v, ok := s["not"]; ok {
		ss := v.(schemaJSON)
		if vv, ok := ss["$ref"]; ok {
			schema.Not = vald.ensureMapped(vv.(string), ss)
		} else {
			schema.Not = vald.ensureMapped("", ss)
		}
	}

	return
}

func formatFromGo(format string) Schema_JSON_Format {
	switch format {
	case "date-time":
		return Schema_JSON_date_time
	case "uriref", "uri-reference":
		return Schema_JSON_uri_reference
	default:
		v, ok := Schema_JSON_Format_value[format]
		if ok {
			return Schema_JSON_Format(v)
		}
		return Schema_JSON_NONE
	}
}

func enumFromGo(value interface{}) *ValueJSON {
	if value == nil {
		return &ValueJSON{Value: &ValueJSON_IsNull{true}}
	}
	switch value.(type) {
	case bool:
		return &ValueJSON{Value: &ValueJSON_Boolean{value.(bool)}}
	case float64:
		return &ValueJSON{Value: &ValueJSON_Number{value.(float64)}}
	case string:
		return &ValueJSON{Value: &ValueJSON_Text{value.(string)}}
	case []interface{}:
		val := value.([]interface{})
		vs := make([]*ValueJSON, len(val))
		for i, v := range val {
			vs[i] = enumFromGo(v)
		}
		return &ValueJSON{Value: &ValueJSON_Array{&ArrayJSON{Values: vs}}}
	case map[string]interface{}:
		val := value.(map[string]interface{})
		vs := make(map[string]*ValueJSON, len(val))
		for n, v := range val {
			vs[n] = enumFromGo(v)
		}
		return &ValueJSON{Value: &ValueJSON_Object{&ObjectJSON{Values: vs}}}
	default:
		panic("unreachable")
	}
}

// //FIXME: build schemaJSON from SID & SIDs then compile against schemaLoader
// func (vald *validator) validationErrors(spec *SpecIR, SID sid) (errs []error) {
// 	return
// }

func (vald *validator) validateAgainstSchema(absRef string) (err error) {
	if _, ok := vald.Refs[absRef]; !ok {
		err = errNoSuchRef
		return
	}

	var value interface{}
	if err = json.NewDecoder(os.Stdin).Decode(&value); err != nil {
		log.Println("[ERR]", err)
		return
	}

	// NOTE Compile errs on bad refs only, MUST do this step in `lint`
	schema, err := vald.Refd.Compile(
		gojsonschema.NewGoLoader(schemaJSON{"$ref": absRef}))
	if err != nil {
		log.Println("[ERR]", err)
		return
	}

	res, err := schema.Validate(gojsonschema.NewGoLoader(value))
	if err != nil {
		log.Println("[ERR]", err)
		return
	}

	errs := res.Errors()
	for _, e := range errs {
		// ResultError interface
		colorERR.Println(e)
	}
	if len(errs) > 0 {
		err = errInvalidPayload
	}
	return
}
<|endoftext|>


<commit_before>package systray

/*
#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit

#include "systray.h"
*/
import "C"

import (
	"unsafe"
)

// SetTemplateIcon sets the systray icon as a template icon (on Mac), falling back
// to a regular icon on other platforms.
// templateIconBytes and regularIconBytes should be the content of .ico for windows and
// .ico/.jpg/.png for other platforms.
func SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0]))
	C.setIcon(cstr, (C.int)(len(templateIconBytes)), true)
}

// SetIcon sets the icon of a menu item. Only works on macOS and Windows.
// iconBytes should be the content of .ico/.jpg/.png
func (item *MenuItem) SetIcon(iconBytes []byte) {
	SetTemplateIcon(iconBytes, iconBytes)
}

// SetTemplateIcon sets the icon of a menu item as a template icon (on macOS). On Windows, it
// falls back to the regular icon bytes and on Linux it does nothing.
// templateIconBytes and regularIconBytes should be the content of .ico for windows and
// .ico/.jpg/.png for other platforms.
func (item *MenuItem) SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0]))
	C.setMenuItemIcon(cstr, (C.int)(len(templateIconBytes)), C.int(item.id), true)
}<commit_msg>Fix bug on darwin of setting icon for menu<commit_after>package systray

/*
#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit

#include "systray.h"
*/
import "C"

import (
	"unsafe"
)

// SetTemplateIcon sets the systray icon as a template icon (on Mac), falling back
// to a regular icon on other platforms.
// templateIconBytes and regularIconBytes should be the content of .ico for windows and
// .ico/.jpg/.png for other platforms.
func SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0]))
	C.setIcon(cstr, (C.int)(len(templateIconBytes)), true)
}

// SetIcon sets the icon of a menu item. Only works on macOS and Windows.
// iconBytes should be the content of .ico/.jpg/.png
func (item *MenuItem) SetIcon(iconBytes []byte) {
	item.SetTemplateIcon(iconBytes, iconBytes)
}

// SetTemplateIcon sets the icon of a menu item as a template icon (on macOS). On Windows, it
// falls back to the regular icon bytes and on Linux it does nothing.
// templateIconBytes and regularIconBytes should be the content of .ico for windows and
// .ico/.jpg/.png for other platforms.
func (item *MenuItem) SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0]))
	C.setMenuItemIcon(cstr, (C.int)(len(templateIconBytes)), C.int(item.id), true)
}
<|endoftext|>