<commit_before>package instructor

import (
	"bufio"
	"bytes"
	"io"
)

// The approach in this file was lifted heavily from https://blog.gopheracademy.com/advent-2014/parsers-lexers/

// Token represents a lexical token.
type Token int

// Low level tokens - things looked for sepcifically by name in the interpreter
const (
	ILLEGAL Token = iota // 0
	EOF                  // 1: end of input
	WS                   // 2: spaces/tabs
)

// Operational tokens - things looked for by name, but are more meaningful
const (
	ASSIGN Token = 100 + iota // 100: assginment operator, =
	PERIOD                    // 101: .
	SQUOTE                    // 102: '
	DQUOTE                    // 103: "
	COMMA                     // 104: ,
	LPAREN                    // 105: (
	RPAREN                    // 106: )
	TICK                      // 107: `
	LBRACK                    // 108: [
	RBRACK                    // 109: ]
)

// Reserved words - special operators and functions, pre-defined by the "runtime"
const (
	WORD Token = 200 + iota // 200: Placeholder, should be unused
	FIND                    // 201: built in helper for locating structs, hacky
	ADD                     // 202: Addition operator
	SUB                     // 203: Subtraction operator
	DIV                     // 204: Division operator
	MULT                    // 205: Multiplication operator
	MOD                     // 206: Modulo operator
)

// Literal value and variable expression tokens
const (
	VARIABLE Token = 300 + iota // 300: Any literal value that isn't a reserved word - any string not starting with single/double/tick quotes
	FIELD                       // 301: Any string not starting with a single/double/stick quotes but preceeded by a period
	STRING                      // 302: Any literal string value
	NUMBER                      // 303: Any literal number, int or float
	RUNE                        // 304: Any literal rune value
	BOOL                        // 305: The keywords true or false
)

const eof = rune(0)

//var validChar = regexp.MustCompile("^[\pL\pN\p{Pc}]*$")

// Scanner is responsible for managing the parsing of a string of input text
type scanner struct {
	r *bufio.Reader
}

type tokenBuffer struct {
	t Token  // last token read
	l string //last literal read
	n int    // size
}

// Lexer is responsible for directly turning the parts of a string of input into tokens and text chunks
type lexer struct {
	s *scanner
	b tokenBuffer
}

// newScanner returns a new instance of the Lexical Scanner
func newScanner(r io.Reader) *scanner {
	return &scanner{
		r: bufio.NewReader(r),
	}
}

// NewLexer returns a new instance of the Parser
func newLexer(r io.Reader) *lexer {
	return &lexer{
		s: newScanner(r),
		b: tokenBuffer{},
	}
}

// read reads the next rune from the buffered reader
// If there is an eof or error, it returns rune(0), eof
func (s *scanner) read() rune {
	c, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return c
}

func (s *scanner) unread() {
	s.r.UnreadRune()
}

// Scan will scan the input text
func (s *scanner) Scan() fragment {
	// Read the next rune
	c := s.read()
	// Return quick if it's already the end of file
	if c == eof {
		return fragment{token: EOF, text: ""}
	}

	if isWhitespace(c) {
		// Rewind by 1, then consume the entire amout of whitespace
		s.unread()
		return s.scanWhitespace()
	} else if isLetter(c) {
		// Rewind by 1, then consume all of the contiguous letters /numbers to later check for a reserved word or variable name, or evaluate as a number
		s.unread()
		return s.scanWord()
	} else if c == '"' {
		// Scan a string which means not ignoring whitespace, until the closing quote
		// We expressly do not unread the double quote beginning the string, and we expressly chuck the double quote closing it
		return s.scanString('"')
	} else if c == '`' {
		// Scan a string which means not ignoring whitespace, until the closing tick
		// We expressly do not unread the tick beginning the string, and we expressly chuck the tick closing it
		// this case is mostly to support idiomatic entry of json
		return s.scanString('`')
	} else if c == '\'' {
		// Scan a rune which means until the closing quote
		// We expressly do not unread the single quote beginning the string, and we expressly chuck the single quote closing it
		return s.scanRune()
	} else if isDigit(c) {
		s.unread()
		return s.scanNumber()
	} else if c == '.' {
		// Scan a word until the next period, eof, or lparen
		return s.scanField()
	}

	// Otherwise, see what kind of token it was
	switch c {
	case '=':
		return fragment{token: ASSIGN, text: string(c)}
	case '.':
		return fragment{token: PERIOD, text: string(c)}
	case '(':
		return fragment{token: LPAREN, text: string(c)}
	case ',':
		return fragment{token: COMMA, text: string(c)}
	case ')':
		return fragment{token: RPAREN, text: string(c)}
	case '[':
		return fragment{token: LBRACK, text: string(c)}
	case ']':
		return fragment{token: RBRACK, text: string(c)}
	default:
		return fragment{token: WORD, text: string(c)}
	}
}

func (s *scanner) scanWhitespace() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find a non whitespace/eol character
	for {
		if c := s.read(); c == eof {
			break
		} else if !isWhitespace(c) {
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}
	return fragment{token: WS, text: b.String()}
}

func (s *scanner) scanNumber() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if !isDigit(c) && c != '.' { // Numbers can contain periods, as a special case, for floats/decimals
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	return fragment{token: NUMBER, text: b.String()}
}

func (s *scanner) scanString(boundaryRune rune) fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if c == boundaryRune { // Break once we encounter a closing quote or tick
			// We are going to chuck the closing quote, so we expressly do not rewind
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	return fragment{token: STRING, text: b.String()}
}

func (s *scanner) scanRune() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if c == '\'' { // Break once we encounter a closing quote
			// We are going to chuck the closing quote, so we expressly do not rewind
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	return fragment{token: RUNE, text: b.String()}
}

func (s *scanner) scanField() fragment {
	// Buffer in the current character, which should be a period
	b := bytes.Buffer{}
	b.WriteRune(s.read())

	for {
		if c := s.read(); c == eof {
			// It was the last field in the chain
			break
		} else if c == '.' || c == '(' || c == '[' {
			// end of this field, start of another.
			// or
			// end of the method name
			// unread so the next scan gets the period.
			s.unread()
			break
		} else {
			b.WriteRune(c)
		}
	}

	return fragment{token: FIELD, text: b.String()}
}

func (s *scanner) scanWord() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if !isLetter(c) && !isDigit(c) { // Words can have digits, but they can't start with them - need to enforce this
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	// Here is where we'd match a specific reserved word
	word := b.String()
	switch word {
	case "find":
		return fragment{token: FIND, text: word}
	case "true", "false":
		return fragment{token: BOOL, text: word}
	}
	return fragment{token: VARIABLE, text: word}
}

func (l *lexer) scan() fragment {
	// A token has been read, return it
	if l.b.n > 0 {
		l.b.n = 0
		return fragment{token: l.b.t, text: l.b.l}
	}
	// Otherwise, read one from the scanner and send it up
	return l.s.Scan()
}

// unscan pushes the previously read token back onto the buffer.
func (l *lexer) unscan() {
	l.b.n = 1
}

func (l *lexer) scanIgnoreWhitespace() fragment {
	f := l.scan()
	if f.token == WS {
		f = l.scan()
	}
	return f
}

func isWhitespace(c rune) bool {
	return c == ' ' || c == '\t'
}

func isLetter(c rune) bool {
	// Anything a-z, A-Z, or special characters
	// TODO replace this with a proper regex, willya?
	return (c >= 'a' && c < 'z') || (c >= 'A' && c <= 'Z') || c == '*'
}

func isDigit(c rune) bool {
	return (c >= '0' && c <= '9')
}
<commit_msg>More organization<commit_after>package instructor

import (
	"bufio"
	"bytes"
	"io"
	"strings"
)

// The approach in this file was lifted heavily from https://blog.gopheracademy.com/advent-2014/parsers-lexers/

// Token represents a lexical token.
type Token int

// Low level tokens - things looked for sepcifically by name in the interpreter
const (
	ILLEGAL Token = iota // 0
	EOF                  // 1: end of input
	WS                   // 2: spaces/tabs
)

// Operational tokens - things looked for by name, but are more meaningful
const (
	ASSIGN Token = 100 + iota // 100: assginment operator, =
	PERIOD                    // 101: .
	SQUOTE                    // 102: '
	DQUOTE                    // 103: "
	COMMA                     // 104: ,
	LPAREN                    // 105: (
	RPAREN                    // 106: )
	TICK                      // 107: `
	LBRACK                    // 108: [
	RBRACK                    // 109: ]
)

// Reserved words - special operators and functions, pre-defined by the "runtime"
const (
	WORD Token = 200 + iota // 200: Placeholder, should be unused
	FIND                    // 201: built in helper for locating structs, hacky
	ADD                     // 202: Addition operator
	SUB                     // 203: Subtraction operator
	DIV                     // 204: Division operator
	MULT                    // 205: Multiplication operator
	MOD                     // 206: Modulo operator
)

// Field and variable tokens
const (
	VARIABLE Token = 300 + iota // 300: Any literal value that isn't a reserved word - any string not starting with single/double/tick quotes
	FIELD                       // 301: Any string not starting with a single/double/stick quotes but preceeded by a period
)

// Literal value tokens
const (
	STRING Token = 400 + iota // 302: Any literal string value
	INT                       // 303: Any literal number without a decimal
	FLOAT                     // 304: Any literal number with a decimal
	RUNE                      // 305: Any literal rune value
	BOOL                      // 306: The keywords true or false
)

const eof = rune(0)

//var validChar = regexp.MustCompile("^[\pL\pN\p{Pc}]*$")

// Scanner is responsible for managing the parsing of a string of input text
type scanner struct {
	r *bufio.Reader
}

type tokenBuffer struct {
	t Token  // last token read
	l string // last literal read
	n int    // size
}

// Lexer is responsible for directly turning the parts of a string of input into tokens and text chunks
type lexer struct {
	s *scanner
	b tokenBuffer
}

// newScanner returns a new instance of the Lexical Scanner
func newScanner(r io.Reader) *scanner {
	return &scanner{
		r: bufio.NewReader(r),
	}
}

// NewLexer returns a new instance of the Parser
func newLexer(r io.Reader) *lexer {
	return &lexer{
		s: newScanner(r),
		b: tokenBuffer{},
	}
}

// read reads the next rune from the buffered reader
// If there is an eof or error, it returns rune(0), eof
func (s *scanner) read() rune {
	c, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return c
}

func (s *scanner) unread() {
	s.r.UnreadRune()
}

// Scan will scan the input text
func (s *scanner) Scan() fragment {
	// Read the next rune
	c := s.read()
	// Return quick if it's already the end of file
	if c == eof {
		return fragment{token: EOF, text: ""}
	}

	if isWhitespace(c) {
		// Rewind by 1, then consume the entire amout of whitespace
		s.unread()
		return s.scanWhitespace()
	} else if isLetter(c) {
		// Rewind by 1, then consume all of the contiguous letters /numbers to later check for a reserved word or variable name, or evaluate as a number
		s.unread()
		return s.scanWord()
	} else if c == '"' {
		// Scan a string which means not ignoring whitespace, until the closing quote
		// We expressly do not unread the double quote beginning the string, and we expressly chuck the double quote closing it
		return s.scanString('"')
	} else if c == '`' {
		// Scan a string which means not ignoring whitespace, until the closing tick
		// We expressly do not unread the tick beginning the string, and we expressly chuck the tick closing it
		// this case is mostly to support idiomatic entry of json
		return s.scanString('`')
	} else if c == '\'' {
		// Scan a rune which means until the closing quote
		// We expressly do not unread the single quote beginning the string, and we expressly chuck the single quote closing it
		return s.scanRune()
	} else if isDigit(c) {
		s.unread()
		return s.scanNumber()
	} else if c == '.' {
		// Scan a word until the next period, eof, or lparen
		return s.scanField()
	}

	// Otherwise, see what kind of token it was
	switch c {
	case '=':
		return fragment{token: ASSIGN, text: string(c)}
	case '.':
		return fragment{token: PERIOD, text: string(c)}
	case '(':
		return fragment{token: LPAREN, text: string(c)}
	case ',':
		return fragment{token: COMMA, text: string(c)}
	case ')':
		return fragment{token: RPAREN, text: string(c)}
	case '[':
		return fragment{token: LBRACK, text: string(c)}
	case ']':
		return fragment{token: RBRACK, text: string(c)}
	default:
		return fragment{token: WORD, text: string(c)}
	}
}

func (s *scanner) scanWhitespace() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find a non whitespace/eol character
	for {
		if c := s.read(); c == eof {
			break
		} else if !isWhitespace(c) {
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}
	return fragment{token: WS, text: b.String()}
}

func (s *scanner) scanNumber() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if !isDigit(c) && c != '.' { // Numbers can contain periods, as a special case, for floats/decimals
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	text := b.String()
	if strings.Contains(text, ".") {
		return fragment{token: FLOAT, text: b.String()}
	}
	return fragment{token: INT, text: b.String()}
}

func (s *scanner) scanString(boundaryRune rune) fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if c == boundaryRune { // Break once we encounter a closing quote or tick
			// We are going to chuck the closing quote, so we expressly do not rewind
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	return fragment{token: STRING, text: b.String()}
}

func (s *scanner) scanRune() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if c == '\'' { // Break once we encounter a closing quote
			// We are going to chuck the closing quote, so we expressly do not rewind
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	return fragment{token: RUNE, text: b.String()}
}

func (s *scanner) scanField() fragment {
	// Buffer in the current character, which should be a period
	b := bytes.Buffer{}
	b.WriteRune(s.read())

	for {
		if c := s.read(); c == eof {
			// It was the last field in the chain
			break
		} else if c == '.' || c == '(' || c == '[' || isWhitespace(c) {
			// end of this field, start of another.
			// or
			// end of the method name
			// or
			// end of the field prior to an assign or equality check
			// unread so the next scan gets the period.
			s.unread()
			break
		} else {
			b.WriteRune(c)
		}
	}

	return fragment{token: FIELD, text: b.String()}
}

func (s *scanner) scanWord() fragment {
	// Buffer for the current character
	b := bytes.Buffer{}
	b.WriteRune(s.read())
	// Keep going until we find something to stop us
	for {
		if c := s.read(); c == eof {
			break
		} else if !isLetter(c) && !isDigit(c) { // Words can have digits, but they can't start with them - need to enforce this
			// Rewind by one before exitting
			s.unread()
			break
		} else {
			// Straight pass through to the buffer
			b.WriteRune(c)
		}
	}

	// Here is where we'd match a specific reserved word
	word := b.String()
	switch word {
	case "find":
		return fragment{token: FIND, text: word}
	case "true", "false":
		return fragment{token: BOOL, text: word}
	}
	return fragment{token: VARIABLE, text: word}
}

func (l *lexer) scan() fragment {
	// A token has been read, return it
	if l.b.n > 0 {
		l.b.n = 0
		return fragment{token: l.b.t, text: l.b.l}
	}
	// Otherwise, read one from the scanner and send it up
	return l.s.Scan()
}

// unscan pushes the previously read token back onto the buffer.
func (l *lexer) unscan() {
	l.b.n = 1
}

func (l *lexer) scanIgnoreWhitespace() fragment {
	f := l.scan()
	if f.token == WS {
		f = l.scan()
	}
	return f
}

func isWhitespace(c rune) bool {
	return c == ' ' || c == '\t'
}

func isLetter(c rune) bool {
	// Anything a-z, A-Z, or special characters
	// TODO replace this with a proper regex, willya?
	return (c >= 'a' && c < 'z') || (c >= 'A' && c <= 'Z') || c == '*'
}

func isDigit(c rune) bool {
	return (c >= '0' && c <= '9')
}
<|endoftext|>


<commit_before>package lg

import (
	"net/http"
	"net/http/httputil"

	"github.com/mgutz/logxi/v1"
)

func Fatal(msg string, args ...interface{}) {
	log.Fatal(msg, args...)
}

func Warn(msg string, args ...interface{}) {
	log.Warn(msg, args...)
}

func Info(msg string, args ...interface{}) {
	log.Info(msg, args...)
}

func Debug(msg string, args ...interface{}) {
	log.Debug(msg, args...)
}

func Check(err error, args ...interface{}) {
	if err != nil {
		log.Fatal(err.Error(), args...)
	}
}

func Response(r *http.Response) {
	b, _ := httputil.DumpResponse(r, true)

	log.Debug(string(b))
}

type F map[string]interface{}

func (f F) Args() []interface{} {
	var args []interface{}

	for k, v := range f {
		args = append(args, k, v)
	}

	return args
}
<commit_msg>Logger<commit_after>package lg

import "net/http"

var DefaultLog *Logger

func init() {
	DefaultLog = New("~")
}

func Fatal(msg string, args ...interface{}) {
	DefaultLog.Fatal(msg, args...)
}

func Warn(msg string, args ...interface{}) {
	DefaultLog.Warn(msg, args...)
}

func Info(msg string, args ...interface{}) {
	DefaultLog.Info(msg, args...)
}

func Debug(msg string, args ...interface{}) {
	DefaultLog.Debug(msg, args...)
}

func Check(err error, args ...interface{}) {
	if err != nil {
		DefaultLog.Fatal(err.Error(), args...)
	}
}

func Response(r *http.Response) {
	DefaultLog.Response(r)
}

type F map[string]interface{}

func (f F) Args() []interface{} {
	var args []interface{}

	for k, v := range f {
		args = append(args, k, v)
	}

	return args
}
<|endoftext|>


<commit_before>package base

import (
	"fmt"
	"log"
)

var logBuffer chan string

func init() {
	logBuffer = make(chan string, 100000)

	go logger()
}

func Log(format string, values ...interface{}) {

	logBuffer <- fmt.Sprintf(format, values...)
}

func logger() {
	for {
		log.Printf(<-logBuffer)
	}
}
<commit_msg>logging to a file, maybe?<commit_after>package base

import (
	"errors"
	"fmt"
	"log"
	"os"

	"github.com/fatih/color"
)

var logBuffer chan string

func init() {
	logBuffer = make(chan string, 100000)

	go logger()
}

func Log(format string, values ...interface{}) {

	logBuffer <- fmt.Sprintf(format, values...)
}

func logger() {

	if len(os.Getenv("DEBUG_LOGS")) == 0 {
		f, err := os.OpenFile("/log.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			msg := fmt.Sprintf("Couldn't open log file: %s", err)
			log.Printf(color.HiRedString(msg))
			panic(errors.New(msg))
		}
		defer f.Close()
		log.SetOutput(f)
	}

	for {
		log.Printf(<-logBuffer)
	}
}
<|endoftext|>


<commit_before>package hmc5883l
import "b00lduck/datalogger/display/i2c"

const (
	ADDR          		= 0x1E
	REGISTER_A			= 0x00
	REGISTER_A_VALUE    = 0x10
	REGISTER_B			= 0x01
	REGISTER_B_VALUE	= 0x20
	REGISTER_MODE		= 0x02
	REGISTER_MODE_VALUE	= 0x00
	REGISTER_X			= 0x03
	REGISTER_Y			= 0x07
	REGISTER_Z			= 0x05
)

type HMC5883LI2C struct {
	bus *i2c.I2CBus
}

type Vector3 struct {
	X,Y,Z int16
}

func CreateHMC5883LI2c(busId byte) (dev *HMC5883LI2C, err error) {

	devI2c := new(HMC5883LI2C)

	devI2c.bus, err = i2c.Create(busId)
	if err != nil {
		return nil, err
	}

	devI2c.config()
	if err != nil {
		return nil, err
	}

	return devI2c, nil
}

func (dev *HMC5883LI2C) config() (err error) {
	err = dev.Write(REGISTER_A, REGISTER_A_VALUE)
	if err != nil {
		return
	}

	err = dev.Write(REGISTER_B, REGISTER_B_VALUE)
	if err != nil {
		return
	}

	err = dev.Write(REGISTER_MODE, REGISTER_MODE_VALUE)
	if err != nil {
		return
	}
	return
}

func (dev *HMC5883LI2C) ReadVector() (vector *Vector3, err error) {
	vector = new(Vector3)
	vector.X, err = dev.Read16(REGISTER_X)
	if err != nil {
		return
	}
	vector.Y, err = dev.Read16(REGISTER_Y)
	if err != nil {
		return
	}
	vector.Z, err = dev.Read16(REGISTER_Z)
	if err != nil {
		return
	}
	return
}

func (dev *HMC5883LI2C) Read16(reg byte) (int16, error) {

	msb, err := dev.Read(reg)
	if err != nil {
		return 0, err
	}

	lsb, err := dev.Read(reg + 1)
	if err != nil {
		return 0, err
	}

	return int16(lsb) * 0x100 + int16(msb), err
}

func (dev *HMC5883LI2C) Read(reg byte) (ret int8, err error) {
	var bytes []byte
	bytes, err = dev.bus.ReadByteBlock(ADDR, reg, 1)
	ret = int8(bytes[0])
	return
}

func (dev *HMC5883LI2C) Write(reg byte, value byte) (err error) {
	err = dev.bus.WriteByte(ADDR, reg, value)
	if err != nil {
		return
	}
	return
}<commit_msg>DISPLAY: valuefix<commit_after>package hmc5883l
import (
	"b00lduck/datalogger/display/i2c"
	"unsafe"
)

const (
	ADDR          		= 0x1E
	REGISTER_A			= 0x00
	REGISTER_A_VALUE    = 0x10
	REGISTER_B			= 0x01
	REGISTER_B_VALUE	= 0x20
	REGISTER_MODE		= 0x02
	REGISTER_MODE_VALUE	= 0x00
	REGISTER_X			= 0x03
	REGISTER_Y			= 0x07
	REGISTER_Z			= 0x05
)

type HMC5883LI2C struct {
	bus *i2c.I2CBus
}

type Vector3 struct {
	X,Y,Z int16
}

func CreateHMC5883LI2c(busId byte) (dev *HMC5883LI2C, err error) {

	devI2c := new(HMC5883LI2C)

	devI2c.bus, err = i2c.Create(busId)
	if err != nil {
		return nil, err
	}

	devI2c.config()
	if err != nil {
		return nil, err
	}

	return devI2c, nil
}

func (dev *HMC5883LI2C) config() (err error) {
	err = dev.Write(REGISTER_A, REGISTER_A_VALUE)
	if err != nil {
		return
	}

	err = dev.Write(REGISTER_B, REGISTER_B_VALUE)
	if err != nil {
		return
	}

	err = dev.Write(REGISTER_MODE, REGISTER_MODE_VALUE)
	if err != nil {
		return
	}
	return
}

func (dev *HMC5883LI2C) ReadVector() (vector *Vector3, err error) {
	vector = new(Vector3)
	vector.X, err = dev.Read16(REGISTER_X)
	if err != nil {
		return
	}
	vector.Y, err = dev.Read16(REGISTER_Y)
	if err != nil {
		return
	}
	vector.Z, err = dev.Read16(REGISTER_Z)
	if err != nil {
		return
	}
	return
}

func (dev *HMC5883LI2C) Read16(reg byte) (int16, error) {

	msb, err := dev.Read(reg)
	if err != nil {
		return 0, err
	}

	lsb, err := dev.Read(reg + 1)
	if err != nil {
		return 0, err
	}

	var x uint16 = uint16(lsb) + uint16(msb) << 8

	px := unsafe.Pointer(&x)

	pxs := (*int16)(px)

	return int16(*pxs), nil
}

func (dev *HMC5883LI2C) Read(reg byte) (ret int8, err error) {
	var bytes []byte
	bytes, err = dev.bus.ReadByteBlock(ADDR, reg, 1)
	ret = int8(bytes[0])
	return
}

func (dev *HMC5883LI2C) Write(reg byte, value byte) (err error) {
	err = dev.bus.WriteByte(ADDR, reg, value)
	if err != nil {
		return
	}
	return
}<|endoftext|>


<commit_before>// Package cloudflare is a store implementation backed by cloudflare workers kv
// Note that the cloudflare workers KV API is eventually consistent.
package cloudflare

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/micro/go-micro/config/options"
	"github.com/micro/go-micro/store"
	"github.com/pkg/errors"
)

const apiBaseURL = "https://api.cloudflare.com/client/v4/"

type workersKV struct {
	options.Options
	httpClient *http.Client
}

// New returns a cloudflare Store implementation.
// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV,
// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and
// KV_NAMESPACE_ID to contain the namespace UUID for your KV storage.
func NewStore(opts ...options.Option) (store.Store, error) {
	// Validate Options
	options := options.NewOptions(opts...)
	apiToken, ok := options.Values().Get("CF_API_TOKEN")
	if !ok {
		log.Fatal("Store: No CF_API_TOKEN passed as an option")
	}
	_, ok = apiToken.(string)
	if !ok {
		log.Fatal("Store: Option CF_API_TOKEN contains a non-string")
	}
	accountID, ok := options.Values().Get("CF_ACCOUNT_ID")
	if !ok {
		log.Fatal("Store: No CF_ACCOUNT_ID passed as an option")
	}
	_, ok = accountID.(string)
	if !ok {
		log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string")
	}
	uuid, ok := options.Values().Get("KV_NAMESPACE_ID")
	if !ok {
		log.Fatal("Store: No KV_NAMESPACE_ID passed as an option")
	}
	_, ok = uuid.(string)
	if !ok {
		log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string")
	}

	return &workersKV{
		Options:    options,
		httpClient: &http.Client{},
	}, nil
}

// In the cloudflare workers KV implemention, List() doesn't guarantee
// anything as the workers API is eventually consistent.
func (w *workersKV) List() ([]*store.Record, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID")
	kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID")

	path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/keys", accountID.(string), kvID.(string))
	response, _, _, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header))
	if err != nil {
		return nil, err
	}
	a := &apiResponse{}
	if err := json.Unmarshal(response, a); err != nil {
		return nil, err
	}
	if !a.Success {
		messages := ""
		for _, m := range a.Errors {
			messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
		}
		return nil, errors.New(messages)
	}

	var keys []string
	for _, r := range a.Result {
		keys = append(keys, r.Name)
	}
	return w.Read(keys...)
}

func (w *workersKV) Read(keys ...string) ([]*store.Record, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID")
	kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID")

	var records []*store.Record
	for _, k := range keys {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k))
		response, headers, status, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header))
		if err != nil {
			return records, err
		}
		if status < 200 || status >= 300 {
			return records, errors.New("Received unexpected Status " + strconv.Itoa(status) + string(response))
		}
		record := &store.Record{
			Key:   k,
			Value: response,
		}
		if expiry := headers.Get("Expiration"); len(expiry) != 0 {
			expiryUnix, err := strconv.ParseInt(expiry, 10, 64)
			if err != nil {
				return records, err
			}
			record.Expiry = time.Until(time.Unix(expiryUnix, 0))
		}
		records = append(records, record)
	}
	return records, nil
}

func (w *workersKV) Write(records ...*store.Record) error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID")
	kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID")

	for _, r := range records {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(r.Key))
		if r.Expiry != 0 {
			// Minimum cloudflare TTL is 60 Seconds
			exp := int(math.Max(60, math.Round(r.Expiry.Seconds())))
			path = path + "?expiration_ttl=" + strconv.Itoa(exp)
		}
		headers := make(http.Header)
		resp, _, _, err := w.request(ctx, http.MethodPut, path, r.Value, headers)
		if err != nil {
			return err
		}
		a := &apiResponse{}
		if err := json.Unmarshal(resp, a); err != nil {
			return err
		}
		if !a.Success {
			messages := ""
			for _, m := range a.Errors {
				messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
			}
			return errors.New(messages)
		}
	}
	return nil
}

func (w *workersKV) Delete(keys ...string) error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	accountID, _ := w.Options.Values().Get("CF_ACCOUNT_ID")
	kvID, _ := w.Options.Values().Get("KV_NAMESPACE_ID")

	for _, k := range keys {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", accountID.(string), kvID.(string), url.PathEscape(k))
		resp, _, _, err := w.request(ctx, http.MethodDelete, path, nil, make(http.Header))
		if err != nil {
			return err
		}

		a := &apiResponse{}
		if err := json.Unmarshal(resp, a); err != nil {
			return err
		}
		if !a.Success {
			messages := ""
			for _, m := range a.Errors {
				messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
			}
			return errors.New(messages)
		}
	}
	return nil
}

func (w *workersKV) request(ctx context.Context, method, path string, body interface{}, headers http.Header) ([]byte, http.Header, int, error) {
	var jsonBody []byte
	var err error

	if body != nil {
		if paramBytes, ok := body.([]byte); ok {
			jsonBody = paramBytes
		} else {
			jsonBody, err = json.Marshal(body)
			if err != nil {
				return nil, nil, 0, errors.Wrap(err, "error marshalling params to JSON")
			}
		}
	} else {
		jsonBody = nil
	}
	var reqBody io.Reader
	if jsonBody != nil {
		reqBody = bytes.NewReader(jsonBody)
	}
	req, err := http.NewRequestWithContext(ctx, method, apiBaseURL+path, reqBody)
	for key, value := range headers {
		req.Header[key] = value
	}
	if token, found := w.Options.Values().Get("CF_API_TOKEN"); found {
		req.Header.Set("Authorization", "Bearer "+token.(string))
	}
	req.Header.Set("User-Agent", "micro/1.0 (https://micro.mu)")

	// Official cloudflare client does exponential backoff here
	resp, err := w.httpClient.Do(req)
	if err != nil {
		return nil, nil, 0, err
	}
	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return respBody, resp.Header, resp.StatusCode, err
	}
	return respBody, resp.Header, resp.StatusCode, nil
}

// apiResponse is a cloudflare v4 api response
type apiResponse struct {
	Result []struct {
		ID         string    `json:"id"`
		Type       string    `json:"type"`
		Name       string    `json:"name"`
		Expiration string    `json:"expiration"`
		Content    string    `json:"content"`
		Proxiable  bool      `json:"proxiable"`
		Proxied    bool      `json:"proxied"`
		TTL        int       `json:"ttl"`
		Priority   int       `json:"priority"`
		Locked     bool      `json:"locked"`
		ZoneID     string    `json:"zone_id"`
		ZoneName   string    `json:"zone_name"`
		ModifiedOn time.Time `json:"modified_on"`
		CreatedOn  time.Time `json:"created_on"`
	} `json:"result"`
	Success bool         `json:"success"`
	Errors  []apiMessage `json:"errors"`
	// not sure Messages is ever populated?
	Messages   []apiMessage `json:"messages"`
	ResultInfo struct {
		Page       int `json:"page"`
		PerPage    int `json:"per_page"`
		Count      int `json:"count"`
		TotalCount int `json:"total_count"`
	} `json:"result_info"`
}

// apiMessage is a Cloudflare v4 API Error
type apiMessage struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}
<commit_msg>Don't recall vals everywhere<commit_after>// Package cloudflare is a store implementation backed by cloudflare workers kv
// Note that the cloudflare workers KV API is eventually consistent.
package cloudflare

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/micro/go-micro/config/options"
	"github.com/micro/go-micro/store"
	"github.com/pkg/errors"
)

const apiBaseURL = "https://api.cloudflare.com/client/v4/"

type workersKV struct {
	options.Options
	// cf account id
	account string
	// cf api token
	token string
	// cf kv namespace
	namespace string
	// http client to use
	httpClient *http.Client
}

// New returns a cloudflare Store implementation.
// Options expects CF_API_TOKEN to a cloudflare API token scoped to Workers KV,
// CF_ACCOUNT_ID to contain a string with your cloudflare account ID and
// KV_NAMESPACE_ID to contain the namespace UUID for your KV storage.
func NewStore(opts ...options.Option) (store.Store, error) {
	// Validate Options
	options := options.NewOptions(opts...)

	var account, token, namespace string

	apiToken, ok := options.Values().Get("CF_API_TOKEN")
	if !ok {
		log.Fatal("Store: No CF_API_TOKEN passed as an option")
	}
	if token, ok = apiToken.(string); !ok {
		log.Fatal("Store: Option CF_API_TOKEN contains a non-string")
	}

	accountID, ok := options.Values().Get("CF_ACCOUNT_ID")
	if !ok {
		log.Fatal("Store: No CF_ACCOUNT_ID passed as an option")
	}
	if account, ok = accountID.(string); !ok {
		log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string")
	}

	uuid, ok := options.Values().Get("KV_NAMESPACE_ID")
	if !ok {
		log.Fatal("Store: No KV_NAMESPACE_ID passed as an option")
	}
	if namespace, ok = uuid.(string); !ok {
		log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string")
	}

	return &workersKV{
		account:    account,
		namespace:  namespace,
		token:      token,
		Options:    options,
		httpClient: &http.Client{},
	}, nil
}

// In the cloudflare workers KV implemention, List() doesn't guarantee
// anything as the workers API is eventually consistent.
func (w *workersKV) List() ([]*store.Record, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/keys", w.account, w.namespace)

	response, _, _, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header))
	if err != nil {
		return nil, err
	}

	a := &apiResponse{}
	if err := json.Unmarshal(response, a); err != nil {
		return nil, err
	}

	if !a.Success {
		messages := ""
		for _, m := range a.Errors {
			messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
		}
		return nil, errors.New(messages)
	}

	var keys []string

	for _, r := range a.Result {
		keys = append(keys, r.Name)
	}

	return w.Read(keys...)
}

func (w *workersKV) Read(keys ...string) ([]*store.Record, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	var records []*store.Record

	for _, k := range keys {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(k))
		response, headers, status, err := w.request(ctx, http.MethodGet, path, nil, make(http.Header))
		if err != nil {
			return records, err
		}
		if status < 200 || status >= 300 {
			return records, errors.New("Received unexpected Status " + strconv.Itoa(status) + string(response))
		}
		record := &store.Record{
			Key:   k,
			Value: response,
		}
		if expiry := headers.Get("Expiration"); len(expiry) != 0 {
			expiryUnix, err := strconv.ParseInt(expiry, 10, 64)
			if err != nil {
				return records, err
			}
			record.Expiry = time.Until(time.Unix(expiryUnix, 0))
		}
		records = append(records, record)
	}

	return records, nil
}

func (w *workersKV) Write(records ...*store.Record) error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	for _, r := range records {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(r.Key))
		if r.Expiry != 0 {
			// Minimum cloudflare TTL is 60 Seconds
			exp := int(math.Max(60, math.Round(r.Expiry.Seconds())))
			path = path + "?expiration_ttl=" + strconv.Itoa(exp)
		}

		headers := make(http.Header)

		resp, _, _, err := w.request(ctx, http.MethodPut, path, r.Value, headers)
		if err != nil {
			return err
		}

		a := &apiResponse{}
		if err := json.Unmarshal(resp, a); err != nil {
			return err
		}

		if !a.Success {
			messages := ""
			for _, m := range a.Errors {
				messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
			}
			return errors.New(messages)
		}
	}

	return nil
}

func (w *workersKV) Delete(keys ...string) error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	for _, k := range keys {
		path := fmt.Sprintf("accounts/%s/storage/kv/namespaces/%s/values/%s", w.account, w.namespace, url.PathEscape(k))
		resp, _, _, err := w.request(ctx, http.MethodDelete, path, nil, make(http.Header))
		if err != nil {
			return err
		}

		a := &apiResponse{}
		if err := json.Unmarshal(resp, a); err != nil {
			return err
		}

		if !a.Success {
			messages := ""
			for _, m := range a.Errors {
				messages += strconv.Itoa(m.Code) + " " + m.Message + "\n"
			}
			return errors.New(messages)
		}
	}

	return nil
}

func (w *workersKV) request(ctx context.Context, method, path string, body interface{}, headers http.Header) ([]byte, http.Header, int, error) {
	var jsonBody []byte
	var err error

	if body != nil {
		if paramBytes, ok := body.([]byte); ok {
			jsonBody = paramBytes
		} else {
			jsonBody, err = json.Marshal(body)
			if err != nil {
				return nil, nil, 0, errors.Wrap(err, "error marshalling params to JSON")
			}
		}
	} else {
		jsonBody = nil
	}

	var reqBody io.Reader

	if jsonBody != nil {
		reqBody = bytes.NewReader(jsonBody)
	}

	req, err := http.NewRequestWithContext(ctx, method, apiBaseURL+path, reqBody)
	for key, value := range headers {
		req.Header[key] = value
	}

	// set token if it exists
	if len(w.token) > 0 {
		req.Header.Set("Authorization", "Bearer "+w.token)
	}

	// set the user agent to micro
	req.Header.Set("User-Agent", "micro/1.0 (https://micro.mu)")

	// Official cloudflare client does exponential backoff here
	// TODO: retry and use util/backoff
	resp, err := w.httpClient.Do(req)
	if err != nil {
		return nil, nil, 0, err
	}
	defer resp.Body.Close()

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

	return respBody, resp.Header, resp.StatusCode, nil
}

// apiResponse is a cloudflare v4 api response
type apiResponse struct {
	Result []struct {
		ID         string    `json:"id"`
		Type       string    `json:"type"`
		Name       string    `json:"name"`
		Expiration string    `json:"expiration"`
		Content    string    `json:"content"`
		Proxiable  bool      `json:"proxiable"`
		Proxied    bool      `json:"proxied"`
		TTL        int       `json:"ttl"`
		Priority   int       `json:"priority"`
		Locked     bool      `json:"locked"`
		ZoneID     string    `json:"zone_id"`
		ZoneName   string    `json:"zone_name"`
		ModifiedOn time.Time `json:"modified_on"`
		CreatedOn  time.Time `json:"created_on"`
	} `json:"result"`
	Success bool         `json:"success"`
	Errors  []apiMessage `json:"errors"`
	// not sure Messages is ever populated?
	Messages   []apiMessage `json:"messages"`
	ResultInfo struct {
		Page       int `json:"page"`
		PerPage    int `json:"per_page"`
		Count      int `json:"count"`
		TotalCount int `json:"total_count"`
	} `json:"result_info"`
}

// apiMessage is a Cloudflare v4 API Error
type apiMessage struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}
<|endoftext|>


<commit_before>package mp3

import (
	"bufio"
	"io"
)

type MP3 struct {
	r     *bufio.Reader
	frame *Frame
	err   error
}

func New(r io.Reader) (*MP3, error) {
	m := &MP3{
		r: bufio.NewReader(r),
	}
	b, err := m.r.Peek(10)
	if err != nil {
		return nil, err
	}
	if b[0] == 'I' && b[1] == 'D' && b[2] == '3' && b[3] < 0xff && b[4] < 0xff && b[6] < 0x80 && b[7] < 0x80 && b[8] < 0x80 && b[9] < 0x80 {
		var sz uint32
		sz = uint32(b[9] & 0x7f)
		sz += uint32(b[8]&0x7f) << 7
		sz += uint32(b[7]&0x7f) << 14
		sz += uint32(b[6]&0x7f) << 21
		sz += uint32(len(b))
		for ; sz > 0; sz-- {
			if _, err := m.r.ReadByte(); err != nil {
				return nil, err
			}
		}
	}
	return m, nil
}

func (m *MP3) Scan() bool {
	pos := 0
	var f Frame
	for {
		b, err := m.r.ReadByte()
		if err != nil {
			m.err = err
			return false
		}
		switch pos {
		case 0:
			if b == 0xff {
				pos++
			}
		case 1:
			if b&0xe0 == 0 {
				pos = 0
				break
			}
			pos++
			f = Frame{
				Version: Version(b & 0x18 >> 3),
				Layer:   Layer(b & 0x6 >> 1),
				CRC:     b&0x1 != 0,
			}
		case 2:
			pos++
			f.Bitrate = Bitrate(b & 0xf0 >> 4)
			f.Sampling = Sampling(b & 0xc >> 2)
			f.Padding = b&0x2 != 0
		case 3:
			f.Mode = Mode(b & 0xc >> 4)
			f.Emphasis = Emphasis(b & 0x3)
			if !f.Valid() {
				pos = 0
				break
			}
			m.frame = &f
			return true
		default:
			pos = 0
		}
	}
}

func (m *MP3) Err() error {
	if m.err == io.EOF {
		return nil
	}
	return m.err
}

func (m *MP3) Frame() *Frame {
	return m.frame
}

type Frame struct {
	Version
	Layer
	CRC bool
	Bitrate
	Sampling
	Padding bool
	Mode
	Emphasis
}

func (f *Frame) Valid() bool {
	if f.Version != MPEG1 {
		return false
	}
	if f.Layer != LayerI {
		return false
	}
	if f.Bitrate == 0xff || f.Bitrate == 0 {
		return false
	}
	return true
}

type Version byte

const (
	MPEG1 Version = 3
	MPEG2         = 2
)

type Layer byte

const (
	LayerI   Layer = 3
	LayerII        = 2
	LayerIII       = 1
)

type Bitrate byte

type Sampling byte

type Mode byte

const (
	ModeStereo Mode = 0
	ModeJoint       = 1
	ModeDual        = 2
	ModeSingle      = 3
)

type Emphasis byte

const (
	EmphasisNone  Emphasis = 0
	Emphasis50_15          = 1
	EmphasisCCIT           = 3
)
<commit_msg>Peek instead of read so we can check each byte<commit_after>package mp3

import (
	"bufio"
	"io"
)

type MP3 struct {
	r     *bufio.Reader
	frame *Frame
	err   error
}

func New(r io.Reader) (*MP3, error) {
	m := &MP3{
		r: bufio.NewReader(r),
	}
	b, err := m.r.Peek(10)
	if err != nil {
		return nil, err
	}
	if b[0] == 'I' && b[1] == 'D' && b[2] == '3' && b[3] < 0xff && b[4] < 0xff && b[6] < 0x80 && b[7] < 0x80 && b[8] < 0x80 && b[9] < 0x80 {
		var sz uint32
		sz = uint32(b[9] & 0x7f)
		sz += uint32(b[8]&0x7f) << 7
		sz += uint32(b[7]&0x7f) << 14
		sz += uint32(b[6]&0x7f) << 21
		sz += uint32(len(b))
		for ; sz > 0; sz-- {
			if _, err := m.r.ReadByte(); err != nil {
				return nil, err
			}
		}
	}
	return m, nil
}

func (m *MP3) Scan() bool {
	var f Frame
	for {
		b, err := m.r.Peek(4)
		if err != nil {
			m.err = err
			return false
		}
		switch b[0] {
		case 0xff:
			if b[1]&0xe0 != 0xe0 {
				break
			}
			f = Frame{
				Version:  Version(b[1] & 0x18 >> 3),
				Layer:    Layer(b[1] & 0x6 >> 1),
				CRC:      b[1]&0x1 != 0,
				Bitrate:  Bitrate(b[2] & 0xf0 >> 4),
				Sampling: Sampling(b[2] & 0xc >> 2),
				Padding:  b[2]&0x2 != 0,
				Mode:     Mode(b[3] & 0xc >> 4),
				Emphasis: Emphasis(b[3] & 0x3),
			}
			if !f.Valid() {
				break
			}
			m.frame = &f
			m.r.Read(b)
			return true
		}
		m.r.ReadByte()
	}
}

func (m *MP3) Err() error {
	if m.err == io.EOF {
		return nil
	}
	return m.err
}

func (m *MP3) Frame() *Frame {
	return m.frame
}

type Frame struct {
	Version
	Layer
	CRC bool
	Bitrate
	Sampling
	Padding bool
	Mode
	Emphasis
}

func (f *Frame) Valid() bool {
	if f.Version != MPEG1 {
		return false
	}
	if f.Layer != LayerI {
		return false
	}
	if f.Bitrate == 0xff || f.Bitrate == 0 {
		return false
	}
	return true
}

type Version byte

const (
	MPEG1 Version = 3
	MPEG2         = 2
)

type Layer byte

const (
	LayerI   Layer = 3
	LayerII        = 2
	LayerIII       = 1
)

type Bitrate byte

type Sampling byte

type Mode byte

const (
	ModeStereo Mode = 0
	ModeJoint       = 1
	ModeDual        = 2
	ModeSingle      = 3
)

type Emphasis byte

const (
	EmphasisNone  Emphasis = 0
	Emphasis50_15          = 1
	EmphasisCCIT           = 3
)
<|endoftext|>


<commit_before>package validation

import "fmt"
import "github.com/chris-wood/spud/codec"
import "github.com/chris-wood/spud/messages/link"
import "github.com/chris-wood/spud/messages/validation/publickey"

type ValidationAlgorithm struct {
    validationAlgorithmType uint16

    // Validation dependent data -- empty until otherwise instantiated
    publicKey publickey.PublicKey
    signatureTime uint64

    // XXX: write TLV wrappers for these fields
    keyId []byte
    certificate []byte
    keyName link.Link
}

type validationAlgorithmError struct {
    problem string
}

func (e validationAlgorithmError) Error() string {
    return fmt.Sprintf("%s", e.problem)
}

// Constructor functions

// func NewValidationAlgorithm(vaType uint16, keyId, publicKey, certificate []byte, keyName link.Link, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, keyId: keyId, publicKey: publicKey, certificate: certificate, keyName: keyName, signatureTime: signatureTime}
// }

func NewValidationAlgorithmFromPublickey(vaType uint16, publicKey publickey.PublicKey, signatureTime uint64) ValidationAlgorithm {
    return ValidationAlgorithm{validationAlgorithmType: vaType, publicKey: publicKey, signatureTime: signatureTime}
}

// func NewValidationAlgorithmFromKeyId(vaType uint16, keyId []byte, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, keyId: keyId, signatureTime: signatureTime}
// }
//
// func NewValidationAlgorithmFromLink(vaType uint16, keyName link.Link, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, keyName: keyName, signatureTime: signatureTime}
// }
//
// func NewValidationAlgorithmFromCertificate(vaType uint16, certificate []byte, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, certificate: certificate, signatureTime: signatureTime}
// }

func createFromInnerTLV(validationType uint16, tlv codec.TLV) (ValidationAlgorithm, error) {
    var result ValidationAlgorithm
    var err error

    var publicKey publickey.PublicKey

    for _, child := range(tlv.Children()) {
        if child.Type() == codec.T_PUBLICKEY {
            publicKey, err = publickey.CreateFromTLV(child)
            if err != nil {
                return result, err
            }
        } else {
            fmt.Printf("Invalid TLV type %d\n", child.Type())
        }
    }

    return ValidationAlgorithm{validationAlgorithmType: validationType, publicKey: publicKey}, nil
}

func CreateFromTLV(tlv codec.TLV) (ValidationAlgorithm, error) {
    var result ValidationAlgorithm

    // There must be one child
    if len(tlv.Children()) != 1 {
        return result, nil
    }

    containerTlv := tlv.Children()[0]
    return createFromInnerTLV(containerTlv.Type(), containerTlv)
}

// ValidationAlgorithm functions

func (va ValidationAlgorithm) GetValidationSuite() uint16 {
    return va.validationAlgorithmType
}

func (va ValidationAlgorithm) GetPublicKey() publickey.PublicKey {
    return va.publicKey
}

// TLV interface functions

func (va ValidationAlgorithm) Type() uint16 {
    return codec.T_VALALG
}

func (va ValidationAlgorithm) TypeString() string {
    return "ValidationAlgorithm"
}

func (va ValidationAlgorithm) Length() uint16 {
    length := uint16(4) // 2+2 for the TL container

    if va.publicKey.Length() > 0  {
        length += va.publicKey.Length() + 4
    }

    // XXX: add the remaining values here

    return length
}

func (va ValidationAlgorithm) Value() []byte {
    e := codec.Encoder{}

    value := make([]byte, 0)
    if va.publicKey.Length() > 0  {
        value = append(value, e.EncodeTLV(va.publicKey)...)
    }

    // XXX: add the remaining VDD values here

    container := e.EncodeContainer(va.validationAlgorithmType, uint16(len(value)))
    container = append(container, value...)

    return container
}

func (va ValidationAlgorithm) Children() []codec.TLV  {
    children := []codec.TLV{va.publicKey}
    return children
}

func (va ValidationAlgorithm) String() string  {
    return va.TypeString()
}
<commit_msg>New KeyId constructor<commit_after>package validation

import "fmt"
import "github.com/chris-wood/spud/codec"
import "github.com/chris-wood/spud/messages/hash"
import "github.com/chris-wood/spud/messages/link"
import "github.com/chris-wood/spud/messages/validation/publickey"

type ValidationAlgorithm struct {
    validationAlgorithmType uint16

    // Validation dependent data -- empty until otherwise instantiated
    publicKey publickey.PublicKey
    keyId hash.Hash
    signatureTime uint64

    // XXX: write TLV wrappers for these fields
    certificate []byte
    keyName link.Link
}

type validationAlgorithmError struct {
    problem string
}

func (e validationAlgorithmError) Error() string {
    return fmt.Sprintf("%s", e.problem)
}

// Constructor functions

func NewValidationAlgorithmFromPublickey(vaType uint16, publicKey publickey.PublicKey, signatureTime uint64) ValidationAlgorithm {
    return ValidationAlgorithm{validationAlgorithmType: vaType, publicKey: publicKey, signatureTime: signatureTime}
}

func NewValidationAlgorithmFromKeyId(vaType uint16, keyId hash.Hash, signatureTime uint64) ValidationAlgorithm {
    return ValidationAlgorithm{validationAlgorithmType: vaType, keyId: keyId, signatureTime: signatureTime}
}

// func NewValidationAlgorithmFromLink(vaType uint16, keyName link.Link, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, keyName: keyName, signatureTime: signatureTime}
// }
//
// func NewValidationAlgorithmFromCertificate(vaType uint16, certificate []byte, signatureTime uint64) ValidationAlgorithm {
//     return ValidationAlgorithm{validationAlgorithmType: vaType, certificate: certificate, signatureTime: signatureTime}
// }

func createFromInnerTLV(validationType uint16, tlv codec.TLV) (ValidationAlgorithm, error) {
    var result ValidationAlgorithm
    var err error

    var publicKey publickey.PublicKey

    for _, child := range(tlv.Children()) {
        if child.Type() == codec.T_PUBLICKEY {
            publicKey, err = publickey.CreateFromTLV(child)
            if err != nil {
                return result, err
            }
        } else {
            fmt.Printf("Invalid TLV type %d\n", child.Type())
        }
    }

    return ValidationAlgorithm{validationAlgorithmType: validationType, publicKey: publicKey}, nil
}

func CreateFromTLV(tlv codec.TLV) (ValidationAlgorithm, error) {
    var result ValidationAlgorithm

    // There must be one child
    if len(tlv.Children()) != 1 {
        return result, nil
    }

    containerTlv := tlv.Children()[0]
    return createFromInnerTLV(containerTlv.Type(), containerTlv)
}

// ValidationAlgorithm functions

func (va ValidationAlgorithm) GetValidationSuite() uint16 {
    return va.validationAlgorithmType
}

func (va ValidationAlgorithm) GetPublicKey() publickey.PublicKey {
    return va.publicKey
}

// TLV interface functions

func (va ValidationAlgorithm) Type() uint16 {
    return codec.T_VALALG
}

func (va ValidationAlgorithm) TypeString() string {
    return "ValidationAlgorithm"
}

func (va ValidationAlgorithm) Length() uint16 {
    length := uint16(4) // 2+2 for the TL container

    if va.publicKey.Length() > 0  {
        length += va.publicKey.Length() + 4
    }

    // XXX: add the remaining values here

    return length
}

func (va ValidationAlgorithm) Value() []byte {
    e := codec.Encoder{}

    value := make([]byte, 0)
    if va.publicKey.Length() > 0  {
        value = append(value, e.EncodeTLV(va.publicKey)...)
    }

    // XXX: add the remaining VDD values here

    container := e.EncodeContainer(va.validationAlgorithmType, uint16(len(value)))
    container = append(container, value...)

    return container
}

func (va ValidationAlgorithm) Children() []codec.TLV  {
    children := []codec.TLV{va.publicKey}
    return children
}

func (va ValidationAlgorithm) String() string  {
    return va.TypeString()
}
<|endoftext|>


<commit_before>package gofigure

// MIT Licensed (see README.md)- Copyright (c) 2014 Ryan S. Brown <sb@ryansb.com>

import (
	"github.com/ryansb/gofigure/conf"
	. "launchpad.net/gocheck"
	"testing"
)

type BasicS struct{}

var basicS = Suite(&BasicS{})

func Test(t *testing.T) {
	TestingT(t)
}

type MyAppSpec struct {
	Env          string
	Port         int
	Debug        bool
	AlarmLoadPct float32
}

func init() {
	conf.Settings.Option(conf.MongoDBHosts("172.16.0.101"))
	conf.Settings.Option(conf.FileLocations("sample/simple.json"))
}

// TODO: make sure that config value heirarchy matches the spec
//       env var > local file > database
<commit_msg>test option precedence<commit_after>package gofigure

// MIT Licensed (see README.md)- Copyright (c) 2014 Ryan S. Brown <sb@ryansb.com>

import (
	"github.com/ryansb/gofigure/conf"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	. "launchpad.net/gocheck"
	"os"
	"testing"
	"time"
)

type BasicS struct{}

var basicS = Suite(&BasicS{})

func Test(t *testing.T) {
	TestingT(t)
}

type MyAppSpec struct {
	Env          string
	Port         int
	Debug        bool
	AlarmLoadPct float32
}

func init() {
	conf.Settings.Option(conf.MongoDBHosts("172.16.0.101"))
	conf.Settings.Option(conf.FileLocations("file/sample/simple.json"))
}

// TODO: make sure that config value heirarchy matches the spec
//       env var > local file > database

func (s *BasicS) TestEnvOverridesFile(c *C) {
	origdb := conf.Settings.Option(conf.UseDB(false))
	os.Setenv("GOFIGURE_PORT", "4321")
	thespec := MyAppSpec{}
	err := Process(&thespec)
	c.Check(err, Equals, nil)
	c.Check(thespec.Port, Equals, 4321)
	c.Check(thespec.AlarmLoadPct, Equals, float32(0.9))

	// Now turn off environment config and retry
	origenv := conf.Settings.Option(conf.UseEnv(false))
	thespec = MyAppSpec{}
	err = Process(&thespec)
	c.Check(err, Equals, nil)
	c.Check(thespec.Port, Equals, 1234)
	conf.Settings.Option(origenv)

	conf.Settings.Option(origdb)
}
func (s *BasicS) TestEnvOverridesDB(c *C) {
	origfile := conf.Settings.Option(conf.UseFile(false))
	session, err := mgo.DialWithTimeout(conf.Settings.MongoDBHosts, 500*time.Millisecond)
	if err != nil {
		c.Fatalf(err.Error())
	}
	defer session.Close()
	err = session.DB("gofigure").C("default").DropCollection()
	if err != nil && err.Error() != "ns not found" {
		c.Fatalf("Error dropping collection: %s", err.Error())
	}
	err = session.DB("gofigure").C("default").Create(&mgo.CollectionInfo{})
	if err != nil {
		c.Fatalf("Error creating collection: %s", err.Error())
	}
	coll := session.DB("gofigure").C("default")
	err = coll.Insert(bson.M{
		"Port":         1234,
		"AlarmLoadPct": 0.9,
		"Env":          "test",
		"Debug":        true,
	})
	if err != nil {
		c.Fatalf("Failed to insert basic config. %s", err.Error())
	}

	os.Setenv("GOFIGURE_PORT", "4321")
	thespec := MyAppSpec{}
	err = Process(&thespec)
	c.Check(err, Equals, nil)
	c.Check(thespec.Port, Equals, 4321)
	c.Check(thespec.AlarmLoadPct, Equals, float32(0.9))

	// Now try without the env
	origenv := conf.Settings.Option(conf.UseEnv(false))
	thespec = MyAppSpec{}
	err = Process(&thespec)
	c.Check(err, Equals, nil)
	c.Check(thespec.Port, Equals, 1234)
	conf.Settings.Option(origenv)

	conf.Settings.Option(origfile)
}
<|endoftext|>


<commit_before>package command

import (
	"context"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"sync"

	"github.com/kr/pretty"
	"github.com/mitchellh/cli"
	"github.com/posener/complete"

	"github.com/hashicorp/errwrap"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/command/agent/auth"
	"github.com/hashicorp/vault/command/agent/auth/alicloud"
	"github.com/hashicorp/vault/command/agent/auth/aws"
	"github.com/hashicorp/vault/command/agent/auth/azure"
	"github.com/hashicorp/vault/command/agent/auth/gcp"
	"github.com/hashicorp/vault/command/agent/auth/jwt"
	"github.com/hashicorp/vault/command/agent/auth/kubernetes"
	"github.com/hashicorp/vault/command/agent/config"
	"github.com/hashicorp/vault/command/agent/sink"
	"github.com/hashicorp/vault/command/agent/sink/file"
	"github.com/hashicorp/vault/helper/gated-writer"
	"github.com/hashicorp/vault/helper/logging"
	"github.com/hashicorp/vault/version"
)

var _ cli.Command = (*AgentCommand)(nil)
var _ cli.CommandAutocomplete = (*AgentCommand)(nil)

type AgentCommand struct {
	*BaseCommand

	ShutdownCh chan struct{}
	SighupCh   chan struct{}

	logWriter io.Writer
	logGate   *gatedwriter.Writer
	logger    log.Logger

	cleanupGuard sync.Once

	startedCh chan (struct{}) // for tests

	flagConfigs  []string
	flagLogLevel string

	flagTestVerifyOnly bool
	flagCombineLogs    bool
}

func (c *AgentCommand) Synopsis() string {
	return "Start a Vault agent"
}

func (c *AgentCommand) Help() string {
	helpText := `
Usage: vault agent [options]

  This command starts a Vault agent that can perform automatic authentication
  in certain environments.

  Start an agent with a configuration file:

      $ vault agent -config=/etc/vault/config.hcl

  For a full list of examples, please see the documentation.

` + c.Flags().Help()
	return strings.TrimSpace(helpText)
}

func (c *AgentCommand) Flags() *FlagSets {
	set := c.flagSet(FlagSetHTTP)

	f := set.NewFlagSet("Command Options")

	f.StringSliceVar(&StringSliceVar{
		Name:   "config",
		Target: &c.flagConfigs,
		Completion: complete.PredictOr(
			complete.PredictFiles("*.hcl"),
			complete.PredictFiles("*.json"),
		),
		Usage: "Path to a configuration file. This configuration file should " +
			"contain only agent directives.",
	})

	f.StringVar(&StringVar{
		Name:       "log-level",
		Target:     &c.flagLogLevel,
		Default:    "info",
		EnvVar:     "VAULT_LOG_LEVEL",
		Completion: complete.PredictSet("trace", "debug", "info", "warn", "err"),
		Usage: "Log verbosity level. Supported values (in order of detail) are " +
			"\"trace\", \"debug\", \"info\", \"warn\", and \"err\".",
	})

	// Internal-only flags to follow.
	//
	// Why hello there little source code reader! Welcome to the Vault source
	// code. The remaining options are intentionally undocumented and come with
	// no warranty or backwards-compatability promise. Do not use these flags
	// in production. Do not build automation using these flags. Unless you are
	// developing against Vault, you should not need any of these flags.

	// TODO: should the below flags be public?
	f.BoolVar(&BoolVar{
		Name:    "combine-logs",
		Target:  &c.flagCombineLogs,
		Default: false,
		Hidden:  true,
	})

	f.BoolVar(&BoolVar{
		Name:    "test-verify-only",
		Target:  &c.flagTestVerifyOnly,
		Default: false,
		Hidden:  true,
	})

	// End internal-only flags.

	return set
}

func (c *AgentCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictNothing
}

func (c *AgentCommand) AutocompleteFlags() complete.Flags {
	return c.Flags().Completions()
}

func (c *AgentCommand) Run(args []string) int {
	f := c.Flags()

	if err := f.Parse(args); err != nil {
		c.UI.Error(err.Error())
		return 1
	}

	// Create a logger. We wrap it in a gated writer so that it doesn't
	// start logging too early.
	c.logGate = &gatedwriter.Writer{Writer: os.Stderr}
	c.logWriter = c.logGate
	if c.flagCombineLogs {
		c.logWriter = os.Stdout
	}
	var level log.Level
	c.flagLogLevel = strings.ToLower(strings.TrimSpace(c.flagLogLevel))
	switch c.flagLogLevel {
	case "trace":
		level = log.Trace
	case "debug":
		level = log.Debug
	case "notice", "info", "":
		level = log.Info
	case "warn", "warning":
		level = log.Warn
	case "err", "error":
		level = log.Error
	default:
		c.UI.Error(fmt.Sprintf("Unknown log level: %s", c.flagLogLevel))
		return 1
	}

	if c.logger == nil {
		c.logger = logging.NewVaultLoggerWithWriter(c.logWriter, level)
	}

	// Validation
	if len(c.flagConfigs) != 1 {
		c.UI.Error("Must specify exactly one config path using -config")
		return 1
	}

	// Load the configuration
	config, err := config.LoadConfig(c.flagConfigs[0], c.logger)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error loading configuration from %s: %s", c.flagConfigs[0], err))
		return 1
	}

	// Ensure at least one config was found.
	if config == nil {
		c.UI.Output(wrapAtLength(
			"No configuration read. Please provide the configuration with the " +
				"-config flag."))
		return 1
	}
	if config.AutoAuth == nil {
		c.UI.Error("No auto_auth block found in config file")
		return 1
	}

	infoKeys := make([]string, 0, 10)
	info := make(map[string]string)
	info["log level"] = c.flagLogLevel
	infoKeys = append(infoKeys, "log level")

	infoKeys = append(infoKeys, "version")
	verInfo := version.GetVersion()
	info["version"] = verInfo.FullVersionNumber(false)
	if verInfo.Revision != "" {
		info["version sha"] = strings.Trim(verInfo.Revision, "'")
		infoKeys = append(infoKeys, "version sha")
	}
	infoKeys = append(infoKeys, "cgo")
	info["cgo"] = "disabled"
	if version.CgoEnabled {
		info["cgo"] = "enabled"
	}

	// Server configuration output
	padding := 24
	sort.Strings(infoKeys)
	c.UI.Output("==> Vault agent configuration:\n")
	for _, k := range infoKeys {
		c.UI.Output(fmt.Sprintf(
			"%s%s: %s",
			strings.Repeat(" ", padding-len(k)),
			strings.Title(k),
			info[k]))
	}
	c.UI.Output("")

	// Tests might not want to start a vault server and just want to verify
	// the configuration.
	if c.flagTestVerifyOnly {
		if os.Getenv("VAULT_TEST_VERIFY_ONLY_DUMP_CONFIG") != "" {
			c.UI.Output(fmt.Sprintf(
				"\nConfiguration:\n%s\n",
				pretty.Sprint(*config)))
		}
		return 0
	}

	client, err := c.Client()
	if err != nil {
		c.UI.Error(fmt.Sprintf(
			"Error fetching client: %v",
			err))
		return 1
	}

	ctx, cancelFunc := context.WithCancel(context.Background())

	var sinks []*sink.SinkConfig
	for _, sc := range config.AutoAuth.Sinks {
		switch sc.Type {
		case "file":
			config := &sink.SinkConfig{
				Logger:  c.logger.Named("sink.file"),
				Config:  sc.Config,
				Client:  client,
				WrapTTL: sc.WrapTTL,
				DHType:  sc.DHType,
				DHPath:  sc.DHPath,
				AAD:     sc.AAD,
			}
			s, err := file.NewFileSink(config)
			if err != nil {
				c.UI.Error(errwrap.Wrapf("Error creating file sink: {{err}}", err).Error())
				return 1
			}
			config.Sink = s
			sinks = append(sinks, config)
		default:
			c.UI.Error(fmt.Sprintf("Unknown sink type %q", sc.Type))
			return 1
		}
	}

	var method auth.AuthMethod
	authConfig := &auth.AuthConfig{
		Logger:    c.logger.Named(fmt.Sprintf("auth.%s", config.AutoAuth.Method.Type)),
		MountPath: config.AutoAuth.Method.MountPath,
		WrapTTL:   config.AutoAuth.Method.WrapTTL,
		Config:    config.AutoAuth.Method.Config,
	}
	switch config.AutoAuth.Method.Type {
	case "alicloud":
		method, err = alicloud.NewAliCloudAuthMethod(authConfig)
	case "aws":
		method, err = aws.NewAWSAuthMethod(authConfig)
	case "azure":
		method, err = azure.NewAzureAuthMethod(authConfig)
	case "gcp":
		method, err = gcp.NewGCPAuthMethod(authConfig)
	case "jwt":
		method, err = jwt.NewJWTAuthMethod(authConfig)
	case "kubernetes":
		method, err = kubernetes.NewKubernetesAuthMethod(authConfig)
	default:
		c.UI.Error(fmt.Sprintf("Unknown auth method %q", config.AutoAuth.Method.Type))
		return 1
	}
	if err != nil {
		c.UI.Error(errwrap.Wrapf(fmt.Sprintf("Error creating %s auth method: {{err}}", config.AutoAuth.Method.Type), err).Error())
		return 1
	}

	// Output the header that the server has started
	if !c.flagCombineLogs {
		c.UI.Output("==> Vault server started! Log data will stream in below:\n")
	}

	// Inform any tests that the server is ready
	select {
	case c.startedCh <- struct{}{}:
	default:
	}

	ss := sink.NewSinkServer(&sink.SinkServerConfig{
		Logger:        c.logger.Named("sink.server"),
		Client:        client,
		ExitAfterAuth: config.ExitAfterAuth,
	})

	ah := auth.NewAuthHandler(&auth.AuthHandlerConfig{
		Logger: c.logger.Named("auth.handler"),
		Client: c.client,
	})

	// Start things running
	go ah.Run(ctx, method)
	go ss.Run(ctx, ah.OutputCh, sinks)

	// Release the log gate.
	c.logGate.Flush()

	// Write out the PID to the file now that server has successfully started
	if err := c.storePidFile(config.PidFile); err != nil {
		c.UI.Error(fmt.Sprintf("Error storing PID: %s", err))
		return 1
	}

	defer func() {
		if err := c.removePidFile(config.PidFile); err != nil {
			c.UI.Error(fmt.Sprintf("Error deleting the PID file: %s", err))
		}
	}()

	select {
	case <-ss.DoneCh:
		// This will happen if we exit-on-auth
		c.logger.Info("sinks finished, exiting")
	case <-c.ShutdownCh:
		c.UI.Output("==> Vault agent shutdown triggered")
		cancelFunc()
		<-ah.DoneCh
		<-ss.DoneCh
	}

	return 0
}

// storePidFile is used to write out our PID to a file if necessary
func (c *AgentCommand) storePidFile(pidPath string) error {
	// Quit fast if no pidfile
	if pidPath == "" {
		return nil
	}

	// Open the PID file
	pidFile, err := os.OpenFile(pidPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return errwrap.Wrapf("could not open pid file: {{err}}", err)
	}
	defer pidFile.Close()

	// Write out the PID
	pid := os.Getpid()
	_, err = pidFile.WriteString(fmt.Sprintf("%d", pid))
	if err != nil {
		return errwrap.Wrapf("could not write to pid file: {{err}}", err)
	}
	return nil
}

// removePidFile is used to cleanup the PID file if necessary
func (c *AgentCommand) removePidFile(pidPath string) error {
	if pidPath == "" {
		return nil
	}
	return os.Remove(pidPath)
}
<commit_msg>Fix authhandler-based wrapping in agent (#5316)<commit_after>package command

import (
	"context"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"sync"

	"github.com/kr/pretty"
	"github.com/mitchellh/cli"
	"github.com/posener/complete"

	"github.com/hashicorp/errwrap"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/command/agent/auth"
	"github.com/hashicorp/vault/command/agent/auth/alicloud"
	"github.com/hashicorp/vault/command/agent/auth/aws"
	"github.com/hashicorp/vault/command/agent/auth/azure"
	"github.com/hashicorp/vault/command/agent/auth/gcp"
	"github.com/hashicorp/vault/command/agent/auth/jwt"
	"github.com/hashicorp/vault/command/agent/auth/kubernetes"
	"github.com/hashicorp/vault/command/agent/config"
	"github.com/hashicorp/vault/command/agent/sink"
	"github.com/hashicorp/vault/command/agent/sink/file"
	"github.com/hashicorp/vault/helper/gated-writer"
	"github.com/hashicorp/vault/helper/logging"
	"github.com/hashicorp/vault/version"
)

var _ cli.Command = (*AgentCommand)(nil)
var _ cli.CommandAutocomplete = (*AgentCommand)(nil)

type AgentCommand struct {
	*BaseCommand

	ShutdownCh chan struct{}
	SighupCh   chan struct{}

	logWriter io.Writer
	logGate   *gatedwriter.Writer
	logger    log.Logger

	cleanupGuard sync.Once

	startedCh chan (struct{}) // for tests

	flagConfigs  []string
	flagLogLevel string

	flagTestVerifyOnly bool
	flagCombineLogs    bool
}

func (c *AgentCommand) Synopsis() string {
	return "Start a Vault agent"
}

func (c *AgentCommand) Help() string {
	helpText := `
Usage: vault agent [options]

  This command starts a Vault agent that can perform automatic authentication
  in certain environments.

  Start an agent with a configuration file:

      $ vault agent -config=/etc/vault/config.hcl

  For a full list of examples, please see the documentation.

` + c.Flags().Help()
	return strings.TrimSpace(helpText)
}

func (c *AgentCommand) Flags() *FlagSets {
	set := c.flagSet(FlagSetHTTP)

	f := set.NewFlagSet("Command Options")

	f.StringSliceVar(&StringSliceVar{
		Name:   "config",
		Target: &c.flagConfigs,
		Completion: complete.PredictOr(
			complete.PredictFiles("*.hcl"),
			complete.PredictFiles("*.json"),
		),
		Usage: "Path to a configuration file. This configuration file should " +
			"contain only agent directives.",
	})

	f.StringVar(&StringVar{
		Name:       "log-level",
		Target:     &c.flagLogLevel,
		Default:    "info",
		EnvVar:     "VAULT_LOG_LEVEL",
		Completion: complete.PredictSet("trace", "debug", "info", "warn", "err"),
		Usage: "Log verbosity level. Supported values (in order of detail) are " +
			"\"trace\", \"debug\", \"info\", \"warn\", and \"err\".",
	})

	// Internal-only flags to follow.
	//
	// Why hello there little source code reader! Welcome to the Vault source
	// code. The remaining options are intentionally undocumented and come with
	// no warranty or backwards-compatability promise. Do not use these flags
	// in production. Do not build automation using these flags. Unless you are
	// developing against Vault, you should not need any of these flags.

	// TODO: should the below flags be public?
	f.BoolVar(&BoolVar{
		Name:    "combine-logs",
		Target:  &c.flagCombineLogs,
		Default: false,
		Hidden:  true,
	})

	f.BoolVar(&BoolVar{
		Name:    "test-verify-only",
		Target:  &c.flagTestVerifyOnly,
		Default: false,
		Hidden:  true,
	})

	// End internal-only flags.

	return set
}

func (c *AgentCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictNothing
}

func (c *AgentCommand) AutocompleteFlags() complete.Flags {
	return c.Flags().Completions()
}

func (c *AgentCommand) Run(args []string) int {
	f := c.Flags()

	if err := f.Parse(args); err != nil {
		c.UI.Error(err.Error())
		return 1
	}

	// Create a logger. We wrap it in a gated writer so that it doesn't
	// start logging too early.
	c.logGate = &gatedwriter.Writer{Writer: os.Stderr}
	c.logWriter = c.logGate
	if c.flagCombineLogs {
		c.logWriter = os.Stdout
	}
	var level log.Level
	c.flagLogLevel = strings.ToLower(strings.TrimSpace(c.flagLogLevel))
	switch c.flagLogLevel {
	case "trace":
		level = log.Trace
	case "debug":
		level = log.Debug
	case "notice", "info", "":
		level = log.Info
	case "warn", "warning":
		level = log.Warn
	case "err", "error":
		level = log.Error
	default:
		c.UI.Error(fmt.Sprintf("Unknown log level: %s", c.flagLogLevel))
		return 1
	}

	if c.logger == nil {
		c.logger = logging.NewVaultLoggerWithWriter(c.logWriter, level)
	}

	// Validation
	if len(c.flagConfigs) != 1 {
		c.UI.Error("Must specify exactly one config path using -config")
		return 1
	}

	// Load the configuration
	config, err := config.LoadConfig(c.flagConfigs[0], c.logger)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error loading configuration from %s: %s", c.flagConfigs[0], err))
		return 1
	}

	// Ensure at least one config was found.
	if config == nil {
		c.UI.Output(wrapAtLength(
			"No configuration read. Please provide the configuration with the " +
				"-config flag."))
		return 1
	}
	if config.AutoAuth == nil {
		c.UI.Error("No auto_auth block found in config file")
		return 1
	}

	infoKeys := make([]string, 0, 10)
	info := make(map[string]string)
	info["log level"] = c.flagLogLevel
	infoKeys = append(infoKeys, "log level")

	infoKeys = append(infoKeys, "version")
	verInfo := version.GetVersion()
	info["version"] = verInfo.FullVersionNumber(false)
	if verInfo.Revision != "" {
		info["version sha"] = strings.Trim(verInfo.Revision, "'")
		infoKeys = append(infoKeys, "version sha")
	}
	infoKeys = append(infoKeys, "cgo")
	info["cgo"] = "disabled"
	if version.CgoEnabled {
		info["cgo"] = "enabled"
	}

	// Server configuration output
	padding := 24
	sort.Strings(infoKeys)
	c.UI.Output("==> Vault agent configuration:\n")
	for _, k := range infoKeys {
		c.UI.Output(fmt.Sprintf(
			"%s%s: %s",
			strings.Repeat(" ", padding-len(k)),
			strings.Title(k),
			info[k]))
	}
	c.UI.Output("")

	// Tests might not want to start a vault server and just want to verify
	// the configuration.
	if c.flagTestVerifyOnly {
		if os.Getenv("VAULT_TEST_VERIFY_ONLY_DUMP_CONFIG") != "" {
			c.UI.Output(fmt.Sprintf(
				"\nConfiguration:\n%s\n",
				pretty.Sprint(*config)))
		}
		return 0
	}

	client, err := c.Client()
	if err != nil {
		c.UI.Error(fmt.Sprintf(
			"Error fetching client: %v",
			err))
		return 1
	}

	ctx, cancelFunc := context.WithCancel(context.Background())

	var sinks []*sink.SinkConfig
	for _, sc := range config.AutoAuth.Sinks {
		switch sc.Type {
		case "file":
			config := &sink.SinkConfig{
				Logger:  c.logger.Named("sink.file"),
				Config:  sc.Config,
				Client:  client,
				WrapTTL: sc.WrapTTL,
				DHType:  sc.DHType,
				DHPath:  sc.DHPath,
				AAD:     sc.AAD,
			}
			s, err := file.NewFileSink(config)
			if err != nil {
				c.UI.Error(errwrap.Wrapf("Error creating file sink: {{err}}", err).Error())
				return 1
			}
			config.Sink = s
			sinks = append(sinks, config)
		default:
			c.UI.Error(fmt.Sprintf("Unknown sink type %q", sc.Type))
			return 1
		}
	}

	var method auth.AuthMethod
	authConfig := &auth.AuthConfig{
		Logger:    c.logger.Named(fmt.Sprintf("auth.%s", config.AutoAuth.Method.Type)),
		MountPath: config.AutoAuth.Method.MountPath,
		Config:    config.AutoAuth.Method.Config,
	}
	switch config.AutoAuth.Method.Type {
	case "alicloud":
		method, err = alicloud.NewAliCloudAuthMethod(authConfig)
	case "aws":
		method, err = aws.NewAWSAuthMethod(authConfig)
	case "azure":
		method, err = azure.NewAzureAuthMethod(authConfig)
	case "gcp":
		method, err = gcp.NewGCPAuthMethod(authConfig)
	case "jwt":
		method, err = jwt.NewJWTAuthMethod(authConfig)
	case "kubernetes":
		method, err = kubernetes.NewKubernetesAuthMethod(authConfig)
	default:
		c.UI.Error(fmt.Sprintf("Unknown auth method %q", config.AutoAuth.Method.Type))
		return 1
	}
	if err != nil {
		c.UI.Error(errwrap.Wrapf(fmt.Sprintf("Error creating %s auth method: {{err}}", config.AutoAuth.Method.Type), err).Error())
		return 1
	}

	// Output the header that the server has started
	if !c.flagCombineLogs {
		c.UI.Output("==> Vault server started! Log data will stream in below:\n")
	}

	// Inform any tests that the server is ready
	select {
	case c.startedCh <- struct{}{}:
	default:
	}

	ss := sink.NewSinkServer(&sink.SinkServerConfig{
		Logger:        c.logger.Named("sink.server"),
		Client:        client,
		ExitAfterAuth: config.ExitAfterAuth,
	})

	ah := auth.NewAuthHandler(&auth.AuthHandlerConfig{
		Logger:  c.logger.Named("auth.handler"),
		Client:  c.client,
		WrapTTL: config.AutoAuth.Method.WrapTTL,
	})

	// Start things running
	go ah.Run(ctx, method)
	go ss.Run(ctx, ah.OutputCh, sinks)

	// Release the log gate.
	c.logGate.Flush()

	// Write out the PID to the file now that server has successfully started
	if err := c.storePidFile(config.PidFile); err != nil {
		c.UI.Error(fmt.Sprintf("Error storing PID: %s", err))
		return 1
	}

	defer func() {
		if err := c.removePidFile(config.PidFile); err != nil {
			c.UI.Error(fmt.Sprintf("Error deleting the PID file: %s", err))
		}
	}()

	select {
	case <-ss.DoneCh:
		// This will happen if we exit-on-auth
		c.logger.Info("sinks finished, exiting")
	case <-c.ShutdownCh:
		c.UI.Output("==> Vault agent shutdown triggered")
		cancelFunc()
		<-ah.DoneCh
		<-ss.DoneCh
	}

	return 0
}

// storePidFile is used to write out our PID to a file if necessary
func (c *AgentCommand) storePidFile(pidPath string) error {
	// Quit fast if no pidfile
	if pidPath == "" {
		return nil
	}

	// Open the PID file
	pidFile, err := os.OpenFile(pidPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return errwrap.Wrapf("could not open pid file: {{err}}", err)
	}
	defer pidFile.Close()

	// Write out the PID
	pid := os.Getpid()
	_, err = pidFile.WriteString(fmt.Sprintf("%d", pid))
	if err != nil {
		return errwrap.Wrapf("could not write to pid file: {{err}}", err)
	}
	return nil
}

// removePidFile is used to cleanup the PID file if necessary
func (c *AgentCommand) removePidFile(pidPath string) error {
	if pidPath == "" {
		return nil
	}
	return os.Remove(pidPath)
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hashicorp/vault/helper/kv-builder"
)

// WriteCommand is a Command that puts data into the Vault.
type WriteCommand struct {
	Meta

	// The fields below can be overwritten for tests
	testStdin io.Reader
}

func (c *WriteCommand) Run(args []string) int {
	var format string
	var force bool
	flags := c.Meta.FlagSet("write", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.BoolVar(&force, "force", false, "")
	flags.BoolVar(&force, "f", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) < 2 && !force {
		c.Ui.Error("write expects at least two arguments")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	data, err := c.parseData(args[1:])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error loading data: %s", err))
		return 1
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Write(path, data)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error writing data to %s: %s", path, err))
		return 1
	}

	if secret == nil {
		c.Ui.Output(fmt.Sprintf("Success! Data written to: %s", path))
		return 0
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *WriteCommand) parseData(args []string) (map[string]interface{}, error) {
	var stdin io.Reader = os.Stdin
	if c.testStdin != nil {
		stdin = c.testStdin
	}

	builder := &kvbuilder.Builder{Stdin: stdin}
	if err := builder.Add(args...); err != nil {
		return nil, err
	}

	return builder.Map(), nil
}

func (c *WriteCommand) Synopsis() string {
	return "Write secrets or configuration into Vault"
}

func (c *WriteCommand) Help() string {
	helpText := `
Usage: vault write [options] path [data]

  Write data (secrets or configuration) into Vault.

  Write sends data into Vault at the given path. The behavior of the write
  is determined by the backend at the given path. For example, writing
  to "aws/policy/ops" will create an "ops" IAM policy for the AWS backend
  (configuration), but writing to "consul/foo" will write a value directly
  into Consul at that key. Check the documentation of the logical backend
  you're using for more information on key structure.

  Data is sent via additional arguments in "key=value" pairs. If value
  begins with an "@", then it is loaded from a JSON file. If you want to start
  the value with a literal "@", then prefix the "@" with a slash: "\@".

General Options:

  ` + generalOptionsUsage() + `

Write Options:

  -f | -force             Force the write to continue without any data values
                          specified. This allows writing to keys that do not
                          need or expect any fields to be specified.

`
	return strings.TrimSpace(helpText)
}
<commit_msg>help sentence improved<commit_after>package command

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hashicorp/vault/helper/kv-builder"
)

// WriteCommand is a Command that puts data into the Vault.
type WriteCommand struct {
	Meta

	// The fields below can be overwritten for tests
	testStdin io.Reader
}

func (c *WriteCommand) Run(args []string) int {
	var format string
	var force bool
	flags := c.Meta.FlagSet("write", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.BoolVar(&force, "force", false, "")
	flags.BoolVar(&force, "f", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) < 2 && !force {
		c.Ui.Error("write expects at least two arguments")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	data, err := c.parseData(args[1:])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error loading data: %s", err))
		return 1
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Write(path, data)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error writing data to %s: %s", path, err))
		return 1
	}

	if secret == nil {
		c.Ui.Output(fmt.Sprintf("Success! Data written to: %s", path))
		return 0
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *WriteCommand) parseData(args []string) (map[string]interface{}, error) {
	var stdin io.Reader = os.Stdin
	if c.testStdin != nil {
		stdin = c.testStdin
	}

	builder := &kvbuilder.Builder{Stdin: stdin}
	if err := builder.Add(args...); err != nil {
		return nil, err
	}

	return builder.Map(), nil
}

func (c *WriteCommand) Synopsis() string {
	return "Write secrets or configuration into Vault"
}

func (c *WriteCommand) Help() string {
	helpText := `
Usage: vault write [options] path [data]

  Write data (secrets or configuration) into Vault.

  Write sends data into Vault at the given path. The behavior of the write
  is determined by the backend at the given path. For example, writing
  to "aws/policy/ops" will create an "ops" IAM policy for the AWS backend
  (configuration), but writing to "consul/foo" will write a value directly
  into Consul at that key. Check the documentation of the logical backend
  you're using for more information on key structure.

  Data is sent via additional arguments in "key=value" pairs. If value
  begins with an "@", then it is loaded from a file. Write expects data in the
	file to be in JSON format. If you want to start the value with a literal "@",
	then prefix the "@" with a slash: "\@".

General Options:

  ` + generalOptionsUsage() + `

Write Options:

  -f | -force             Force the write to continue without any data values
                          specified. This allows writing to keys that do not
                          need or expect any fields to be specified.

`
	return strings.TrimSpace(helpText)
}
<|endoftext|>


<commit_before>package linhat

// Open represents an instance of the basis on (0, 1)^n.
type Open struct {
	ni int
}

// NewOpen creates an instance of the basis on (0, 1)^n.
func NewOpen(inputs uint) *Open {
	return &Open{int(inputs)}
}

// Evaluate computes the value of a multidimensional basis function at a point.
func (o *Open) Evaluate(index []uint64, point []float64) float64 {
	ni := o.ni

	value := 1.0

	for i := 0; i < ni; i++ {
		level := 0xFFFFFFFF & index[i]
		if level == 0 {
			continue
		}

		order := index[i] >> 32
		count := uint64(2)<<level - 1

		switch order {
		case 0:
			scale := float64(count + 1)
			if point[i] >= 2/scale {
				return 0
			}
			value *= 2 - scale*point[i]
		case count - 1:
			scale1, scale2 := float64(count-1), float64(count+1)
			if point[i] <= scale1/scale2 {
				return 0
			}
			value *= scale2*point[i] - scale1
		default:
			node := float64(order+1) / float64(count+1)
			scale, distance := float64(count+1), point[i]-node
			if distance < 0 {
				distance = -distance
			}
			if distance >= 1/scale {
				return 0
			}
			value *= 1 - scale*distance
		}
	}

	return value
}
<commit_msg>A minor adjustment in linhat.Open<commit_after>package linhat

// Open represents an instance of the basis on (0, 1)^n.
type Open struct {
	ni int
}

// NewOpen creates an instance of the basis on (0, 1)^n.
func NewOpen(inputs uint) *Open {
	return &Open{int(inputs)}
}

// Evaluate computes the value of a multidimensional basis function at a point.
func (o *Open) Evaluate(index []uint64, point []float64) float64 {
	ni := o.ni

	value := 1.0

	for i := 0; i < ni; i++ {
		level := 0xFFFFFFFF & index[i]
		if level == 0 {
			continue
		}

		order := index[i] >> 32
		count := uint64(2)<<level - 1

		switch order {
		case 0:
			scale := float64(count + 1)
			if point[i] >= 2/scale {
				return 0
			}
			value *= 2 - scale*point[i]
		case count - 1:
			scale1, scale2 := float64(count-1), float64(count+1)
			if point[i] <= scale1/scale2 {
				return 0
			}
			value *= scale2*point[i] - scale1
		default:
			scale := float64(count + 1)
			distance := point[i] - float64(order+1)/scale
			if distance < 0 {
				distance = -distance
			}
			if distance >= 1/scale {
				return 0
			}
			value *= 1 - scale*distance
		}
	}

	return value
}
<|endoftext|>