<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package winfsnotify

import (
	"os"
	"testing"
	"time"
)

func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
	t.Logf(`expected: "%s": 0x%x`, name, mask)
	select {
	case event := <-eventstream:
		if event == nil {
			t.Fatal("nil event received")
		}
		t.Logf("received: %s", event)
		if event.Name != name || event.Mask != mask {
			t.Fatal("did not receive expected event")
		}
	case <-time.After(1 * time.Second):
		t.Fatal("timed out waiting for event")
	}
}

func TestNotifyEvents(t *testing.T) {
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher() failed: %s", err)
	}

	testDir := "TestNotifyEvents.testdirectory"
	testFile := testDir + "/TestNotifyEvents.testfile"
	testFile2 := testFile + ".new"
	const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED

	// Add a watch for testDir
	os.RemoveAll(testDir)
	if err = os.Mkdir(testDir, 0777); err != nil {
		t.Fatalf("Failed to create test directory: %s", err)
	}
	defer os.RemoveAll(testDir)
	err = watcher.AddWatch(testDir, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	// Receive errors on the error channel on a separate goroutine
	go func() {
		for err := range watcher.Error {
			t.Fatalf("error received: %s", err)
		}
	}()

	// Create a file
	file, err := os.Create(testFile)
	if err != nil {
		t.Fatalf("creating test file failed: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_CREATE)

	err = watcher.AddWatch(testFile, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	if _, err = file.WriteString("hello, world"); err != nil {
		t.Fatalf("failed to write to test file: %s", err)
	}
	if err = file.Close(); err != nil {
		t.Fatalf("failed to close test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MODIFY)
	expect(t, watcher.Event, testFile, FS_MODIFY)

	if err = os.Rename(testFile, testFile2); err != nil {
		t.Fatalf("failed to rename test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MOVED_FROM)
	expect(t, watcher.Event, testFile2, FS_MOVED_TO)
	expect(t, watcher.Event, testFile, FS_MOVE_SELF)

	if err = os.RemoveAll(testDir); err != nil {
		t.Fatalf("failed to remove test directory: %s", err)
	}
	expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
	expect(t, watcher.Event, testFile2, FS_IGNORED)
	expect(t, watcher.Event, testFile2, FS_DELETE)
	expect(t, watcher.Event, testDir, FS_DELETE_SELF)
	expect(t, watcher.Event, testDir, FS_IGNORED)

	t.Log("calling Close()")
	if err = watcher.Close(); err != nil {
		t.Fatalf("failed to close watcher: %s", err)
	}
}

func TestNotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	done := false
	go func() {
		watcher.Close()
		done = true
	}()

	time.Sleep(50 * time.Millisecond)
	if !done {
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	err := watcher.Watch("_test")
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<commit_msg>exp/winfsnotify: remove reference to _test Updates issue 2573.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package winfsnotify

import (
	"os"
	"testing"
	"time"
)

func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
	t.Logf(`expected: "%s": 0x%x`, name, mask)
	select {
	case event := <-eventstream:
		if event == nil {
			t.Fatal("nil event received")
		}
		t.Logf("received: %s", event)
		if event.Name != name || event.Mask != mask {
			t.Fatal("did not receive expected event")
		}
	case <-time.After(1 * time.Second):
		t.Fatal("timed out waiting for event")
	}
}

func TestNotifyEvents(t *testing.T) {
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher() failed: %s", err)
	}

	testDir := "TestNotifyEvents.testdirectory"
	testFile := testDir + "/TestNotifyEvents.testfile"
	testFile2 := testFile + ".new"
	const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED

	// Add a watch for testDir
	os.RemoveAll(testDir)
	if err = os.Mkdir(testDir, 0777); err != nil {
		t.Fatalf("Failed to create test directory: %s", err)
	}
	defer os.RemoveAll(testDir)
	err = watcher.AddWatch(testDir, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	// Receive errors on the error channel on a separate goroutine
	go func() {
		for err := range watcher.Error {
			t.Fatalf("error received: %s", err)
		}
	}()

	// Create a file
	file, err := os.Create(testFile)
	if err != nil {
		t.Fatalf("creating test file failed: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_CREATE)

	err = watcher.AddWatch(testFile, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	if _, err = file.WriteString("hello, world"); err != nil {
		t.Fatalf("failed to write to test file: %s", err)
	}
	if err = file.Close(); err != nil {
		t.Fatalf("failed to close test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MODIFY)
	expect(t, watcher.Event, testFile, FS_MODIFY)

	if err = os.Rename(testFile, testFile2); err != nil {
		t.Fatalf("failed to rename test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MOVED_FROM)
	expect(t, watcher.Event, testFile2, FS_MOVED_TO)
	expect(t, watcher.Event, testFile, FS_MOVE_SELF)

	if err = os.RemoveAll(testDir); err != nil {
		t.Fatalf("failed to remove test directory: %s", err)
	}
	expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
	expect(t, watcher.Event, testFile2, FS_IGNORED)
	expect(t, watcher.Event, testFile2, FS_DELETE)
	expect(t, watcher.Event, testDir, FS_DELETE_SELF)
	expect(t, watcher.Event, testDir, FS_IGNORED)

	t.Log("calling Close()")
	if err = watcher.Close(); err != nil {
		t.Fatalf("failed to close watcher: %s", err)
	}
}

func TestNotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	done := false
	go func() {
		watcher.Close()
		done = true
	}()

	time.Sleep(50 * time.Millisecond)
	if !done {
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	dir, err := ioutil.TempDir("", "wininotify")
	if err != nil {
		t.Fatalf("TempDir failed: %s", err)
	}
	defer os.RemoveAll(dir)

	err = watcher.Watch(dir)
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<|endoftext|>


<commit_before>package parser

import (
	"log"
	"strconv"
	"strings"
	"unicode/utf16"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/robertsdionne/dcpu"
)

//go:generate java -jar $HOME/Downloads/antlr-4.6-complete.jar -Dlanguage=Go -package parser DCPU.g4 -visitor

func Assemble(source string) (program []uint16) {
	input := antlr.NewInputStream(source)
	lexer := NewDCPULexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	parser := NewDCPUParser(stream)
	parser.BuildParseTrees = true
	visitor := Assembler{
		BaseDCPUVisitor: &BaseDCPUVisitor{},
	}
	program = visitor.Visit(parser.Program()).([]uint16)
	return
}

type Assembler struct {
	*BaseDCPUVisitor
}

func (a *Assembler) Visit(tree antlr.ParseTree) interface{} {
	return tree.Accept(a)
}

func (a *Assembler) VisitChildren(node antlr.RuleNode) interface{} {
	var results []interface{}
	for _, child := range node.GetChildren() {
		results = append(results, child.(antlr.ParseTree).Accept(a))
	}
	return results
}

func (a *Assembler) VisitProgram(ctx *ProgramContext) interface{} {
	program := []interface{}{}
	labelAddresses := map[string]uint16{}

	results := a.VisitChildren(ctx)
	for _, result := range results.([]interface{}) {
		switch result := result.(type) {
		case []interface{}:
			for _, word := range result {
				program = append(program, word)
			}

		case string:
			labelAddresses[result] = uint16(len(program))
		}
	}

	assembledProgram := []uint16{}

	for _, word := range program {
		switch word := word.(type) {
		case uint16:
			assembledProgram = append(assembledProgram, word)
		case string:
			assembledProgram = append(assembledProgram, labelAddresses[word])
		default:
			log.Fatalln("Found bad type", word)
		}
	}

	return assembledProgram
}

func (a *Assembler) VisitInstruction(ctx *InstructionContext) interface{} {
	switch {
	case ctx.BinaryOperation() != nil:
		return a.Visit(ctx.BinaryOperation())

	case ctx.UnaryOperation() != nil:
		return a.Visit(ctx.UnaryOperation())

	case ctx.DebugOperation() != nil:
		return a.Visit(ctx.DebugOperation())
	}
	return nil
}

func (a *Assembler) VisitLabelDefinition(ctx *LabelDefinitionContext) interface{} {
	return ctx.IDENTIFIER().GetText()
}

func (a *Assembler) VisitDataSection(ctx *DataSectionContext) interface{} {
	return a.Visit(ctx.Data())
}

func (a *Assembler) VisitData(ctx *DataContext) interface{} {
	var result []interface{}
	for _, child := range ctx.GetChildren() {
		switch child := child.(type) {
		case *DatumContext:
			datum := a.Visit(child)
			switch datum := datum.(type) {
			case []uint16:
				for _, value := range datum {
					result = append(result, value)
				}

			case string, uint16:
				result = append(result, datum)
			}
		}
	}
	return result
}

func (a *Assembler) VisitDatum(ctx *DatumContext) interface{} {
	switch {
	case ctx.STRING() != nil:
		text := ctx.STRING().GetText()
		encoded := utf16.Encode([]rune(text[1 : len(text)-2]))
		result := []uint16{uint16(len(encoded))}
		result = append(result, encoded...)
		return result

	case ctx.IDENTIFIER() != nil:
		return ctx.IDENTIFIER().GetText()

	case ctx.NUMBER() != nil:
		return parseValue(ctx.NUMBER().GetText())
	}

	return nil
}

func (a *Assembler) VisitBinaryOperation(ctx *BinaryOperationContext) interface{} {
	opcode := a.Visit(ctx.BinaryOpcode()).(uint16)
	argumentB := a.Visit(ctx.ArgumentB()).([]interface{})
	argumentA := a.Visit(ctx.ArgumentA()).([]interface{})
	result := []interface{}{
		opcode | argumentB[0].(uint16)<<dcpu.BasicValueShiftB | argumentA[0].(uint16)<<dcpu.BasicValueShiftA,
	}
	result = append(result, argumentB[1:]...)
	result = append(result, argumentA[1:]...)
	return result
}

func (a *Assembler) VisitBinaryOpcode(ctx *BinaryOpcodeContext) interface{} {
	return binaryOpcodeValue(ctx)
}

func binaryOpcodeValue(ctx *BinaryOpcodeContext) uint16 {
	switch {
	case ctx.SET() != nil:
		return dcpu.Set

	case ctx.ADD() != nil:
		return dcpu.Add

	case ctx.SUB() != nil:
		return dcpu.Subtract

	case ctx.MUL() != nil:
		return dcpu.Multiply

	case ctx.MLI() != nil:
		return dcpu.MultiplySigned

	case ctx.DIV() != nil:
		return dcpu.Divide

	case ctx.DVI() != nil:
		return dcpu.DivideSigned

	case ctx.MOD() != nil:
		return dcpu.Modulo

	case ctx.MDI() != nil:
		return dcpu.ModuloSigned

	case ctx.AND() != nil:
		return dcpu.BinaryAnd

	case ctx.BOR() != nil:
		return dcpu.BinaryOr

	case ctx.XOR() != nil:
		return dcpu.BinaryExclusiveOr

	case ctx.SHR() != nil:
		return dcpu.ShiftRight

	case ctx.ASR() != nil:
		return dcpu.ArithmeticShiftRight

	case ctx.SHL() != nil:
		return dcpu.ShiftLeft

	case ctx.IFB() != nil:
		return dcpu.IfBitSet

	case ctx.IFC() != nil:
		return dcpu.IfClear

	case ctx.IFE() != nil:
		return dcpu.IfEqual

	case ctx.IFN() != nil:
		return dcpu.IfNotEqual

	case ctx.IFG() != nil:
		return dcpu.IfGreaterThan

	case ctx.IFA() != nil:
		return dcpu.IfAbove

	case ctx.IFL() != nil:
		return dcpu.IfLessThan

	case ctx.IFU() != nil:
		return dcpu.IfUnder

	case ctx.ADX() != nil:
		return dcpu.AddWithCarry

	case ctx.SBX() != nil:
		return dcpu.SubtractWithCarry

	case ctx.STI() != nil:
		return dcpu.SetThenIncrement

	case ctx.STD() != nil:
		return dcpu.SetThenDecrement

	default:
		return 0
	}
}

func (a *Assembler) VisitUnaryOperation(ctx *UnaryOperationContext) interface{} {
	opcode := a.Visit(ctx.UnaryOpcode()).(uint16)
	argument := a.Visit(ctx.ArgumentA()).([]interface{})
	result := []interface{}{opcode<<dcpu.SpecialOpcodeShift | argument[0].(uint16)<<dcpu.SpecialValueShiftA}
	result = append(result, argument[1:]...)
	return result
}

func (a *Assembler) VisitUnaryOpcode(ctx *UnaryOpcodeContext) interface{} {
	return unaryOpcodeValue(ctx)
}

func unaryOpcodeValue(ctx *UnaryOpcodeContext) uint16 {
	switch {
	case ctx.JSR() != nil:
		return dcpu.JumpSubRoutine

	case ctx.INT() != nil:
		return dcpu.InterruptTrigger

	case ctx.IAG() != nil:
		return dcpu.InterruptAddressGet

	case ctx.IAS() != nil:
		return dcpu.InterruptAddressSet

	case ctx.RFI() != nil:
		return dcpu.ReturnFromInterrupt

	case ctx.IAQ() != nil:
		return dcpu.InterruptAddToQueue

	case ctx.HWN() != nil:
		return dcpu.HardwareNumberConnected

	case ctx.HWQ() != nil:
		return dcpu.HardwareQuery

	case ctx.HWI() != nil:
		return dcpu.HardwareInterrupt

	default:
		return 0
	}
}

func (a *Assembler) VisitDebugOperation(ctx *DebugOperationContext) interface{} {
	opcode := a.Visit(ctx.DebugOpcode()).(uint16)
	return []interface{}{opcode << dcpu.DebugOpcodeShift}
}

func (a *Assembler) VisitDebugOpcode(ctx *DebugOpcodeContext) interface{} {
	return debugOpcodeValue(ctx)
}

func debugOpcodeValue(ctx *DebugOpcodeContext) uint16 {
	switch {
	case ctx.ALT() != nil:
		return dcpu.Alert

	case ctx.DUM() != nil:
		return dcpu.DumpState

	default:
		return 0
	}
}

func (a *Assembler) VisitArgumentB(ctx *ArgumentBContext) interface{} {
	switch {
	case ctx.Register() != nil:
		return []interface{}{a.Visit(ctx.Register())}

	case ctx.LocationInRegister() != nil:
		return []interface{}{a.Visit(ctx.LocationInRegister())}

	case ctx.LocationOffsetByRegister() != nil:
		return a.Visit(ctx.LocationOffsetByRegister())

	case ctx.PUSH() != nil:
		return []interface{}{uint16(dcpu.Push)}

	case ctx.PEEK() != nil:
		return []interface{}{uint16(dcpu.Peek)}

	case ctx.Pick() != nil:
		return a.Visit(ctx.Pick())

	case ctx.STACK_POINTER() != nil:
		return []interface{}{uint16(dcpu.StackPointer)}

	case ctx.PROGRAM_COUNTER() != nil:
		return []interface{}{uint16(dcpu.ProgramCounter)}

	case ctx.EXTRA() != nil:
		return []interface{}{uint16(dcpu.Extra)}

	case ctx.Location() != nil:
		return []interface{}{uint16(dcpu.Location), a.Visit(ctx.Location())}
	}
	return []interface{}{uint16(0)}
}

func (a *Assembler) VisitRegister(ctx *RegisterContext) interface{} {
	return registerValue(ctx.REGISTER())
}

func (a *Assembler) VisitLocationInRegister(ctx *LocationInRegisterContext) interface{} {
	return registerValue(ctx.REGISTER()) + dcpu.LocationInRegisterA
}

func (a *Assembler) VisitLocationOffsetByRegister(ctx *LocationOffsetByRegisterContext) interface{} {
	var location interface{}
	switch {
	case ctx.Label() != nil:
		location = a.Visit(ctx.Label())
	case ctx.Value() != nil:
		location = a.Visit(ctx.Value())
	}
	return []interface{}{registerValue(ctx.REGISTER()) + dcpu.LocationOffsetByRegisterA, location}
}

func registerValue(register antlr.TerminalNode) uint16 {
	switch strings.ToUpper(register.GetText()) {
	case "A":
		return dcpu.RegisterA

	case "B":
		return dcpu.RegisterB

	case "C":
		return dcpu.RegisterC

	case "X":
		return dcpu.RegisterX

	case "Y":
		return dcpu.RegisterY

	case "Z":
		return dcpu.RegisterZ

	case "I":
		return dcpu.RegisterI

	case "J":
		return dcpu.RegisterJ
	}

	return 0
}

func (a *Assembler) VisitArgumentA(ctx *ArgumentAContext) interface{} {
	switch {
	case ctx.Register() != nil:
		return []interface{}{a.Visit(ctx.Register())}

	case ctx.LocationInRegister() != nil:
		return []interface{}{a.Visit(ctx.LocationInRegister())}

	case ctx.LocationOffsetByRegister() != nil:
		return a.Visit(ctx.LocationOffsetByRegister())

	case ctx.POP() != nil:
		return []interface{}{uint16(dcpu.Pop)}

	case ctx.PEEK() != nil:
		return []interface{}{uint16(dcpu.Peek)}

	case ctx.Pick() != nil:
		return a.Visit(ctx.Pick())

	case ctx.STACK_POINTER() != nil:
		return []interface{}{uint16(dcpu.StackPointer)}

	case ctx.PROGRAM_COUNTER() != nil:
		return []interface{}{uint16(dcpu.ProgramCounter)}

	case ctx.EXTRA() != nil:
		return []interface{}{uint16(dcpu.Extra)}

	case ctx.Location() != nil:
		return []interface{}{uint16(dcpu.Location), a.Visit(ctx.Location())}

	case ctx.Label() != nil:
		return []interface{}{uint16(dcpu.Literal), a.Visit(ctx.Label())}

	case ctx.Value() != nil:
		value := a.Visit(ctx.Value()).(uint16)
		switch {
		case value == 0xffff:
			return []interface{}{uint16(dcpu.LiteralNegative1)}
		case 0 <= value && value <= 30:
			return []interface{}{uint16(dcpu.Literal0 + value)}
		default:
			return []interface{}{uint16(dcpu.Literal), value}
		}
	}
	return []interface{}{uint16(0)}
}

func (a *Assembler) VisitLocation(ctx *LocationContext) interface{} {
	switch {
	case ctx.Label() != nil:
		return a.Visit(ctx.Label())

	case ctx.Value() != nil:
		return a.Visit(ctx.Value())
	}
	return nil
}

func (a *Assembler) VisitLabel(ctx *LabelContext) interface{} {
	return ctx.IDENTIFIER().GetText()
}

func (a *Assembler) VisitValue(ctx *ValueContext) interface{} {
	return parseValue(ctx.NUMBER().GetText())
}

func parseValue(text string) uint16 {
	switch {
	case strings.HasPrefix(text, "0x"):
		value, err := strconv.ParseUint(text[2:], 16, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	case strings.HasPrefix(text, "0b"):
		value, err := strconv.ParseUint(text[2:], 2, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	case strings.HasPrefix(text, "0") && text != "0":
		value, err := strconv.ParseUint(text[1:], 8, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	default:
		value, err := strconv.Atoi(text)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)
	}
}
<commit_msg>Don't export parser.Assembler.<commit_after>package parser

import (
	"log"
	"strconv"
	"strings"
	"unicode/utf16"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/robertsdionne/dcpu"
)

//go:generate java -jar $HOME/Downloads/antlr-4.6-complete.jar -Dlanguage=Go -package parser DCPU.g4 -visitor

func Assemble(source string) (program []uint16) {
	input := antlr.NewInputStream(source)
	lexer := NewDCPULexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	parser := NewDCPUParser(stream)
	parser.BuildParseTrees = true
	visitor := assembler{
		BaseDCPUVisitor: &BaseDCPUVisitor{},
	}
	program = visitor.Visit(parser.Program()).([]uint16)
	return
}

type assembler struct {
	*BaseDCPUVisitor
}

func (a *assembler) Visit(tree antlr.ParseTree) interface{} {
	return tree.Accept(a)
}

func (a *assembler) VisitChildren(node antlr.RuleNode) interface{} {
	var results []interface{}
	for _, child := range node.GetChildren() {
		results = append(results, child.(antlr.ParseTree).Accept(a))
	}
	return results
}

func (a *assembler) VisitProgram(ctx *ProgramContext) interface{} {
	program := []interface{}{}
	labelAddresses := map[string]uint16{}

	results := a.VisitChildren(ctx)
	for _, result := range results.([]interface{}) {
		switch result := result.(type) {
		case []interface{}:
			for _, word := range result {
				program = append(program, word)
			}

		case string:
			labelAddresses[result] = uint16(len(program))
		}
	}

	assembledProgram := []uint16{}

	for _, word := range program {
		switch word := word.(type) {
		case uint16:
			assembledProgram = append(assembledProgram, word)
		case string:
			assembledProgram = append(assembledProgram, labelAddresses[word])
		default:
			log.Fatalln("Found bad type", word)
		}
	}

	return assembledProgram
}

func (a *assembler) VisitInstruction(ctx *InstructionContext) interface{} {
	switch {
	case ctx.BinaryOperation() != nil:
		return a.Visit(ctx.BinaryOperation())

	case ctx.UnaryOperation() != nil:
		return a.Visit(ctx.UnaryOperation())

	case ctx.DebugOperation() != nil:
		return a.Visit(ctx.DebugOperation())
	}
	return nil
}

func (a *assembler) VisitLabelDefinition(ctx *LabelDefinitionContext) interface{} {
	return ctx.IDENTIFIER().GetText()
}

func (a *assembler) VisitDataSection(ctx *DataSectionContext) interface{} {
	return a.Visit(ctx.Data())
}

func (a *assembler) VisitData(ctx *DataContext) interface{} {
	var result []interface{}
	for _, child := range ctx.GetChildren() {
		switch child := child.(type) {
		case *DatumContext:
			datum := a.Visit(child)
			switch datum := datum.(type) {
			case []uint16:
				for _, value := range datum {
					result = append(result, value)
				}

			case string, uint16:
				result = append(result, datum)
			}
		}
	}
	return result
}

func (a *assembler) VisitDatum(ctx *DatumContext) interface{} {
	switch {
	case ctx.STRING() != nil:
		text := ctx.STRING().GetText()
		encoded := utf16.Encode([]rune(text[1 : len(text)-2]))
		result := []uint16{uint16(len(encoded))}
		result = append(result, encoded...)
		return result

	case ctx.IDENTIFIER() != nil:
		return ctx.IDENTIFIER().GetText()

	case ctx.NUMBER() != nil:
		return parseValue(ctx.NUMBER().GetText())
	}

	return nil
}

func (a *assembler) VisitBinaryOperation(ctx *BinaryOperationContext) interface{} {
	opcode := a.Visit(ctx.BinaryOpcode()).(uint16)
	argumentB := a.Visit(ctx.ArgumentB()).([]interface{})
	argumentA := a.Visit(ctx.ArgumentA()).([]interface{})
	result := []interface{}{
		opcode | argumentB[0].(uint16)<<dcpu.BasicValueShiftB | argumentA[0].(uint16)<<dcpu.BasicValueShiftA,
	}
	result = append(result, argumentB[1:]...)
	result = append(result, argumentA[1:]...)
	return result
}

func (a *assembler) VisitBinaryOpcode(ctx *BinaryOpcodeContext) interface{} {
	return binaryOpcodeValue(ctx)
}

func binaryOpcodeValue(ctx *BinaryOpcodeContext) uint16 {
	switch {
	case ctx.SET() != nil:
		return dcpu.Set

	case ctx.ADD() != nil:
		return dcpu.Add

	case ctx.SUB() != nil:
		return dcpu.Subtract

	case ctx.MUL() != nil:
		return dcpu.Multiply

	case ctx.MLI() != nil:
		return dcpu.MultiplySigned

	case ctx.DIV() != nil:
		return dcpu.Divide

	case ctx.DVI() != nil:
		return dcpu.DivideSigned

	case ctx.MOD() != nil:
		return dcpu.Modulo

	case ctx.MDI() != nil:
		return dcpu.ModuloSigned

	case ctx.AND() != nil:
		return dcpu.BinaryAnd

	case ctx.BOR() != nil:
		return dcpu.BinaryOr

	case ctx.XOR() != nil:
		return dcpu.BinaryExclusiveOr

	case ctx.SHR() != nil:
		return dcpu.ShiftRight

	case ctx.ASR() != nil:
		return dcpu.ArithmeticShiftRight

	case ctx.SHL() != nil:
		return dcpu.ShiftLeft

	case ctx.IFB() != nil:
		return dcpu.IfBitSet

	case ctx.IFC() != nil:
		return dcpu.IfClear

	case ctx.IFE() != nil:
		return dcpu.IfEqual

	case ctx.IFN() != nil:
		return dcpu.IfNotEqual

	case ctx.IFG() != nil:
		return dcpu.IfGreaterThan

	case ctx.IFA() != nil:
		return dcpu.IfAbove

	case ctx.IFL() != nil:
		return dcpu.IfLessThan

	case ctx.IFU() != nil:
		return dcpu.IfUnder

	case ctx.ADX() != nil:
		return dcpu.AddWithCarry

	case ctx.SBX() != nil:
		return dcpu.SubtractWithCarry

	case ctx.STI() != nil:
		return dcpu.SetThenIncrement

	case ctx.STD() != nil:
		return dcpu.SetThenDecrement

	default:
		return 0
	}
}

func (a *assembler) VisitUnaryOperation(ctx *UnaryOperationContext) interface{} {
	opcode := a.Visit(ctx.UnaryOpcode()).(uint16)
	argument := a.Visit(ctx.ArgumentA()).([]interface{})
	result := []interface{}{opcode<<dcpu.SpecialOpcodeShift | argument[0].(uint16)<<dcpu.SpecialValueShiftA}
	result = append(result, argument[1:]...)
	return result
}

func (a *assembler) VisitUnaryOpcode(ctx *UnaryOpcodeContext) interface{} {
	return unaryOpcodeValue(ctx)
}

func unaryOpcodeValue(ctx *UnaryOpcodeContext) uint16 {
	switch {
	case ctx.JSR() != nil:
		return dcpu.JumpSubRoutine

	case ctx.INT() != nil:
		return dcpu.InterruptTrigger

	case ctx.IAG() != nil:
		return dcpu.InterruptAddressGet

	case ctx.IAS() != nil:
		return dcpu.InterruptAddressSet

	case ctx.RFI() != nil:
		return dcpu.ReturnFromInterrupt

	case ctx.IAQ() != nil:
		return dcpu.InterruptAddToQueue

	case ctx.HWN() != nil:
		return dcpu.HardwareNumberConnected

	case ctx.HWQ() != nil:
		return dcpu.HardwareQuery

	case ctx.HWI() != nil:
		return dcpu.HardwareInterrupt

	default:
		return 0
	}
}

func (a *assembler) VisitDebugOperation(ctx *DebugOperationContext) interface{} {
	opcode := a.Visit(ctx.DebugOpcode()).(uint16)
	return []interface{}{opcode << dcpu.DebugOpcodeShift}
}

func (a *assembler) VisitDebugOpcode(ctx *DebugOpcodeContext) interface{} {
	return debugOpcodeValue(ctx)
}

func debugOpcodeValue(ctx *DebugOpcodeContext) uint16 {
	switch {
	case ctx.ALT() != nil:
		return dcpu.Alert

	case ctx.DUM() != nil:
		return dcpu.DumpState

	default:
		return 0
	}
}

func (a *assembler) VisitArgumentB(ctx *ArgumentBContext) interface{} {
	switch {
	case ctx.Register() != nil:
		return []interface{}{a.Visit(ctx.Register())}

	case ctx.LocationInRegister() != nil:
		return []interface{}{a.Visit(ctx.LocationInRegister())}

	case ctx.LocationOffsetByRegister() != nil:
		return a.Visit(ctx.LocationOffsetByRegister())

	case ctx.PUSH() != nil:
		return []interface{}{uint16(dcpu.Push)}

	case ctx.PEEK() != nil:
		return []interface{}{uint16(dcpu.Peek)}

	case ctx.Pick() != nil:
		return a.Visit(ctx.Pick())

	case ctx.STACK_POINTER() != nil:
		return []interface{}{uint16(dcpu.StackPointer)}

	case ctx.PROGRAM_COUNTER() != nil:
		return []interface{}{uint16(dcpu.ProgramCounter)}

	case ctx.EXTRA() != nil:
		return []interface{}{uint16(dcpu.Extra)}

	case ctx.Location() != nil:
		return []interface{}{uint16(dcpu.Location), a.Visit(ctx.Location())}
	}
	return []interface{}{uint16(0)}
}

func (a *assembler) VisitRegister(ctx *RegisterContext) interface{} {
	return registerValue(ctx.REGISTER())
}

func (a *assembler) VisitLocationInRegister(ctx *LocationInRegisterContext) interface{} {
	return registerValue(ctx.REGISTER()) + dcpu.LocationInRegisterA
}

func (a *assembler) VisitLocationOffsetByRegister(ctx *LocationOffsetByRegisterContext) interface{} {
	var location interface{}
	switch {
	case ctx.Label() != nil:
		location = a.Visit(ctx.Label())
	case ctx.Value() != nil:
		location = a.Visit(ctx.Value())
	}
	return []interface{}{registerValue(ctx.REGISTER()) + dcpu.LocationOffsetByRegisterA, location}
}

func registerValue(register antlr.TerminalNode) uint16 {
	switch strings.ToUpper(register.GetText()) {
	case "A":
		return dcpu.RegisterA

	case "B":
		return dcpu.RegisterB

	case "C":
		return dcpu.RegisterC

	case "X":
		return dcpu.RegisterX

	case "Y":
		return dcpu.RegisterY

	case "Z":
		return dcpu.RegisterZ

	case "I":
		return dcpu.RegisterI

	case "J":
		return dcpu.RegisterJ
	}

	return 0
}

func (a *assembler) VisitArgumentA(ctx *ArgumentAContext) interface{} {
	switch {
	case ctx.Register() != nil:
		return []interface{}{a.Visit(ctx.Register())}

	case ctx.LocationInRegister() != nil:
		return []interface{}{a.Visit(ctx.LocationInRegister())}

	case ctx.LocationOffsetByRegister() != nil:
		return a.Visit(ctx.LocationOffsetByRegister())

	case ctx.POP() != nil:
		return []interface{}{uint16(dcpu.Pop)}

	case ctx.PEEK() != nil:
		return []interface{}{uint16(dcpu.Peek)}

	case ctx.Pick() != nil:
		return a.Visit(ctx.Pick())

	case ctx.STACK_POINTER() != nil:
		return []interface{}{uint16(dcpu.StackPointer)}

	case ctx.PROGRAM_COUNTER() != nil:
		return []interface{}{uint16(dcpu.ProgramCounter)}

	case ctx.EXTRA() != nil:
		return []interface{}{uint16(dcpu.Extra)}

	case ctx.Location() != nil:
		return []interface{}{uint16(dcpu.Location), a.Visit(ctx.Location())}

	case ctx.Label() != nil:
		return []interface{}{uint16(dcpu.Literal), a.Visit(ctx.Label())}

	case ctx.Value() != nil:
		value := a.Visit(ctx.Value()).(uint16)
		switch {
		case value == 0xffff:
			return []interface{}{uint16(dcpu.LiteralNegative1)}
		case 0 <= value && value <= 30:
			return []interface{}{uint16(dcpu.Literal0 + value)}
		default:
			return []interface{}{uint16(dcpu.Literal), value}
		}
	}
	return []interface{}{uint16(0)}
}

func (a *assembler) VisitLocation(ctx *LocationContext) interface{} {
	switch {
	case ctx.Label() != nil:
		return a.Visit(ctx.Label())

	case ctx.Value() != nil:
		return a.Visit(ctx.Value())
	}
	return nil
}

func (a *assembler) VisitLabel(ctx *LabelContext) interface{} {
	return ctx.IDENTIFIER().GetText()
}

func (a *assembler) VisitValue(ctx *ValueContext) interface{} {
	return parseValue(ctx.NUMBER().GetText())
}

func parseValue(text string) uint16 {
	switch {
	case strings.HasPrefix(text, "0x"):
		value, err := strconv.ParseUint(text[2:], 16, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	case strings.HasPrefix(text, "0b"):
		value, err := strconv.ParseUint(text[2:], 2, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	case strings.HasPrefix(text, "0") && text != "0":
		value, err := strconv.ParseUint(text[1:], 8, 16)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)

	default:
		value, err := strconv.Atoi(text)
		if err != nil {
			log.Fatalln(err)
		}
		return uint16(value)
	}
}
<|endoftext|>


<commit_before>package ciolite

// Api functions that support: https://context.io/docs/lite/users/email_accounts/folders/messages

import (
	"fmt"

	"github.com/contextio/contextio-go/cioutil"
)

// GetUserEmailAccountsFolderMessageParams query values data struct.
// Optional: Delimiter, IncludeBody, BodyType, IncludeHeaders, IncludeFlags,
// and (for GetUserEmailAccountsFolderMessages only) Limit, Offset.
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUserEmailAccountsFolderMessageParams struct {
	// Optional:
	Delimiter    string `json:"delimiter,omitempty"`
	BodyType     string `json:"body_type,omitempty"`
	IncludeBody  bool   `json:"include_body,omitempty"`
	IncludeFlags bool   `json:"include_flags,omitempty"`

	// IncludeHeaders can be "0", "1", or "raw"
	IncludeHeaders string `json:"include_headers,omitempty"`

	// Optional for GetUserEmailAccountsFolderMessages (not used by GetUserEmailAccountFolderMessage):
	Limit  int `json:"limit,omitempty"`
	Offset int `json:"offset,omitempty"`
}

// GetUsersEmailAccountFolderMessagesResponse data struct
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUsersEmailAccountFolderMessagesResponse struct {
	EmailMessageID string `json:"email_message_id,omitempty"`
	Subject        string `json:"subject,omitempty"`
	MessageID      string `json:"message_id,omitempty"`
	InReplyTo      string `json:"in_reply_to,omitempty"`
	ResourceURL    string `json:"resource_url,omitempty"`

	Folders         []string `json:"folders,omitempty"`
	ListHeaders     []string `json:"list_headers,omitempty"`
	References      []string `json:"references,omitempty"`
	ReceivedHeaders []string `json:"received_headers,omitempty"`

	Addresses GetUsersEmailAccountFolderMessageAddresses `json:"addresses,omitempty"`

	PersonInfo PersonInfo `json:"person_info,omitempty"`

	Attachments []struct {
		Type               string `json:"type,omitempty"`
		FileName           string `json:"file_name,omitempty"`
		BodySection        string `json:"body_section,omitempty"`
		ContentDisposition string `json:"content_disposition,omitempty"`
		EmailMessageID     string `json:"email_message_id,omitempty"`
		XAttachmentID      string `json:"x_attachment_id,omitempty"`

		Size         int `json:"size,omitempty"`
		AttachmentID int `json:"attachment_id,omitempty"`
	} `json:"attachments,omitempty"`

	Bodies []struct {
		BodySection string `json:"body_section,omitempty"`
		Type        string `json:"type,omitempty"`
		Encoding    string `json:"encoding,omitempty"`

		Size int `json:"size,omitempty"`
	} `json:"bodies,omitempty"`

	SentAt     int `json:"sent_at,omitempty"`
	ReceivedAt int `json:"received_at,omitempty"`
}

// PersonInfo data struct within GetUsersEmailAccountFolderMessagesResponse and WebhookMessageData
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type PersonInfo map[string]map[string]string

// GetUsersEmailAccountFolderMessageAddresses data struct within GetUsersEmailAccountFolderMessagesResponse
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUsersEmailAccountFolderMessageAddresses struct {
	From []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"from,omitempty"`

	To []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"to,omitempty"`

	Cc []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"cc,omitempty"`

	Bcc []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"bcc,omitempty"`

	Sender []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"sender,omitempty"`

	ReplyTo []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"reply_to,omitempty"`
}

// MoveUserEmailAccountFolderMessageParams form values data struct.
// Requires: NewFolderID, and may optionally contain Delimiter.
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
type MoveUserEmailAccountFolderMessageParams struct {
	// Required:
	NewFolderID string `json:"new_folder_id"`
	// Optional:
	Delimiter string `json:"delimiter,omitempty"`
}

// MoveUserEmailAccountFolderMessageResponse data struct
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
type MoveUserEmailAccountFolderMessageResponse struct {
	Success bool `json:"success,omitempty"`
}

// GetUserEmailAccountsFolderMessages gets listings of email messages for a user.
// queryValues may optionally contain Delimiter, IncludeBody, BodyType,
// IncludeHeaders, IncludeFlags, Limit, Offset
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
func (cioLite CioLite) GetUserEmailAccountsFolderMessages(userID string, label string, folder string, queryValues GetUserEmailAccountsFolderMessageParams) ([]GetUsersEmailAccountFolderMessagesResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "GET",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages", userID, label, folder),
		QueryValues: queryValues,
	}

	// Make response
	var response []GetUsersEmailAccountFolderMessagesResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}

// GetUserEmailAccountFolderMessage gets file, contact and other information about a given email message.
// queryValues may optionally contain Delimiter, IncludeBody, BodyType, IncludeHeaders, IncludeFlags
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
func (cioLite CioLite) GetUserEmailAccountFolderMessage(userID string, label string, folder string, messageID string, queryValues GetUserEmailAccountsFolderMessageParams) (GetUsersEmailAccountFolderMessagesResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "GET",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages/%s", userID, label, folder, messageID),
		QueryValues: queryValues,
	}

	// Make response
	var response GetUsersEmailAccountFolderMessagesResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}

// MoveUserEmailAccountFolderMessage moves a message.
// formValues requires NewFolderID, and may optionally contain Delimiter
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
func (cioLite CioLite) MoveUserEmailAccountFolderMessage(userID string, label string, folder string, messageID string, queryValues MoveUserEmailAccountFolderMessageParams) (MoveUserEmailAccountFolderMessageResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "PUT",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages/%s", userID, label, folder, messageID),
		QueryValues: queryValues,
	}

	// Make response
	var response MoveUserEmailAccountFolderMessageResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}
<commit_msg>encode the message id in the query<commit_after>package ciolite

// Api functions that support: https://context.io/docs/lite/users/email_accounts/folders/messages

import (
	"fmt"
	"net/url"

	"github.com/contextio/contextio-go/cioutil"
)

// GetUserEmailAccountsFolderMessageParams query values data struct.
// Optional: Delimiter, IncludeBody, BodyType, IncludeHeaders, IncludeFlags,
// and (for GetUserEmailAccountsFolderMessages only) Limit, Offset.
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUserEmailAccountsFolderMessageParams struct {
	// Optional:
	Delimiter    string `json:"delimiter,omitempty"`
	BodyType     string `json:"body_type,omitempty"`
	IncludeBody  bool   `json:"include_body,omitempty"`
	IncludeFlags bool   `json:"include_flags,omitempty"`

	// IncludeHeaders can be "0", "1", or "raw"
	IncludeHeaders string `json:"include_headers,omitempty"`

	// Optional for GetUserEmailAccountsFolderMessages (not used by GetUserEmailAccountFolderMessage):
	Limit  int `json:"limit,omitempty"`
	Offset int `json:"offset,omitempty"`
}

// GetUsersEmailAccountFolderMessagesResponse data struct
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUsersEmailAccountFolderMessagesResponse struct {
	EmailMessageID string `json:"email_message_id,omitempty"`
	Subject        string `json:"subject,omitempty"`
	MessageID      string `json:"message_id,omitempty"`
	InReplyTo      string `json:"in_reply_to,omitempty"`
	ResourceURL    string `json:"resource_url,omitempty"`

	Folders         []string `json:"folders,omitempty"`
	ListHeaders     []string `json:"list_headers,omitempty"`
	References      []string `json:"references,omitempty"`
	ReceivedHeaders []string `json:"received_headers,omitempty"`

	Addresses GetUsersEmailAccountFolderMessageAddresses `json:"addresses,omitempty"`

	PersonInfo PersonInfo `json:"person_info,omitempty"`

	Attachments []struct {
		Type               string `json:"type,omitempty"`
		FileName           string `json:"file_name,omitempty"`
		BodySection        string `json:"body_section,omitempty"`
		ContentDisposition string `json:"content_disposition,omitempty"`
		EmailMessageID     string `json:"email_message_id,omitempty"`
		XAttachmentID      string `json:"x_attachment_id,omitempty"`

		Size         int `json:"size,omitempty"`
		AttachmentID int `json:"attachment_id,omitempty"`
	} `json:"attachments,omitempty"`

	Bodies []struct {
		BodySection string `json:"body_section,omitempty"`
		Type        string `json:"type,omitempty"`
		Encoding    string `json:"encoding,omitempty"`

		Size int `json:"size,omitempty"`
	} `json:"bodies,omitempty"`

	SentAt     int `json:"sent_at,omitempty"`
	ReceivedAt int `json:"received_at,omitempty"`
}

// PersonInfo data struct within GetUsersEmailAccountFolderMessagesResponse and WebhookMessageData
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type PersonInfo map[string]map[string]string

// GetUsersEmailAccountFolderMessageAddresses data struct within GetUsersEmailAccountFolderMessagesResponse
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
type GetUsersEmailAccountFolderMessageAddresses struct {
	From []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"from,omitempty"`

	To []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"to,omitempty"`

	Cc []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"cc,omitempty"`

	Bcc []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"bcc,omitempty"`

	Sender []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"sender,omitempty"`

	ReplyTo []struct {
		Email string `json:"email,omitempty"`
		Name  string `json:"name,omitempty"`
	} `json:"reply_to,omitempty"`
}

// MoveUserEmailAccountFolderMessageParams form values data struct.
// Requires: NewFolderID, and may optionally contain Delimiter.
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
type MoveUserEmailAccountFolderMessageParams struct {
	// Required:
	NewFolderID string `json:"new_folder_id"`
	// Optional:
	Delimiter string `json:"delimiter,omitempty"`
}

// MoveUserEmailAccountFolderMessageResponse data struct
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
type MoveUserEmailAccountFolderMessageResponse struct {
	Success bool `json:"success,omitempty"`
}

// GetUserEmailAccountsFolderMessages gets listings of email messages for a user.
// queryValues may optionally contain Delimiter, IncludeBody, BodyType,
// IncludeHeaders, IncludeFlags, Limit, Offset
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#get
func (cioLite CioLite) GetUserEmailAccountsFolderMessages(userID string, label string, folder string, queryValues GetUserEmailAccountsFolderMessageParams) ([]GetUsersEmailAccountFolderMessagesResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "GET",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages", userID, label, folder),
		QueryValues: queryValues,
	}

	// Make response
	var response []GetUsersEmailAccountFolderMessagesResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}

// GetUserEmailAccountFolderMessage gets file, contact and other information about a given email message.
// queryValues may optionally contain Delimiter, IncludeBody, BodyType, IncludeHeaders, IncludeFlags
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-get
func (cioLite CioLite) GetUserEmailAccountFolderMessage(userID string, label string, folder string, messageID string, queryValues GetUserEmailAccountsFolderMessageParams) (GetUsersEmailAccountFolderMessagesResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "GET",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages/%s", userID, label, folder, url.QueryEscape(messageID)),
		QueryValues: queryValues,
	}

	// Make response
	var response GetUsersEmailAccountFolderMessagesResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}

// MoveUserEmailAccountFolderMessage moves a message.
// formValues requires NewFolderID, and may optionally contain Delimiter
// 	https://context.io/docs/lite/users/email_accounts/folders/messages#id-put
func (cioLite CioLite) MoveUserEmailAccountFolderMessage(userID string, label string, folder string, messageID string, queryValues MoveUserEmailAccountFolderMessageParams) (MoveUserEmailAccountFolderMessageResponse, error) {

	// Make request
	request := cioutil.ClientRequest{
		Method:      "PUT",
		Path:        fmt.Sprintf("/users/%s/email_accounts/%s/folders/%s/messages/%s", userID, label, folder, url.QueryEscape(messageID)),
		QueryValues: queryValues,
	}

	// Make response
	var response MoveUserEmailAccountFolderMessageResponse

	// Request
	err := cioLite.DoFormRequest(request, &response)

	return response, err
}
<|endoftext|>


<commit_before>package loader

import (
	"context"
	"fmt"
	"github.com/Pixboost/transformimgs/v8/img"
	"io/ioutil"
	"net/http"
)

type Http struct {
	// Headers will set headers on each request
	Headers http.Header
}

func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	for k, v := range r.Headers {
		for _, headerVal := range v {
			req.Header.Add(k, headerVal)
		}
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Expected %d but got code %d.\n Error '%s'",
			http.StatusOK, resp.StatusCode, resp.Status)
	}

	contentType := resp.Header.Get("Content-Type")

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return &img.Image{
		Id:       url,
		Data:     result,
		MimeType: contentType,
	}, nil
}
<commit_msg>Decreased connection timeout to 5 seconds when reading a source image<commit_after>package loader

import (
	"context"
	"fmt"
	"github.com/Pixboost/transformimgs/v8/img"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

type Http struct {
	// Headers will set headers on each request
	Headers http.Header
}

var dialer = &net.Dialer{
	Timeout:   5 * time.Second,
	KeepAlive: 30 * time.Second,
}

var client = &http.Client{
	Transport: &http.Transport{
		Proxy:                 http.ProxyFromEnvironment,
		DialContext:           dialer.DialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	},
}

func (r *Http) Load(url string, _ context.Context) (*img.Image, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	for k, v := range r.Headers {
		for _, headerVal := range v {
			req.Header.Add(k, headerVal)
		}
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Expected %d but got code %d.\n Error '%s'",
			http.StatusOK, resp.StatusCode, resp.Status)
	}

	contentType := resp.Header.Get("Content-Type")

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return &img.Image{
		Id:       url,
		Data:     result,
		MimeType: contentType,
	}, nil
}
<|endoftext|>


<commit_before>package etcdserver

import (
	"fmt"
	"reflect"
	"testing"
	"time"
	"code.google.com/p/go.net/context"

	pb "github.com/coreos/etcd/etcdserver2/etcdserverpb"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/raft/raftpb"
	"github.com/coreos/etcd/store"
)

func TestClusterOf1(t *testing.T) { testServer(t, 1) }
func TestClusterOf3(t *testing.T) { testServer(t, 3) }

func testServer(t *testing.T, ns int64) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	ss := make([]*Server, ns)

	send := func(msgs []raftpb.Message) {
		for _, m := range msgs {
			fmt.Printf("sending: %+v\n", m)
			ss[m.To].Node.Step(ctx, m)
		}
	}

	peers := make([]int64, ns)
	for i := int64(0); i < ns; i++ {
		peers[i] = i
	}

	var srv *Server
	for i := int64(0); i < ns; i++ {
		n := raft.Start(ctx, i, peers)

		srv = &Server{
			Node:  n,
			Store: store.New(),
			Send:  send,
			Save:  func(_ raftpb.State, _ []raftpb.Entry) {},
		}
		Start(srv)

		ss[i] = srv
	}

	if err := srv.Node.Campaign(ctx); err != nil {
		t.Fatal(err)
	}

	r := pb.Request{
		Method: "PUT",
		Id:     1,
		Path:   "/foo",
		Val:    "bar",
	}
	resp, err := srv.Do(ctx, r)
	if err != nil {
		t.Fatal(err)
	}

	g, w := resp.Event.Node, &store.NodeExtern{
		Key:           "/foo",
		ModifiedIndex: 1,
		CreatedIndex:  1,
		Value:         stringp("bar"),
	}

	if !reflect.DeepEqual(g, w) {
		t.Error("value:", *g.Value)
		t.Errorf("g = %+v, w %+v", g, w)
	}

	time.Sleep(10 * time.Millisecond)

	var last interface{}
	for i, sv := range ss {
		sv.Stop()
		g := store.Root(sv.Store)
		if last != nil && !reflect.DeepEqual(last, g) {
			t.Errorf("server %d: Root = %#v, want %#v", i, g, last)
		}
		last = g
	}
}

func stringp(s string) *string { return &s }
<commit_msg>etcdserver: set 10x the keys in test<commit_after>package etcdserver

import (
	"fmt"
	"reflect"
	"testing"
	"time"
	"code.google.com/p/go.net/context"

	pb "github.com/coreos/etcd/etcdserver2/etcdserverpb"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/raft/raftpb"
	"github.com/coreos/etcd/store"
)

func TestClusterOf1(t *testing.T) { testServer(t, 1) }
func TestClusterOf3(t *testing.T) { testServer(t, 3) }

func testServer(t *testing.T, ns int64) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	ss := make([]*Server, ns)

	send := func(msgs []raftpb.Message) {
		for _, m := range msgs {
			fmt.Printf("sending: %+v\n", m)
			ss[m.To].Node.Step(ctx, m)
		}
	}

	peers := make([]int64, ns)
	for i := int64(0); i < ns; i++ {
		peers[i] = i
	}

	var srv *Server
	for i := int64(0); i < ns; i++ {
		n := raft.Start(ctx, i, peers)

		srv = &Server{
			Node:  n,
			Store: store.New(),
			Send:  send,
			Save:  func(_ raftpb.State, _ []raftpb.Entry) {},
		}
		Start(srv)

		ss[i] = srv
	}

	if err := srv.Node.Campaign(ctx); err != nil {
		t.Fatal(err)
	}

	for i := 1; i <= 10; i++ {
		r := pb.Request{
			Method: "PUT",
			Id:     1,
			Path:   "/foo",
			Val:    "bar",
		}
		resp, err := srv.Do(ctx, r)
		if err != nil {
			t.Fatal(err)
		}

		g, w := resp.Event.Node, &store.NodeExtern{
			Key:           "/foo",
			ModifiedIndex: uint64(i),
			CreatedIndex:  uint64(i),
			Value:         stringp("bar"),
		}

		if !reflect.DeepEqual(g, w) {
			t.Error("value:", *g.Value)
			t.Errorf("g = %+v, w %+v", g, w)
		}
	}

	time.Sleep(10 * time.Millisecond)

	var last interface{}
	for i, sv := range ss {
		sv.Stop()
		g := store.Root(sv.Store)
		if last != nil && !reflect.DeepEqual(last, g) {
			t.Errorf("server %d: Root = %#v, want %#v", i, g, last)
		}
		last = g
	}
}

func stringp(s string) *string { return &s }
<|endoftext|>


<commit_before>package url

import (
	"errors"
	"html"
	"regexp"
)

var titleRE = regexp.MustCompile(`<title[^>]*>([^<]+)<`)

type Default struct{}

func (p *Default) Match(url string) bool { return true }

func (p *Default) Parse(body string) (string, error) {
	text := titleRE.FindStringSubmatch(body)
	if text == nil {
		return "", errors.New("url: cannot parse title")
	}
	return Trim(html.UnescapeString(text[1])), nil
}
<commit_msg>lib/url: parse <title> case insensitive<commit_after>package url

import (
	"errors"
	"html"
	"regexp"
)

var titleRE = regexp.MustCompile(`(?i)<title[^>]*>([^<]+)<`)

type Default struct{}

func (p *Default) Match(url string) bool { return true }

func (p *Default) Parse(body string) (string, error) {
	text := titleRE.FindStringSubmatch(body)
	if text == nil {
		return "", errors.New("url: cannot parse title")
	}
	return Trim(html.UnescapeString(text[1])), nil
}
<|endoftext|>


<commit_before>package test

import (
	"bufio"
	"errors"
	"flag"
	"log"
	"net"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/blackchip-org/chatty/irc"
)

var (
	RealServer bool
	nextPort   = 6667
)

func init() {
	flag.BoolVar(&RealServer, "real-server", false, "run tests using a real server")
}

type Server struct {
	server    *irc.Server
	clients   []*Client
	err       error
	connDelay time.Duration
	t         *testing.T
}

type Client struct {
	conn  net.Conn
	recvq chan string
	w     *bufio.Writer
	debug bool
	err   error
	t     *testing.T
}

func NewServer(t *testing.T) (*Server, *Client) {
	addr := ":" + strconv.Itoa(nextPort)
	if !RealServer {
		nextPort++
		if nextPort > 6668 {
			nextPort = 6667
		}
	}
	ts := &Server{
		server: &irc.Server{
			Name: "irc.localhost",
			Addr: addr,
		},
		clients: make([]*Client, 0),
		t:       t,
	}
	if !RealServer {
		go func() {
			retries := 0
			for {
				if err := ts.server.ListenAndServe(); err != nil {
					if retries >= 10 {
						log.Printf("server error: %v\n", err)
						ts.err = err
						return
					}
					retries++
					time.Sleep(100 * time.Millisecond)
				} else {
					return
				}
			}
		}()
	}
	if RealServer {
		ts.connDelay = 1 * time.Second
	}
	tc := ts.NewClient()
	return ts, tc
}

func (s *Server) NewClient() *Client {
	tc := &Client{
		recvq: make(chan string, 1024),
		t:     s.t,
	}
	s.clients = append(s.clients, tc)
	if s.err != nil {
		tc.err = s.err
		return tc
	}
	err := tc.connect(s.server.Addr)
	if err != nil {
		tc.err = err
		return tc
	}
	go func() {
		if err := tc.reader(); err != nil {
			tc.err = err
		}
	}()
	if RealServer {
		tc.debug = true
	}
	time.Sleep(s.connDelay)
	return tc
}

func (s *Server) Quit() {
	for _, client := range s.clients {
		if client.conn != nil {
			client.Send("QUIT")
			client.conn.Close()
		}
	}
	s.server.Quit()
}

func (c *Client) connect(addr string) error {
	retries := 0
	for {
		conn, err := net.Dial("tcp", addr)
		if err != nil {
			if retries >= 10 {
				return err
			}
		} else {
			c.conn = conn
			c.w = bufio.NewWriter(conn)
			return nil
		}
		retries++
		time.Sleep(100 * time.Millisecond)
	}
}

func (c *Client) Send(line string) {
	if c.err != nil {
		return
	}
	c.t.Logf(" -> [%p] %v", c, line)
	_, err := c.w.WriteString(line + "\r\n")
	if err != nil {
		c.err = err
		return
	}
	if err := c.w.Flush(); err != nil {
		c.err = err
		return
	}
}

func (c *Client) SendMessage(cmd string, params ...string) {
	m := irc.NewMessage(cmd, params...)
	c.Send(m.Encode())
}

func (c *Client) Recv() string {
	if c.err != nil {
		return ""
	}
	retries := 0
	for {
		select {
		case line := <-c.recvq:
			line = normalizeLine(line)
			c.t.Logf("<-  [%p] %v", c, line)
			return line
		default:
			retries++
			if retries > 10 {
				if c.err == nil {
					c.err = errors.New("recv timeout")
				}
				return "recv timeout"
			}
			time.Sleep(100 * time.Millisecond)
		}
	}
}

func (c *Client) Drain() string {
	if c.err != nil {
		return ""
	}
	lines := make([]string, 0)
	for {
		line := c.Recv()
		if line == "" {
			return strings.Join(lines, "\n")
		}
		lines = append(lines, line)
	}
}

func (c *Client) RecvMessage() irc.Message {
	line := c.Recv()
	return irc.DecodeMessage(line)
}

func (c *Client) reader() error {
	scanner := bufio.NewScanner(c.conn)
	for {
		if ok := scanner.Scan(); !ok {
			return scanner.Err()
		}
		line := scanner.Text()
		c.recvq <- line
	}
}

func (c *Client) WaitFor(reply string) irc.Message {
	c.t.Logf("!!  [%p] waiting for %v", c, reply)
	for {
		m := c.RecvMessage()
		if c.err != nil {
			c.t.Logf("**  [%p] error %v", c, c.err)
			return irc.Message{}
		}
		if m.Cmd == reply {
			c.t.Logf("..  [%p] got %v", c, reply)
			return m
		}
	}
}

func (c *Client) Login(nick string, user string) {
	c.Send("NICK " + nick)
	c.Send("USER " + user)
	c.WaitFor(irc.RplEndOfMotd)
}

func (c *Client) LoginDefault() {
	c.Login("Batman", "Batman 0 * :Bruce Wayne")
}

func (c *Client) Err() error {
	return c.err
}

// Replace server specific host info with localhost for testing
func normalizeLine(line string) string {
	line = strings.TrimSpace(line)
	if !strings.HasPrefix(line, ":") {
		return line
	}
	parts := strings.Split(line, " ")
	at := strings.Index(parts[0], "@")
	if at < 0 {
		return line
	}
	parts[0] = parts[0][:at] + "@localhost"
	return strings.Join(parts, " ")
}
<commit_msg>logging tweaks<commit_after>package test

import (
	"bufio"
	"errors"
	"flag"
	"log"
	"net"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/blackchip-org/chatty/irc"
)

var (
	RealServer bool
	nextPort   = 6667
)

func init() {
	flag.BoolVar(&RealServer, "real-server", false, "run tests using a real server")
}

type Server struct {
	server    *irc.Server
	clients   []*Client
	err       error
	connDelay time.Duration
	t         *testing.T
}

type Client struct {
	conn  net.Conn
	recvq chan string
	w     *bufio.Writer
	debug bool
	err   error
	t     *testing.T
}

func NewServer(t *testing.T) (*Server, *Client) {
	addr := ":" + strconv.Itoa(nextPort)
	if !RealServer {
		nextPort++
		if nextPort > 6668 {
			nextPort = 6667
		}
	}
	ts := &Server{
		server: &irc.Server{
			Name: "irc.localhost",
			Addr: addr,
		},
		clients: make([]*Client, 0),
		t:       t,
	}
	if !RealServer {
		go func() {
			retries := 0
			for {
				if err := ts.server.ListenAndServe(); err != nil {
					if retries >= 10 {
						log.Printf("server error: %v\n", err)
						ts.err = err
						return
					}
					retries++
					time.Sleep(100 * time.Millisecond)
				} else {
					return
				}
			}
		}()
	}
	if RealServer {
		ts.connDelay = 1 * time.Second
	}
	tc := ts.NewClient()
	return ts, tc
}

func (s *Server) NewClient() *Client {
	tc := &Client{
		recvq: make(chan string, 1024),
		t:     s.t,
	}
	s.clients = append(s.clients, tc)
	if s.err != nil {
		tc.err = s.err
		return tc
	}
	err := tc.connect(s.server.Addr)
	if err != nil {
		tc.err = err
		return tc
	}
	go func() {
		if err := tc.reader(); err != nil {
			tc.err = err
		}
	}()
	if RealServer {
		tc.debug = true
	}
	time.Sleep(s.connDelay)
	return tc
}

func (s *Server) Quit() {
	for _, client := range s.clients {
		if client.conn != nil {
			client.Send("QUIT")
			client.conn.Close()
		}
	}
	s.server.Quit()
}

func (c *Client) connect(addr string) error {
	retries := 0
	for {
		conn, err := net.Dial("tcp", addr)
		if err != nil {
			if retries >= 10 {
				return err
			}
		} else {
			c.conn = conn
			c.w = bufio.NewWriter(conn)
			return nil
		}
		retries++
		time.Sleep(100 * time.Millisecond)
	}
}

func (c *Client) Send(line string) {
	if c.err != nil {
		return
	}
	c.t.Logf(" -> [%p] %v", c, line)
	_, err := c.w.WriteString(line + "\r\n")
	if err != nil {
		c.err = err
		return
	}
	if err := c.w.Flush(); err != nil {
		c.err = err
		return
	}
}

func (c *Client) SendMessage(cmd string, params ...string) {
	m := irc.NewMessage(cmd, params...)
	c.Send(m.Encode())
}

func (c *Client) Recv() string {
	if c.err != nil {
		return ""
	}
	retries := 0
	for {
		select {
		case line := <-c.recvq:
			line = normalizeLine(line)
			c.t.Logf("<-  [%p] %v", c, line)
			return line
		default:
			retries++
			if retries > 10 {
				if c.err == nil {
					c.err = errors.New("recv timeout")
				}
				return "recv timeout"
			}
			time.Sleep(100 * time.Millisecond)
		}
	}
}

func (c *Client) Drain() string {
	if c.err != nil {
		return ""
	}
	lines := make([]string, 0)
	for {
		line := c.Recv()
		if line == "" {
			return strings.Join(lines, "\n")
		}
		lines = append(lines, line)
	}
}

func (c *Client) RecvMessage() irc.Message {
	line := c.Recv()
	return irc.DecodeMessage(line)
}

func (c *Client) reader() error {
	scanner := bufio.NewScanner(c.conn)
	for {
		if ok := scanner.Scan(); !ok {
			return scanner.Err()
		}
		line := scanner.Text()
		c.recvq <- line
	}
}

func (c *Client) WaitFor(reply string) irc.Message {
	c.t.Logf(" !  [%p]\t%v wait", c, reply)
	for {
		m := c.RecvMessage()
		if c.err != nil {
			c.t.Logf(" *  [%p]\terror %v", c, c.err)
			return irc.Message{}
		}
		if m.Cmd == reply {
			c.t.Logf(" .  [%p]\t%v recv", c, reply)
			return m
		}
	}
}

func (c *Client) Login(nick string, user string) {
	c.Send("NICK " + nick)
	c.Send("USER " + user)
	c.WaitFor(irc.RplEndOfMotd)
}

func (c *Client) LoginDefault() {
	c.Login("Batman", "Batman 0 * :Bruce Wayne")
}

func (c *Client) Err() error {
	return c.err
}

// Replace server specific host info with localhost for testing
func normalizeLine(line string) string {
	line = strings.TrimSpace(line)
	if !strings.HasPrefix(line, ":") {
		return line
	}
	parts := strings.Split(line, " ")
	at := strings.Index(parts[0], "@")
	if at < 0 {
		return line
	}
	parts[0] = parts[0][:at] + "@localhost"
	return strings.Join(parts, " ")
}
<|endoftext|>


<commit_before>package som

import (
	"encoding/xml"
	"fmt"
	"io"
	"math"

	"github.com/gonum/matrix/mat64"
)

// Creates an SVG representation of the U-Matrix of the given codebook.
// codebook is the codebook we're displaying the U-Matrix for,
// coordsDims are the dimensions of the grid,
// uShape is the shape of the grid,
// title is the title of the output SVG,
// and writer is the io.Writter to write the output SVG to.
func UMatrixSVG(codebook *mat64.Dense, coordsDims []int, uShape string, title string, writer io.Writer) error {
	xmlEncoder := xml.NewEncoder(writer)
	// array to hold the xml elements
	elems := []interface{}{h1{Title: title}}

	rows, _ := codebook.Dims()
	distMat, _ := DistanceMx("euclidean", codebook)
	distMatRows, distMatCols := distMat.Dims()
	coords, _ := GridCoords(uShape, coordsDims)
	coordsDistMat, _ := DistanceMx("euclidean", coords)

	// get maximum distance between codebook vectors
	// maximum distance will be rgb(0,0,0)
	MAX := 0.0
	for i := 0; i < distMatRows; i++ {
		for j := i; j < distMatCols; j++ {
			if distMat.At(i, j) > MAX {
				MAX = distMat.At(i, j)
			}
		}
	}
	MUL := 20.0
	OFF := 10.0
	// function to scale the coord grid to something visible
	scale := func(x float64) float64 { return MUL*x + OFF }

	svgElem := svgElement{Width: float64(coordsDims[1])*MUL + 2*OFF, Height: float64(coordsDims[0])*MUL + 2*OFF, Polygons: make([]polygon, rows)}
	elems = append(elems, svgElem)
	for row := 0; row < rows; row++ {
		coord := coords.RowView(row)
		cbVec := codebook.RowView(row)
		avgDistance := 0.0
		// this is a rough approximation of the notion of neighbor grid coords
		allRowsInRadius := allRowsInRadius(row, math.Sqrt2*1.01, coordsDistMat)
		for _, rwd := range allRowsInRadius {
			if rwd.Dist > 0.0 {
				otherMu := codebook.RowView(rwd.Row)
				cbvDist, _ := Distance("euclidean", cbVec, otherMu)
				avgDistance += cbvDist
			}
		}
		avgDistance /= float64(len(allRowsInRadius) - 1)
		color := int((1.0 - avgDistance/MAX) * 255.0)
		polygonCoords := ""
		x := scale(coord.At(0, 0))
		y := scale(coord.At(1, 0))
		xOffset := 0.5 * MUL
		yOffset := 0.5 * MUL
		// hexagon has a different yOffset
		if uShape == "hexagon" {
			yOffset = math.Sqrt(0.75) / 2.0 * MUL
		}
		// draw a box around the current coord
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y+yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y-yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x-xOffset, y-yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x-xOffset, y+yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y+yOffset)

		svgElem.Polygons[row] = polygon{
			Points: []byte(polygonCoords),
			Style:  fmt.Sprintf("fill:rgb(%d,%d,%d);stroke:black;stroke-width:1", color, color, color),
		}
	}

	xmlEncoder.Encode(elems)
	xmlEncoder.Flush()

	return nil
}

type rowWithDist struct {
	Row  int
	Dist float64
}

func allRowsInRadius(selectedRow int, radius float64, distMatrix *mat64.Dense) []rowWithDist {
	rowsInRadius := []rowWithDist{}
	for i, dist := range distMatrix.RowView(selectedRow).RawVector().Data {
		if dist < radius {
			rowsInRadius = append(rowsInRadius, rowWithDist{Row: i, Dist: dist})
		}
	}
	return rowsInRadius
}

type h1 struct {
	XMLName xml.Name `xml:"h1"`
	Title   string   `xml:",innerxml"`
}

type polygon struct {
	XMLName xml.Name `xml:"polygon"`
	Points  []byte   `xml:"points,attr"`
	Style   string   `xml:"style,attr"`
}

type svgElement struct {
	XMLName  xml.Name `xml:"svg"`
	Width    float64  `xml:"width,attr"`
	Height   float64  `xml:"height,attr"`
	Polygons []polygon
}
<commit_msg>Fixed minor problems as per code review<commit_after>package som

import (
	"encoding/xml"
	"fmt"
	"io"
	"math"

	"github.com/gonum/matrix/mat64"
)

type rowWithDist struct {
	Row  int
	Dist float64
}

type h1 struct {
	XMLName xml.Name `xml:"h1"`
	Title   string   `xml:",innerxml"`
}

type polygon struct {
	XMLName xml.Name `xml:"polygon"`
	Points  []byte   `xml:"points,attr"`
	Style   string   `xml:"style,attr"`
}

type svgElement struct {
	XMLName  xml.Name `xml:"svg"`
	Width    float64  `xml:"width,attr"`
	Height   float64  `xml:"height,attr"`
	Polygons []polygon
}

// Creates an SVG representation of the U-Matrix of the given codebook.
// codebook is the codebook we're displaying the U-Matrix for,
// coordsDims are the dimensions of the grid,
// uShape is the shape of the grid,
// title is the title of the output SVG,
// and writer is the io.Writter to write the output SVG to.
func UMatrixSVG(codebook *mat64.Dense, coordsDims []int, uShape string, title string, writer io.Writer) error {
	xmlEncoder := xml.NewEncoder(writer)
	// array to hold the xml elements
	elems := []interface{}{h1{Title: title}}

	rows, _ := codebook.Dims()
	distMat, err := DistanceMx("euclidean", codebook)
	if err != nil {
		return err
	}
	coords, err := GridCoords(uShape, coordsDims)
	if err != nil {
		return err
	}
	coordsDistMat, err := DistanceMx("euclidean", coords)
	if err != nil {
		return err
	}

	// get maximum distance between codebook vectors
	// maximum distance will be rgb(0,0,0)
	maxDistance := mat64.Max(distMat)

	// function to scale the coord grid to something visible
	const MUL = 20.0
	const OFF = 10.0
	scale := func(x float64) float64 { return MUL*x + OFF }

	svgElem := svgElement{
		Width:    float64(coordsDims[1])*MUL + 2*OFF,
		Height:   float64(coordsDims[0])*MUL + 2*OFF,
		Polygons: make([]polygon, rows),
	}
	elems = append(elems, svgElem)
	for row := 0; row < rows; row++ {
		coord := coords.RowView(row)
		cbVec := codebook.RowView(row)
		avgDistance := 0.0
		// this is a rough approximation of the notion of neighbor grid coords
		allRowsInRadius := allRowsInRadius(row, math.Sqrt2*1.01, coordsDistMat)
		for _, rwd := range allRowsInRadius {
			if rwd.Dist > 0.0 {
				otherMu := codebook.RowView(rwd.Row)
				cbvDist, err := Distance("euclidean", cbVec, otherMu)
				if err != nil {
					return err
				}

				avgDistance += cbvDist
			}
		}
		avgDistance /= float64(len(allRowsInRadius) - 1)
		color := int((1.0 - avgDistance/maxDistance) * 255.0)
		polygonCoords := ""
		x := scale(coord.At(0, 0))
		y := scale(coord.At(1, 0))
		xOffset := 0.5 * MUL
		yOffset := 0.5 * MUL
		// hexagon has a different yOffset
		if uShape == "hexagon" {
			yOffset = math.Sqrt(0.75) / 2.0 * MUL
		}
		// draw a box around the current coord
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y+yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y-yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x-xOffset, y-yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x-xOffset, y+yOffset)
		polygonCoords += fmt.Sprintf("%f,%f ", x+xOffset, y+yOffset)

		svgElem.Polygons[row] = polygon{
			Points: []byte(polygonCoords),
			Style:  fmt.Sprintf("fill:rgb(%d,%d,%d);stroke:black;stroke-width:1", color, color, color),
		}
	}

	xmlEncoder.Encode(elems)
	xmlEncoder.Flush()

	return nil
}

func allRowsInRadius(selectedRow int, radius float64, distMatrix *mat64.Dense) []rowWithDist {
	rowsInRadius := []rowWithDist{}
	for i, dist := range distMatrix.RowView(selectedRow).RawVector().Data {
		if dist < radius {
			rowsInRadius = append(rowsInRadius, rowWithDist{Row: i, Dist: dist})
		}
	}
	return rowsInRadius
}
<|endoftext|>


<commit_before>// Copyright (C) 2012-2014 by krepa098. All rights reserved.
// Use of this source code is governed by a zlib-style
// license that can be found in the license.txt file.

package gosfml2

// #include <SFML/Audio/SoundBuffer.h>
// #include <stdlib.h>
// extern void copyData(void*, void*, size_t);
// extern size_t sizeofInt16();
import "C"

import (
	"errors"
	"runtime"
	"time"
	"unsafe"
)

//MISSING:
//			sfSoundBuffer_createFromStream

/////////////////////////////////////
///		STRUCTS
/////////////////////////////////////

type SoundBuffer struct {
	cptr *C.sfSoundBuffer
}

/////////////////////////////////////
///		FUNCS
/////////////////////////////////////

// Copy a C soundBuffer into a Go SoundBuffer
func newSoundBufferFromPtr(cbuffer *C.sfSoundBuffer) *SoundBuffer {
	buffer := &SoundBuffer{C.sfSoundBuffer_copy(cbuffer)}
	runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

	return buffer
}

// Create a new sound buffer and load it from a file
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
func NewSoundBufferFromFile(file string) (*SoundBuffer, error) {
	cFile := C.CString(file)
	defer C.free(unsafe.Pointer(cFile))

	if cptr := C.sfSoundBuffer_createFromFile(cFile); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}

	return nil, genericError
}

// Create a new sound buffer and load it from a file in memory
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
//
// 	data: Slice of file data
func NewSoundBufferFromMemory(data []byte) (*SoundBuffer, error) {
	if len(data) == 0 {
		return nil, errors.New("NewSoundBufferFromMemory: len(data)==0")
	}

	if cptr := C.sfSoundBuffer_createFromMemory(unsafe.Pointer(&data[0]), C.size_t(len(data))); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}

	return nil, genericError
}

// Create a new sound buffer and load it from an array of samples in memory
//
// The assumed format of the audio samples is 16 bits signed integer
// (int16).
//
// 	samples:      Slice of samples
// 	channelCount: Number of channels (1 = mono, 2 = stereo, ...)
// 	sampleRate:   Sample rate (number of samples to play per second)
func NewSoundBufferFromSamples(samples []int16, channelCount, sampleRate uint) (*SoundBuffer, error) {
	if len(samples) == 0 {
		return nil, errors.New("NewSoundBufferFromSamples: len(data)==0")
	}

	if cptr := C.sfSoundBuffer_createFromSamples((*C.sfInt16)(unsafe.Pointer(&samples[0])), C.size_t(len(samples)), C.uint(channelCount), C.uint(sampleRate)); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}
	return nil, genericError
}

// Create a new sound buffer by copying an existing one
func (this *SoundBuffer) Copy() *SoundBuffer {
	buffer := &SoundBuffer{C.sfSoundBuffer_copy(this.cptr)}
	runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)
	return buffer
}

// Destroy a sound buffer
func (this *SoundBuffer) destroy() {
	C.sfSoundBuffer_destroy(this.cptr)
}

// Save a sound buffer to an audio file
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
//
// 	file: Path of the sound file to write
func (this *SoundBuffer) SaveToFile(file string) {
	cFile := C.CString(file)
	defer C.free(unsafe.Pointer(cFile))

	C.sfSoundBuffer_saveToFile(this.cptr, cFile)
}

// Get the number of samples stored in a sound buffer
//
// The array of samples can be accessed with the
// SoundBuffer.GetSamples function.
func (this *SoundBuffer) GetSampleCount() uint {
	return uint(C.sfSoundBuffer_getSampleCount(this.cptr))
}

// Get the slice of audio samples stored in a sound buffer
//
// The format of the returned samples is 16 bits signed integer
// (int16).
func (this *SoundBuffer) GetSamples() []int16 {
	data := make([]int16, this.GetSampleCount())
	if len(data) > 0 {
		C.copyData(unsafe.Pointer(C.sfSoundBuffer_getSamples(this.cptr)), unsafe.Pointer(&data[0]), C.size_t(len(data))*C.sizeofInt16())
	}
	return data
}

// Get the sample rate of a sound buffer
//
// The sample rate is the number of samples played per second.
// The higher, the better the quality (for example, 44100
// samples/s is CD quality).
func (this *SoundBuffer) GetSampleRate() uint {
	return uint(C.sfSoundBuffer_getSampleRate(this.cptr))
}

// Get the number of channels used by a sound buffer
//
// If the sound is mono then the number of channels will
// be 1, 2 for stereo, etc.
func (this *SoundBuffer) GetChannelCount() uint {
	return uint(C.sfSoundBuffer_getChannelCount(this.cptr))
}

// Get the total duration of a sound buffer
func (this *SoundBuffer) GetDuration() time.Duration {
	return time.Duration(C.sfSoundBuffer_getDuration(this.cptr).microseconds) * time.Microsecond
}

/////////////////////////////////////
///		GO <-> C
/////////////////////////////////////

func (this *SoundBuffer) toCPtr() *C.sfSoundBuffer {
	if this != nil {
		return this.cptr
	}
	return nil
}
<commit_msg>improved error handling<commit_after>// Copyright (C) 2012-2014 by krepa098. All rights reserved.
// Use of this source code is governed by a zlib-style
// license that can be found in the license.txt file.

package gosfml2

// #include <SFML/Audio/SoundBuffer.h>
// #include <stdlib.h>
// extern void copyData(void*, void*, size_t);
// extern size_t sizeofInt16();
import "C"

import (
	"errors"
	"runtime"
	"time"
	"unsafe"
)

//MISSING:
//			sfSoundBuffer_createFromStream

/////////////////////////////////////
///		STRUCTS
/////////////////////////////////////

type SoundBuffer struct {
	cptr *C.sfSoundBuffer
}

/////////////////////////////////////
///		FUNCS
/////////////////////////////////////

// Copy a C soundBuffer into a Go SoundBuffer
func newSoundBufferFromPtr(cbuffer *C.sfSoundBuffer) *SoundBuffer {
	buffer := &SoundBuffer{C.sfSoundBuffer_copy(cbuffer)}
	runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

	return buffer
}

// Create a new sound buffer and load it from a file
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
func NewSoundBufferFromFile(file string) (*SoundBuffer, error) {
	cFile := C.CString(file)
	defer C.free(unsafe.Pointer(cFile))

	if cptr := C.sfSoundBuffer_createFromFile(cFile); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}

	return nil, genericError
}

// Create a new sound buffer and load it from a file in memory
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
//
// 	data: Slice of file data
func NewSoundBufferFromMemory(data []byte) (*SoundBuffer, error) {
	if len(data) == 0 {
		return nil, errors.New("NewSoundBufferFromMemory: len(data)==0")
	}

	if cptr := C.sfSoundBuffer_createFromMemory(unsafe.Pointer(&data[0]), C.size_t(len(data))); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}

	return nil, genericError
}

// Create a new sound buffer and load it from an array of samples in memory
//
// The assumed format of the audio samples is 16 bits signed integer
// (int16).
//
// 	samples:      Slice of samples
// 	channelCount: Number of channels (1 = mono, 2 = stereo, ...)
// 	sampleRate:   Sample rate (number of samples to play per second)
func NewSoundBufferFromSamples(samples []int16, channelCount, sampleRate uint) (*SoundBuffer, error) {
	if len(samples) == 0 {
		return nil, errors.New("NewSoundBufferFromSamples: len(data)==0")
	}

	if cptr := C.sfSoundBuffer_createFromSamples((*C.sfInt16)(unsafe.Pointer(&samples[0])), C.size_t(len(samples)), C.uint(channelCount), C.uint(sampleRate)); cptr != nil {
		buffer := &SoundBuffer{cptr}
		runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)

		return buffer, nil
	}
	return nil, genericError
}

// Create a new sound buffer by copying an existing one
func (this *SoundBuffer) Copy() *SoundBuffer {
	buffer := &SoundBuffer{C.sfSoundBuffer_copy(this.cptr)}
	runtime.SetFinalizer(buffer, (*SoundBuffer).destroy)
	return buffer
}

// Destroy a sound buffer
func (this *SoundBuffer) destroy() {
	C.sfSoundBuffer_destroy(this.cptr)
}

// Save a sound buffer to an audio file
//
// Here is a complete list of all the supported audio formats:
// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
//
// 	file: Path of the sound file to write
func (this *SoundBuffer) SaveToFile(file string) error {
	cFile := C.CString(file)
	defer C.free(unsafe.Pointer(cFile))

	if !sfBool2Go(C.sfSoundBuffer_saveToFile(this.cptr, cFile)) {
		return genericError
	}
	return nil
}

// Get the number of samples stored in a sound buffer
//
// The array of samples can be accessed with the
// SoundBuffer.GetSamples function.
func (this *SoundBuffer) GetSampleCount() uint {
	return uint(C.sfSoundBuffer_getSampleCount(this.cptr))
}

// Get the slice of audio samples stored in a sound buffer
//
// The format of the returned samples is 16 bits signed integer
// (int16).
func (this *SoundBuffer) GetSamples() []int16 {
	data := make([]int16, this.GetSampleCount())
	if len(data) > 0 {
		C.copyData(unsafe.Pointer(C.sfSoundBuffer_getSamples(this.cptr)), unsafe.Pointer(&data[0]), C.size_t(len(data))*C.sizeofInt16())
	}
	return data
}

// Get the sample rate of a sound buffer
//
// The sample rate is the number of samples played per second.
// The higher, the better the quality (for example, 44100
// samples/s is CD quality).
func (this *SoundBuffer) GetSampleRate() uint {
	return uint(C.sfSoundBuffer_getSampleRate(this.cptr))
}

// Get the number of channels used by a sound buffer
//
// If the sound is mono then the number of channels will
// be 1, 2 for stereo, etc.
func (this *SoundBuffer) GetChannelCount() uint {
	return uint(C.sfSoundBuffer_getChannelCount(this.cptr))
}

// Get the total duration of a sound buffer
func (this *SoundBuffer) GetDuration() time.Duration {
	return time.Duration(C.sfSoundBuffer_getDuration(this.cptr).microseconds) * time.Microsecond
}

/////////////////////////////////////
///		GO <-> C
/////////////////////////////////////

func (this *SoundBuffer) toCPtr() *C.sfSoundBuffer {
	if this != nil {
		return this.cptr
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	bindata "github.com/jteeuwen/go-bindata"
	v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1"
	controllergen "github.com/rancher/wrangler/pkg/controller-gen"
	"github.com/rancher/wrangler/pkg/controller-gen/args"
	"github.com/sirupsen/logrus"
)

var (
	basePackage = "github.com/rancher/k3s/types"
)

func main() {
	os.Unsetenv("GOPATH")
	bc := &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path:      "build/data",
				Recursive: true,
			},
		},
		Package:    "data",
		NoCompress: true,
		NoMemCopy:  true,
		NoMetadata: true,
		Output:     "pkg/data/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path: "manifests",
			},
		},
		Package:    "deploy",
		NoMetadata: true,
		Prefix:     "manifests/",
		Output:     "pkg/deploy/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path:      "build/static",
				Recursive: true,
			},
		},
		Package:    "static",
		NoMetadata: true,
		Prefix:     "build/static/",
		Output:     "pkg/static/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path: "vendor/k8s.io/kubernetes/openapi.json",
			},
			{
				Path: "vendor/k8s.io/kubernetes/openapi.pb",
			},
		},
		Package:    "openapi",
		NoMetadata: true,
		Prefix:     "vendor/k8s.io/kubernetes/",
		Output:     "pkg/openapi/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	controllergen.Run(args.Options{
		OutputPackage: "github.com/rancher/k3s/pkg/generated",
		Boilerplate:   "scripts/boilerplate.go.txt",
		Groups: map[string]args.Group{
			"k3s.cattle.io": {
				Types: []interface{}{
					v1.ListenerConfig{},
					v1.Addon{},
				},
				GenerateTypes: true,
			},
		},
	})
}
<commit_msg>Disable mock generation<commit_after>package main

import (
	"os"

	bindata "github.com/jteeuwen/go-bindata"
	v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1"
	controllergen "github.com/rancher/wrangler/pkg/controller-gen"
	"github.com/rancher/wrangler/pkg/controller-gen/args"
	"github.com/sirupsen/logrus"
)

var (
	basePackage = "github.com/rancher/k3s/types"
)

func main() {
	os.Unsetenv("GOPATH")
	bc := &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path:      "build/data",
				Recursive: true,
			},
		},
		Package:    "data",
		NoCompress: true,
		NoMemCopy:  true,
		NoMetadata: true,
		Output:     "pkg/data/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path: "manifests",
			},
		},
		Package:    "deploy",
		NoMetadata: true,
		Prefix:     "manifests/",
		Output:     "pkg/deploy/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path:      "build/static",
				Recursive: true,
			},
		},
		Package:    "static",
		NoMetadata: true,
		Prefix:     "build/static/",
		Output:     "pkg/static/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	bc = &bindata.Config{
		Input: []bindata.InputConfig{
			{
				Path: "vendor/k8s.io/kubernetes/openapi.json",
			},
			{
				Path: "vendor/k8s.io/kubernetes/openapi.pb",
			},
		},
		Package:    "openapi",
		NoMetadata: true,
		Prefix:     "vendor/k8s.io/kubernetes/",
		Output:     "pkg/openapi/zz_generated_bindata.go",
	}
	if err := bindata.Translate(bc); err != nil {
		logrus.Fatal(err)
	}

	controllergen.Run(args.Options{
		OutputPackage: "github.com/rancher/k3s/pkg/generated",
		Boilerplate:   "scripts/boilerplate.go.txt",
		Groups: map[string]args.Group{
			"k3s.cattle.io": {
				Types: []interface{}{
					v1.ListenerConfig{},
					v1.Addon{},
				},
				GenerateTypes: true,
			},
		},
		GenMocks: false,
	})
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package ipcache

import (
	"context"
	"fmt"
	"net"
	"strings"

	"github.com/sirupsen/logrus"

	"github.com/cilium/cilium/pkg/identity"
	"github.com/cilium/cilium/pkg/ip"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/labels/cidr"
	"github.com/cilium/cilium/pkg/logging/logfields"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/source"
)

// AllocateCIDRs attempts to allocate identities for a list of CIDRs. If any
// allocation fails, all allocations are rolled back and the error is returned.
// When an identity is freshly allocated for a CIDR, it is added to the
// ipcache if 'newlyAllocatedIdentities' is 'nil', otherwise the newly allocated
// identities are placed in 'newlyAllocatedIdentities' and it is the caller's
// responsibility to upsert them into ipcache by calling UpsertGeneratedIdentities().
//
// Previously used numeric identities for the given prefixes may be passed in as the
// 'oldNIDs' parameter; nil slice must be passed if no previous numeric identities exist.
// Previously used NID is allocated if still available. Non-availability is not an error.
//
// Upon success, the caller must also arrange for the resulting identities to
// be released via a subsequent call to ReleaseCIDRIdentitiesByCIDR().
func (ipc *IPCache) AllocateCIDRs(
	prefixes []*net.IPNet, oldNIDs []identity.NumericIdentity, newlyAllocatedIdentities map[string]*identity.Identity,
) ([]*identity.Identity, error) {
	// maintain list of used identities to undo on error
	usedIdentities := make([]*identity.Identity, 0, len(prefixes))

	// Maintain list of newly allocated identities to update ipcache,
	// but upsert them to ipcache only if no map was given by the caller.
	upsert := false
	if newlyAllocatedIdentities == nil {
		upsert = true
		newlyAllocatedIdentities = map[string]*identity.Identity{}
	}

	allocatedIdentities := make(map[string]*identity.Identity, len(prefixes))
	for i, p := range prefixes {
		if p == nil {
			continue
		}

		lbls := cidr.GetCIDRLabels(p)
		lbls.MergeLabels(ipc.GetIDMetadataByIP(p.IP.String()))
		oldNID := identity.InvalidIdentity
		if oldNIDs != nil && len(oldNIDs) > i {
			oldNID = oldNIDs[i]
		}
		id, isNew, err := ipc.allocate(p, lbls, oldNID)
		if err != nil {
			ipc.IdentityAllocator.ReleaseSlice(context.Background(), nil, usedIdentities)
			return nil, err
		}

		prefixStr := p.String()
		usedIdentities = append(usedIdentities, id)
		allocatedIdentities[prefixStr] = id
		if isNew {
			newlyAllocatedIdentities[prefixStr] = id
		}
	}

	// Only upsert into ipcache if identity wasn't allocated
	// before and the caller does not care doing this
	if upsert {
		ipc.UpsertGeneratedIdentities(newlyAllocatedIdentities)
	}

	identities := make([]*identity.Identity, 0, len(allocatedIdentities))
	for _, id := range allocatedIdentities {
		identities = append(identities, id)
	}
	return identities, nil
}

// AllocateCIDRsForIPs performs the same action as AllocateCIDRs but for IP
// addresses instead of CIDRs.
//
// Upon success, the caller must also arrange for the resulting identities to
// be released via a subsequent call to ReleaseCIDRIdentitiesByID().
func (ipc *IPCache) AllocateCIDRsForIPs(
	prefixes []net.IP, newlyAllocatedIdentities map[string]*identity.Identity,
) ([]*identity.Identity, error) {
	return ipc.AllocateCIDRs(ip.GetCIDRPrefixesFromIPs(prefixes), nil, newlyAllocatedIdentities)
}

func (ipc *IPCache) UpsertGeneratedIdentities(newlyAllocatedIdentities map[string]*identity.Identity) {
	for prefixString, id := range newlyAllocatedIdentities {
		ipc.Upsert(prefixString, nil, 0, nil, Identity{
			ID:     id.ID,
			Source: source.Generated,
		})
	}
}

// allocate will allocate a new identity for the given prefix based on the
// given set of labels. This function performs both global and local (CIDR)
// identity allocation and the set of labels determine which identity
// allocation type is to occur.
//
// If the identity is a CIDR identity, then its corresponding Identity will
// have its CIDR labels set correctly.
//
// A possible previously used numeric identity for these labels can be passed
// in as the 'oldNID' parameter; identity.InvalidIdentity must be passed if no
// previous numeric identity exists.
//
// It is up to the caller to provide the full set of labels for identity
// allocation.
func (ipc *IPCache) allocate(prefix *net.IPNet, lbls labels.Labels, oldNID identity.NumericIdentity) (*identity.Identity, bool, error) {
	if prefix == nil {
		return nil, false, nil
	}

	allocateCtx, cancel := context.WithTimeout(context.Background(), option.Config.IPAllocationTimeout)
	defer cancel()

	id, isNew, err := ipc.IdentityAllocator.AllocateIdentity(allocateCtx, lbls, false, oldNID)
	if err != nil {
		return nil, isNew, fmt.Errorf("failed to allocate identity for cidr %s: %s", prefix, err)
	}

	if lbls.Has(labels.LabelWorld[labels.IDNameWorld]) {
		id.CIDRLabel = labels.NewLabelsFromModel([]string{labels.LabelSourceCIDR + ":" + prefix.String()})
	}

	return id, isNew, err
}

func (ipc *IPCache) releaseCIDRIdentities(ctx context.Context, identities map[string]*identity.Identity) {
	for prefix, id := range identities {
		released, err := ipc.IdentityAllocator.Release(ctx, id, false)
		if err != nil {
			log.WithFields(logrus.Fields{
				logfields.Identity: id,
				logfields.CIDR:     prefix,
			}).WithError(err).Warning("Unable to release CIDR identity. Ignoring error. Identity may be leaked")
		}

		if released {
			ipc.Delete(prefix, source.Generated)
		}
	}
}

// ReleaseCIDRIdentitiesByCIDR releases the identities of a list of CIDRs.
// When the last use of the identity is released, the ipcache entry is deleted.
func (ipc *IPCache) ReleaseCIDRIdentitiesByCIDR(prefixes []*net.IPNet) {
	// TODO: Structure the code to pass context down from the Daemon.
	releaseCtx, cancel := context.WithTimeout(context.TODO(), option.Config.KVstoreConnectivityTimeout)
	defer cancel()

	identities := make(map[string]*identity.Identity, len(prefixes))
	for _, prefix := range prefixes {
		if prefix == nil {
			continue
		}

		if id := ipc.IdentityAllocator.LookupIdentity(releaseCtx, cidr.GetCIDRLabels(prefix)); id != nil {
			identities[prefix.String()] = id
		} else {
			log.Errorf("Unable to find identity of previously used CIDR %s", prefix.String())
		}
	}

	ipc.releaseCIDRIdentities(releaseCtx, identities)
}

// ReleaseCIDRIdentitiesByID releases the specified identities.
// When the last use of the identity is released, the ipcache entry is deleted.
func (ipc *IPCache) ReleaseCIDRIdentitiesByID(ctx context.Context, identities []identity.NumericIdentity) {
	fullIdentities := make(map[string]*identity.Identity, len(identities))
	for _, nid := range identities {
		if id := ipc.IdentityAllocator.LookupIdentityByID(ctx, nid); id != nil {
			cidr := id.CIDRLabel.String()
			if !strings.HasPrefix(cidr, labels.LabelSourceCIDR) {
				log.WithFields(logrus.Fields{
					logfields.Identity: nid,
					logfields.Labels:   id.Labels,
				}).Warn("Unexpected release of non-CIDR identity, will leak this identity. Please report this issue to the developers.")
				continue
			}
			fullIdentities[strings.TrimPrefix(cidr, labels.LabelSourceCIDR+":")] = id
		} else {
			log.WithFields(logrus.Fields{
				logfields.Identity: nid,
			}).Warn("Unexpected release of numeric identity that is no longer allocated")
		}
	}

	ipc.releaseCIDRIdentities(ctx, fullIdentities)
}
<commit_msg>ipcache: Fix race in identity/ipcache release<commit_after>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package ipcache

import (
	"context"
	"fmt"
	"net"
	"strings"

	"github.com/sirupsen/logrus"

	"github.com/cilium/cilium/pkg/identity"
	"github.com/cilium/cilium/pkg/ip"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/labels/cidr"
	"github.com/cilium/cilium/pkg/logging/logfields"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/source"
)

// AllocateCIDRs attempts to allocate identities for a list of CIDRs. If any
// allocation fails, all allocations are rolled back and the error is returned.
// When an identity is freshly allocated for a CIDR, it is added to the
// ipcache if 'newlyAllocatedIdentities' is 'nil', otherwise the newly allocated
// identities are placed in 'newlyAllocatedIdentities' and it is the caller's
// responsibility to upsert them into ipcache by calling UpsertGeneratedIdentities().
//
// Previously used numeric identities for the given prefixes may be passed in as the
// 'oldNIDs' parameter; nil slice must be passed if no previous numeric identities exist.
// Previously used NID is allocated if still available. Non-availability is not an error.
//
// Upon success, the caller must also arrange for the resulting identities to
// be released via a subsequent call to ReleaseCIDRIdentitiesByCIDR().
func (ipc *IPCache) AllocateCIDRs(
	prefixes []*net.IPNet, oldNIDs []identity.NumericIdentity, newlyAllocatedIdentities map[string]*identity.Identity,
) ([]*identity.Identity, error) {
	// maintain list of used identities to undo on error
	usedIdentities := make([]*identity.Identity, 0, len(prefixes))

	// Maintain list of newly allocated identities to update ipcache,
	// but upsert them to ipcache only if no map was given by the caller.
	upsert := false
	if newlyAllocatedIdentities == nil {
		upsert = true
		newlyAllocatedIdentities = map[string]*identity.Identity{}
	}

	ipc.Lock()
	allocatedIdentities := make(map[string]*identity.Identity, len(prefixes))
	for i, p := range prefixes {
		if p == nil {
			continue
		}

		lbls := cidr.GetCIDRLabels(p)
		lbls.MergeLabels(ipc.GetIDMetadataByIP(p.IP.String()))
		oldNID := identity.InvalidIdentity
		if oldNIDs != nil && len(oldNIDs) > i {
			oldNID = oldNIDs[i]
		}
		id, isNew, err := ipc.allocate(p, lbls, oldNID)
		if err != nil {
			ipc.IdentityAllocator.ReleaseSlice(context.Background(), nil, usedIdentities)
			return nil, err
		}

		prefixStr := p.String()
		usedIdentities = append(usedIdentities, id)
		allocatedIdentities[prefixStr] = id
		if isNew {
			newlyAllocatedIdentities[prefixStr] = id
		}
	}
	ipc.Unlock()

	// Only upsert into ipcache if identity wasn't allocated
	// before and the caller does not care doing this
	if upsert {
		ipc.UpsertGeneratedIdentities(newlyAllocatedIdentities)
	}

	identities := make([]*identity.Identity, 0, len(allocatedIdentities))
	for _, id := range allocatedIdentities {
		identities = append(identities, id)
	}
	return identities, nil
}

// AllocateCIDRsForIPs performs the same action as AllocateCIDRs but for IP
// addresses instead of CIDRs.
//
// Upon success, the caller must also arrange for the resulting identities to
// be released via a subsequent call to ReleaseCIDRIdentitiesByID().
func (ipc *IPCache) AllocateCIDRsForIPs(
	prefixes []net.IP, newlyAllocatedIdentities map[string]*identity.Identity,
) ([]*identity.Identity, error) {
	return ipc.AllocateCIDRs(ip.GetCIDRPrefixesFromIPs(prefixes), nil, newlyAllocatedIdentities)
}

func (ipc *IPCache) UpsertGeneratedIdentities(newlyAllocatedIdentities map[string]*identity.Identity) {
	for prefixString, id := range newlyAllocatedIdentities {
		ipc.Upsert(prefixString, nil, 0, nil, Identity{
			ID:     id.ID,
			Source: source.Generated,
		})
	}
}

// allocate will allocate a new identity for the given prefix based on the
// given set of labels. This function performs both global and local (CIDR)
// identity allocation and the set of labels determine which identity
// allocation type is to occur.
//
// If the identity is a CIDR identity, then its corresponding Identity will
// have its CIDR labels set correctly.
//
// A possible previously used numeric identity for these labels can be passed
// in as the 'oldNID' parameter; identity.InvalidIdentity must be passed if no
// previous numeric identity exists.
//
// It is up to the caller to provide the full set of labels for identity
// allocation.
func (ipc *IPCache) allocate(prefix *net.IPNet, lbls labels.Labels, oldNID identity.NumericIdentity) (*identity.Identity, bool, error) {
	if prefix == nil {
		return nil, false, nil
	}

	allocateCtx, cancel := context.WithTimeout(context.Background(), option.Config.IPAllocationTimeout)
	defer cancel()

	id, isNew, err := ipc.IdentityAllocator.AllocateIdentity(allocateCtx, lbls, false, oldNID)
	if err != nil {
		return nil, isNew, fmt.Errorf("failed to allocate identity for cidr %s: %s", prefix, err)
	}

	if lbls.Has(labels.LabelWorld[labels.IDNameWorld]) {
		id.CIDRLabel = labels.NewLabelsFromModel([]string{labels.LabelSourceCIDR + ":" + prefix.String()})
	}

	return id, isNew, err
}

func (ipc *IPCache) releaseCIDRIdentities(ctx context.Context, identities map[string]*identity.Identity) {
	// Create a critical section for identity release + removal from ipcache.
	// Otherwise, it's possible to trigger the following race condition:
	//
	// Goroutine 1                | Goroutine 2
	// releaseCIDRIdentities()    | AllocateCIDRs()
	// -> Release(..., id, ...)   |
	//                            | -> allocate(...)
	//                            | -> ipc.UpsertGeneratedIdentities(...)
	// -> ipc.deleteLocked(...)   |
	//
	// In this case, the expectation from Goroutine 2 is that an identity
	// is allocated and that identity is in the ipcache, but the result
	// is that the identity is allocated but the ipcache entry is missing.
	ipc.Lock()
	defer ipc.Unlock()
	for prefix, id := range identities {
		released, err := ipc.IdentityAllocator.Release(ctx, id, false)
		if err != nil {
			log.WithFields(logrus.Fields{
				logfields.Identity: id,
				logfields.CIDR:     prefix,
			}).WithError(err).Warning("Unable to release CIDR identity. Ignoring error. Identity may be leaked")
		}

		if released {
			ipc.deleteLocked(prefix, source.Generated)
		}
	}
}

// ReleaseCIDRIdentitiesByCIDR releases the identities of a list of CIDRs.
// When the last use of the identity is released, the ipcache entry is deleted.
func (ipc *IPCache) ReleaseCIDRIdentitiesByCIDR(prefixes []*net.IPNet) {
	// TODO: Structure the code to pass context down from the Daemon.
	releaseCtx, cancel := context.WithTimeout(context.TODO(), option.Config.KVstoreConnectivityTimeout)
	defer cancel()

	identities := make(map[string]*identity.Identity, len(prefixes))
	for _, prefix := range prefixes {
		if prefix == nil {
			continue
		}

		if id := ipc.IdentityAllocator.LookupIdentity(releaseCtx, cidr.GetCIDRLabels(prefix)); id != nil {
			identities[prefix.String()] = id
		} else {
			log.Errorf("Unable to find identity of previously used CIDR %s", prefix.String())
		}
	}

	ipc.releaseCIDRIdentities(releaseCtx, identities)
}

// ReleaseCIDRIdentitiesByID releases the specified identities.
// When the last use of the identity is released, the ipcache entry is deleted.
func (ipc *IPCache) ReleaseCIDRIdentitiesByID(ctx context.Context, identities []identity.NumericIdentity) {
	fullIdentities := make(map[string]*identity.Identity, len(identities))
	for _, nid := range identities {
		if id := ipc.IdentityAllocator.LookupIdentityByID(ctx, nid); id != nil {
			cidr := id.CIDRLabel.String()
			if !strings.HasPrefix(cidr, labels.LabelSourceCIDR) {
				log.WithFields(logrus.Fields{
					logfields.Identity: nid,
					logfields.Labels:   id.Labels,
				}).Warn("Unexpected release of non-CIDR identity, will leak this identity. Please report this issue to the developers.")
				continue
			}
			fullIdentities[strings.TrimPrefix(cidr, labels.LabelSourceCIDR+":")] = id
		} else {
			log.WithFields(logrus.Fields{
				logfields.Identity: nid,
			}).Warn("Unexpected release of numeric identity that is no longer allocated")
		}
	}

	ipc.releaseCIDRIdentities(ctx, fullIdentities)
}
<|endoftext|>