<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/bgentry/heroku-go"
	"io"
	"os"
	"sort"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"
)

var cmdDynos = &Command{
	Run:   runDynos,
	Usage: "dynos [-l] [name...]",
	Short: "list dynos",
	Long: `
Lists dynos.

Options:

    -l       long listing

Long listing for shows the name, state, age, and command.

Examples:

    $ hk dynos
    run.3794
    web.1
    web.2

    $ hk dynos web
    web.1
    web.2

    $ hk dynos -l
    run.3794  up   1m  bash
    web.1     up  15h  "blog /app /tmp/dst"
    web.2     up   8h  "blog /app /tmp/dst"
`,
}

func init() {
	cmdDynos.Flag.BoolVar(&flagLong, "l", false, "long listing")
}

func runDynos(cmd *Command, names []string) {
	w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0)
	defer w.Flush()
	listDynos(w, names)
}

func listDynos(w io.Writer, names []string) {
	dynos, err := client.DynoList(mustApp(), nil)
	must(err)
	sort.Sort(DynosByName(dynos))

	if len(names) == 0 {
		for _, d := range dynos {
			listDyno(w, &d)
		}
		return
	}

	for _, name := range names {
		for _, d := range dynos {
			if !strings.Contains(name, ".") {
				if strings.HasPrefix(d.Name, name+".") {
					listDyno(w, &d)
				}
			} else {
				if d.Name == name {
					listDyno(w, &d)
				}
			}
		}
	}
}

func listDyno(w io.Writer, d *heroku.Dyno) {
	if flagLong {
		listRec(w,
			d.Name,
			d.State,
			prettyDuration{dynoAge(d)},
			maybeQuote(d.Command),
		)
	} else {
		fmt.Fprintln(w, d.Name)
	}
}

// quotes s as a json string if it contains any weird chars
// currently weird is anything other than [alnum]_-
func maybeQuote(s string) string {
	for _, r := range s {
		if !('0' <= r && r <= '9' || 'a' <= r && r <= 'z' ||
			'A' <= r && r <= 'Z' || r == '-' || r == '_') {
			return quote(s)
		}
	}
	return s
}

// quotes s as a json string
func quote(s string) string {
	b, _ := json.Marshal(s)
	return string(b)
}

type DynosByName []heroku.Dyno

func (p DynosByName) Len() int      { return len(p) }
func (p DynosByName) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p DynosByName) Less(i, j int) bool {
	return p[i].Type < p[j].Type || (p[i].Type == p[j].Type && dynoSeq(&p[i]) < dynoSeq(&p[j]))
}

type prettyDuration struct {
	time.Duration
}

func dynoAge(d *heroku.Dyno) time.Duration {
	return time.Now().Sub(d.UpdatedAt)
}

func dynoSeq(d *heroku.Dyno) int {
	i, _ := strconv.Atoi(strings.TrimPrefix(d.Name, d.Type+"."))
	return i
}

func (a prettyDuration) String() string {
	switch d := a.Duration; {
	case d > 2*24*time.Hour:
		return a.Unit(24*time.Hour, "d")
	case d > 2*time.Hour:
		return a.Unit(time.Hour, "h")
	case d > 2*time.Minute:
		return a.Unit(time.Minute, "m")
	}
	return a.Unit(time.Second, "s")
}

func (a prettyDuration) Unit(u time.Duration, s string) string {
	return fmt.Sprintf("%2d", roundDur(a.Duration, u)) + s
}

func roundDur(d, k time.Duration) int {
	return int((d + k/2 - 1) / k)
}

func abbrev(s string, n int) string {
	if len(s) > n {
		return s[:n-1] + "…"
	}
	return s
}
<commit_msg>small fix to dynos usage<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/bgentry/heroku-go"
	"io"
	"os"
	"sort"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"
)

var cmdDynos = &Command{
	Run:   runDynos,
	Usage: "dynos [-l] [name...]",
	Short: "list dynos",
	Long: `
Lists dynos.

Options:

    -l       long listing

Long listing shows the name, state, age, and command.

Examples:

    $ hk dynos
    run.3794
    web.1
    web.2

    $ hk dynos web
    web.1
    web.2

    $ hk dynos -l
    run.3794  up   1m  bash
    web.1     up  15h  "blog /app /tmp/dst"
    web.2     up   8h  "blog /app /tmp/dst"
`,
}

func init() {
	cmdDynos.Flag.BoolVar(&flagLong, "l", false, "long listing")
}

func runDynos(cmd *Command, names []string) {
	w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0)
	defer w.Flush()
	listDynos(w, names)
}

func listDynos(w io.Writer, names []string) {
	dynos, err := client.DynoList(mustApp(), nil)
	must(err)
	sort.Sort(DynosByName(dynos))

	if len(names) == 0 {
		for _, d := range dynos {
			listDyno(w, &d)
		}
		return
	}

	for _, name := range names {
		for _, d := range dynos {
			if !strings.Contains(name, ".") {
				if strings.HasPrefix(d.Name, name+".") {
					listDyno(w, &d)
				}
			} else {
				if d.Name == name {
					listDyno(w, &d)
				}
			}
		}
	}
}

func listDyno(w io.Writer, d *heroku.Dyno) {
	if flagLong {
		listRec(w,
			d.Name,
			d.State,
			prettyDuration{dynoAge(d)},
			maybeQuote(d.Command),
		)
	} else {
		fmt.Fprintln(w, d.Name)
	}
}

// quotes s as a json string if it contains any weird chars
// currently weird is anything other than [alnum]_-
func maybeQuote(s string) string {
	for _, r := range s {
		if !('0' <= r && r <= '9' || 'a' <= r && r <= 'z' ||
			'A' <= r && r <= 'Z' || r == '-' || r == '_') {
			return quote(s)
		}
	}
	return s
}

// quotes s as a json string
func quote(s string) string {
	b, _ := json.Marshal(s)
	return string(b)
}

type DynosByName []heroku.Dyno

func (p DynosByName) Len() int      { return len(p) }
func (p DynosByName) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p DynosByName) Less(i, j int) bool {
	return p[i].Type < p[j].Type || (p[i].Type == p[j].Type && dynoSeq(&p[i]) < dynoSeq(&p[j]))
}

type prettyDuration struct {
	time.Duration
}

func dynoAge(d *heroku.Dyno) time.Duration {
	return time.Now().Sub(d.UpdatedAt)
}

func dynoSeq(d *heroku.Dyno) int {
	i, _ := strconv.Atoi(strings.TrimPrefix(d.Name, d.Type+"."))
	return i
}

func (a prettyDuration) String() string {
	switch d := a.Duration; {
	case d > 2*24*time.Hour:
		return a.Unit(24*time.Hour, "d")
	case d > 2*time.Hour:
		return a.Unit(time.Hour, "h")
	case d > 2*time.Minute:
		return a.Unit(time.Minute, "m")
	}
	return a.Unit(time.Second, "s")
}

func (a prettyDuration) Unit(u time.Duration, s string) string {
	return fmt.Sprintf("%2d", roundDur(a.Duration, u)) + s
}

func roundDur(d, k time.Duration) int {
	return int((d + k/2 - 1) / k)
}

func abbrev(s string, n int) string {
	if len(s) > n {
		return s[:n-1] + "…"
	}
	return s
}
<|endoftext|>


<commit_before>package hrq

import (
	"io"
	"net/http"
	"time"
)

// DefaultTimeout is seconds of timeout.
var DefaultTimeout = 15

// Request wraps http.Request.
type Request struct {
	Req     *http.Request
	Timeout time.Duration
}

// Send sends request.
func (r *Request) Send() (res *Response, err error) {
	cli := &http.Client{
		Timeout: r.Timeout,
	}
	response, err := cli.Do(r.Req)
	if err != nil {
		return
	}
	res = &Response{
		Res: response,
	}
	return
}

// NewRequest make a Request.
func NewRequest(method, url string, body io.Reader, timeoutSecond int) (req *Request, err error) {
	request, err := http.NewRequest(method, url, nil)
	if err != nil {
		return
	}
	timeout := time.Duration(timeoutSecond) * time.Second
	req = &Request{
		Req:     request,
		Timeout: timeout,
	}
	return
}

// Get make a request whose method is GET.
func Get(url string) (req *Request, err error) {
	req, err = NewRequest("GET", url, nil, DefaultTimeout)
	return
}
<commit_msg>Add SetHeader()<commit_after>package hrq

import (
	"io"
	"net/http"
	"time"
)

// DefaultTimeout is seconds of timeout.
var DefaultTimeout = 15

// DefaultContentType is a content-type of request.
var DefaultContentType = "application/x-www-form-urlencoded"

// Request wraps http.Request.
type Request struct {
	Req     *http.Request
	Timeout time.Duration
}

// Send sends request.
func (r *Request) Send() (res *Response, err error) {
	cli := &http.Client{
		Timeout: r.Timeout,
	}
	response, err := cli.Do(r.Req)
	if err != nil {
		return
	}
	res = &Response{
		Res: response,
	}
	return
}

// SetHeader sets a value of request header.
func (r *Request) SetHeader(key, value string) *Request {
	r.Req.Header.Set(key, value)
	return r
}

// NewRequest make a Request.
func NewRequest(method, url string, body io.Reader, timeoutSecond int) (req *Request, err error) {
	request, err := http.NewRequest(method, url, nil)
	if err != nil {
		return
	}
	timeout := time.Duration(timeoutSecond) * time.Second
	req = &Request{
		Req:     request,
		Timeout: timeout,
	}
	return
}

// Get make a request whose method is GET.
func Get(url string) (req *Request, err error) {
	req, err = NewRequest("GET", url, nil, DefaultTimeout)
	return
}

// Post make a request whose method is GET.
func Post(url string) (req *Request, err error) {
	req, err = NewRequest("Post", url, nil, DefaultTimeout)
	req.SetHeader("Content-Type", DefaultContentType)
	return
}
<|endoftext|>


<commit_before>package request

import (
	"encoding/json"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"time"

	"gopkg.in/ddo/go-dlog.v1"
)

const (
	DEFAULT_TIMEOUT = 180
)

var debug = dlog.New("request", nil)

type Client struct {
	httpClient *http.Client
}

func New() *Client {
	var cookie, _ = cookiejar.New(nil)

	client := &http.Client{
		Timeout: time.Second * DEFAULT_TIMEOUT,
		Jar:     cookie,
	}

	debug()
	return &Client{client}
}

func NewNoCookie() *Client {
	client := &http.Client{
		Timeout: time.Second * DEFAULT_TIMEOUT,
	}

	debug()
	return &Client{client}
}

type Data map[string][]string
type Header map[string]string

type Option struct {
	Url      string //required
	Method   string //default: "GET", anything "POST", "PUT", "DELETE" or "PATCH"
	BodyStr  string
	Body     *Data
	Form     *Data       //set Content-Type header as "application/x-www-form-urlencoded"
	Json     interface{} //set Content-Type header as "application/json"
	Query    *Data
	QueryRaw string
	Header   *Header
}

func (c *Client) SetTimeout(timeout time.Duration) {
	debug(timeout)

	c.httpClient.Timeout = timeout
}

func (c *Client) Request(opt *Option) (res *http.Response, err error) {
	debug("START")

	//set GET as default method
	if opt.Method == "" {
		opt.Method = "GET"
	}

	opt.Method = strings.ToUpper(opt.Method)

	//url
	reqUrl, err := makeUrl(opt.Url, opt.Query)

	if err != nil {
		return
	}

	//body
	reqBody, err := makeBody(opt)

	if err != nil {
		return
	}

	req, err := http.NewRequest(opt.Method, reqUrl.String()+opt.QueryRaw, strings.NewReader(reqBody))

	if err != nil {
		debug("ERR(req)", err)
		return
	}

	//header
	makeHeader(req, opt)

	res, err = c.httpClient.Do(req)

	if err != nil {
		debug("ERR(http)", err)
		return
	}

	debug(res.Request.URL)
	debug("DONE", res.Status)
	return
}

func makeUrl(urlStr string, query *Data) (u *url.URL, err error) {
	u, err = url.Parse(urlStr)

	if err != nil {
		debug("ERR:", err)
		return
	}

	if query == nil {
		return
	}

	qs := u.Query()

	for key, slice := range *query {
		for _, value := range slice {
			qs.Add(key, value)
		}
	}

	u.RawQuery = qs.Encode()
	return
}

func makeBody(opt *Option) (body string, err error) {
	var data *Data

	switch {
	case opt.BodyStr != "":
		body = opt.BodyStr
		return

	case opt.Json != nil:
		jsonStr, err := json.Marshal(opt.Json)

		if err != nil {
			debug("ERR:", err)
			return body, err
		}

		body = string(jsonStr)
		return body, err

	case opt.Form != nil:
		data = opt.Form

	case opt.Body != nil:
		data = opt.Body

	default:
		return
	}

	values := url.Values{}

	for key, slice := range *data {
		for _, value := range slice {
			values.Add(key, value)
		}
	}

	body = values.Encode()
	return
}

func makeHeader(req *http.Request, opt *Option) {
	//default User-Agent
	// req.Header.Set("User-Agent", "github.com/ddo/request")
	req.Header.Set("User-Agent", " ") // == "" on the host side

	switch {
	case opt.Form != nil:
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	case opt.Json != nil:
		req.Header.Set("Content-Type", "application/json")
	}

	if opt.Header == nil {
		return
	}

	for key, value := range *opt.Header {
		req.Header.Set(key, value)
	}
}
<commit_msg>add #SetProxy<commit_after>package request

import (
	"encoding/json"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"time"

	"gopkg.in/ddo/go-dlog.v1"
)

const (
	DEFAULT_TIMEOUT = 180
)

var debug = dlog.New("request", nil)

type Client struct {
	httpClient *http.Client
}

func New() *Client {
	var cookie, _ = cookiejar.New(nil)

	client := &http.Client{
		Timeout: time.Second * DEFAULT_TIMEOUT,
		Jar:     cookie,
	}

	debug()
	return &Client{client}
}

func NewNoCookie() *Client {
	client := &http.Client{
		Timeout: time.Second * DEFAULT_TIMEOUT,
	}

	debug()
	return &Client{client}
}

type Data map[string][]string
type Header map[string]string

type Option struct {
	Url      string //required
	Method   string //default: "GET", anything "POST", "PUT", "DELETE" or "PATCH"
	BodyStr  string
	Body     *Data
	Form     *Data       //set Content-Type header as "application/x-www-form-urlencoded"
	Json     interface{} //set Content-Type header as "application/json"
	Query    *Data
	QueryRaw string
	Header   *Header
}

func (c *Client) SetTimeout(timeout time.Duration) {
	debug(timeout)

	c.httpClient.Timeout = timeout
}

func (c *Client) SetProxy(proxyUrlStr string) (err error) {
	debug(proxyUrlStr)

	proxyUrl, err := url.Parse(proxyUrlStr)
	if err != nil {
		debug("ERR(url.Parse)", err)
		return
	}

	c.httpClient.Transport = &http.Transport{Proxy: http.ProxyURL(proxyUrl)}
	return
}

func (c *Client) Request(opt *Option) (res *http.Response, err error) {
	debug("START")

	//set GET as default method
	if opt.Method == "" {
		opt.Method = "GET"
	}

	opt.Method = strings.ToUpper(opt.Method)

	//url
	reqUrl, err := makeUrl(opt.Url, opt.Query)

	if err != nil {
		return
	}

	//body
	reqBody, err := makeBody(opt)

	if err != nil {
		return
	}

	req, err := http.NewRequest(opt.Method, reqUrl.String()+opt.QueryRaw, strings.NewReader(reqBody))

	if err != nil {
		debug("ERR(req)", err)
		return
	}

	//header
	makeHeader(req, opt)

	res, err = c.httpClient.Do(req)

	if err != nil {
		debug("ERR(http)", err)
		return
	}

	debug(res.Request.URL)
	debug("DONE", res.Status)
	return
}

func makeUrl(urlStr string, query *Data) (u *url.URL, err error) {
	u, err = url.Parse(urlStr)

	if err != nil {
		debug("ERR:", err)
		return
	}

	if query == nil {
		return
	}

	qs := u.Query()

	for key, slice := range *query {
		for _, value := range slice {
			qs.Add(key, value)
		}
	}

	u.RawQuery = qs.Encode()
	return
}

func makeBody(opt *Option) (body string, err error) {
	var data *Data

	switch {
	case opt.BodyStr != "":
		body = opt.BodyStr
		return

	case opt.Json != nil:
		jsonStr, err := json.Marshal(opt.Json)

		if err != nil {
			debug("ERR:", err)
			return body, err
		}

		body = string(jsonStr)
		return body, err

	case opt.Form != nil:
		data = opt.Form

	case opt.Body != nil:
		data = opt.Body

	default:
		return
	}

	values := url.Values{}

	for key, slice := range *data {
		for _, value := range slice {
			values.Add(key, value)
		}
	}

	body = values.Encode()
	return
}

func makeHeader(req *http.Request, opt *Option) {
	//default User-Agent
	// req.Header.Set("User-Agent", "github.com/ddo/request")
	req.Header.Set("User-Agent", " ") // == "" on the host side

	switch {
	case opt.Form != nil:
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	case opt.Json != nil:
		req.Header.Set("Content-Type", "application/json")
	}

	if opt.Header == nil {
		return
	}

	for key, value := range *opt.Header {
		req.Header.Set(key, value)
	}
}
<|endoftext|>


<commit_before>package mackerel

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
)

// APIError represents the error type from Mackerel API.
type APIError struct {
	StatusCode int
	Message    string
}

func (err *APIError) Error() string {
	return fmt.Sprintf("API request failed: %s", err.Message)
}

func extractErrorMessage(r io.Reader) (errorMessage string) {
	bs, err := ioutil.ReadAll(r)
	if err != nil {
		return
	}
	var data struct{ Error struct{ Message string } }
	err = json.Unmarshal(bs, &data)
	if err == nil {
		errorMessage = data.Error.Message
	} else {
		var data struct{ Error string }
		err = json.Unmarshal(bs, &data)
		errorMessage = data.Error
	}
	return
}
<commit_msg>remove unused err<commit_after>package mackerel

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
)

// APIError represents the error type from Mackerel API.
type APIError struct {
	StatusCode int
	Message    string
}

func (err *APIError) Error() string {
	return fmt.Sprintf("API request failed: %s", err.Message)
}

func extractErrorMessage(r io.Reader) (errorMessage string) {
	bs, err := ioutil.ReadAll(r)
	if err != nil {
		return
	}
	var data struct{ Error struct{ Message string } }
	err = json.Unmarshal(bs, &data)
	if err == nil {
		errorMessage = data.Error.Message
	} else {
		var data struct{ Error string }
		json.Unmarshal(bs, &data)
		errorMessage = data.Error
	}
	return
}
<|endoftext|>


<commit_before>// Package diary provides a simple JSON logger.
package diary

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"time"
)

// Default keys for log output
const (
	DefaultTimeKey    = "ts"
	DefaultLevelKey   = "lvl"
	DefaultMessageKey = "message"
)

// Level is the level of the log entry
type Level int

// Log Levels
const (
	LevelFatal = iota
	LevelError
	LevelInfo
	LevelDebug
)

type (
	// Context is a map of key/value pairs. These are Marshalled and included in the log output.
	Context map[string]interface{}

	// Logger is the actual logger. The default log level is info and the default writer is STDOUT.
	Logger struct {
		level      Level
		context    Context
		writer     io.Writer
		timeKey    string
		levelKey   string
		messageKey string
	}
)

// SetLevel creates a function that sets the log level. Generally, used when create a new logger.
func SetLevel(lvl Level) func(*Logger) {
	return func(l *Logger) {
		l.level = lvl
		return
	}
}

// SetContext creates a function that sets the context. Generally, used when create a new logger.
func SetContext(ctx Context) func(*Logger) {
	return func(l *Logger) {
		l.context = ctx
		return
	}
}

// SetWriter creates a function that will set the writer. Generally, used when create a new logger.
func SetWriter(w io.Writer) func(*Logger) {
	return func(l *Logger) {
		l.writer = w
		return
	}
}

// SetTimeKey creates a funtion that sets the time key. Generally, used when create a new logger.
func SetTimeKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.timeKey = key
		return
	}
}

// SetLevelKey creates a funtion that sets the level key. Generally, used when create a new logger.
func SetLevelKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.levelKey = key
		return
	}
}

// SetMessageKey creates a funtion that sets the message key. Generally, used when create a new logger.
func SetMessageKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.messageKey = key
		return
	}
}

func (l *Logger) doOptions(options []func(*Logger)) {
	for _, f := range options {
		f(l)
	}
	return
}

// New creates a logger.
func New(context Context, options ...func(*Logger)) *Logger {
	l := &Logger{
		level:      LevelInfo,
		context:    context,
		writer:     os.Stdout,
		timeKey:    DefaultTimeKey,
		levelKey:   DefaultLevelKey,
		messageKey: DefaultMessageKey,
	}

	l.doOptions(options)

	return l
}

// New creates a child logger.  Initial options are inherited from the parent.
func (l *Logger) New(context Context, options ...func(*Logger)) *Logger {
	n := &Logger{
		level:      l.level,
		writer:     l.writer,
		timeKey:    l.timeKey,
		levelKey:   l.levelKey,
		messageKey: l.messageKey,
	}

	ctx := make(Context)

	for k, v := range l.context {
		ctx[k] = v
	}

	for k, v := range context {
		ctx[k] = v
	}

	n.context = ctx

	n.doOptions(options)

	return n
}

// Fatal logs a message at the "fatal" log level. It then calls os.Exit
func (l *Logger) Fatal(msg string, context ...Context) {
	l.write(LevelFatal, msg, context)
	os.Exit(-1)
}

// Error logs a message at the "error" log level.
func (l *Logger) Error(msg string, context ...Context) {
	l.write(LevelError, msg, context)
}

// Info logs a message at the "info" log level.
func (l *Logger) Info(msg string, context ...Context) {
	l.write(LevelInfo, msg, context)
}

// Debug logs a message at the "debug" log level.
func (l *Logger) Debug(msg string, context ...Context) {
	l.write(LevelDebug, msg, context)
}

func (l *Logger) write(level Level, msg string, context []Context) {
	if level > l.level {
		return
	}

	record := make(map[string]interface{}, 8)

	for k, v := range l.context {
		record[k] = v
	}

	for _, ctx := range context {
		for k, v := range ctx {
			record[k] = v
		}
	}

	record[l.timeKey] = time.Now()
	record[l.messageKey] = msg
	record[l.levelKey] = l.level.String()

	if data, err := json.Marshal(record); err == nil {
		data = append(data, '\n')
		l.writer.Write(data)
	}
}

// String returns the name of a Level.
func (l Level) String() string {
	switch l {
	case LevelDebug:
		return "dbug"
	case LevelInfo:
		return "info"
	case LevelError:
		return "eror"
	case LevelFatal:
		return "fatal"
	default:
		return "unknown"
	}
}

// LevelFromString returns the appropriate Level from a string name.
// Useful for parsing command line args and configuration files.
func LevelFromString(levelString string) (Level, error) {
	switch levelString {
	case "debug":
		return LevelDebug, nil
	case "info":
		return LevelInfo, nil
	case "error", "eror", "err":
		return LevelError, nil
	case "fatal":
		return LevelFatal, nil
	default:
		return LevelDebug, fmt.Errorf("Unknown level: %v", levelString)
	}
}
<commit_msg>changed LevelFromString return val (val, error) -> (val, bool)<commit_after>// Package diary provides a simple JSON logger.
package diary

import (
	"encoding/json"
	"io"
	"os"
	"time"
)

// Default keys for log output
const (
	DefaultTimeKey    = "ts"
	DefaultLevelKey   = "lvl"
	DefaultMessageKey = "message"
)

// Level is the level of the log entry
type Level int

// Log Levels
const (
	LevelFatal = iota
	LevelError
	LevelInfo
	LevelDebug
)

type (
	// Context is a map of key/value pairs. These are Marshalled and included in the log output.
	Context map[string]interface{}

	// Logger is the actual logger. The default log level is info and the default writer is STDOUT.
	Logger struct {
		level      Level
		context    Context
		writer     io.Writer
		timeKey    string
		levelKey   string
		messageKey string
	}
)

// SetLevel creates a function that sets the log level. Generally, used when create a new logger.
func SetLevel(lvl Level) func(*Logger) {
	return func(l *Logger) {
		l.level = lvl
		return
	}
}

// SetContext creates a function that sets the context. Generally, used when create a new logger.
func SetContext(ctx Context) func(*Logger) {
	return func(l *Logger) {
		l.context = ctx
		return
	}
}

// SetWriter creates a function that will set the writer. Generally, used when create a new logger.
func SetWriter(w io.Writer) func(*Logger) {
	return func(l *Logger) {
		l.writer = w
		return
	}
}

// SetTimeKey creates a funtion that sets the time key. Generally, used when create a new logger.
func SetTimeKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.timeKey = key
		return
	}
}

// SetLevelKey creates a funtion that sets the level key. Generally, used when create a new logger.
func SetLevelKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.levelKey = key
		return
	}
}

// SetMessageKey creates a funtion that sets the message key. Generally, used when create a new logger.
func SetMessageKey(key string) func(*Logger) {
	return func(l *Logger) {
		l.messageKey = key
		return
	}
}

func (l *Logger) doOptions(options []func(*Logger)) {
	for _, f := range options {
		f(l)
	}
	return
}

// New creates a logger.
func New(context Context, options ...func(*Logger)) *Logger {
	l := &Logger{
		level:      LevelInfo,
		context:    context,
		writer:     os.Stdout,
		timeKey:    DefaultTimeKey,
		levelKey:   DefaultLevelKey,
		messageKey: DefaultMessageKey,
	}

	l.doOptions(options)

	return l
}

// New creates a child logger.  Initial options are inherited from the parent.
func (l *Logger) New(context Context, options ...func(*Logger)) *Logger {
	n := &Logger{
		level:      l.level,
		writer:     l.writer,
		timeKey:    l.timeKey,
		levelKey:   l.levelKey,
		messageKey: l.messageKey,
	}

	ctx := make(Context)

	for k, v := range l.context {
		ctx[k] = v
	}

	for k, v := range context {
		ctx[k] = v
	}

	n.context = ctx

	n.doOptions(options)

	return n
}

// Fatal logs a message at the "fatal" log level. It then calls os.Exit
func (l *Logger) Fatal(msg string, context ...Context) {
	l.write(LevelFatal, msg, context)
	os.Exit(-1)
}

// Error logs a message at the "error" log level.
func (l *Logger) Error(msg string, context ...Context) {
	l.write(LevelError, msg, context)
}

// Info logs a message at the "info" log level.
func (l *Logger) Info(msg string, context ...Context) {
	l.write(LevelInfo, msg, context)
}

// Debug logs a message at the "debug" log level.
func (l *Logger) Debug(msg string, context ...Context) {
	l.write(LevelDebug, msg, context)
}

func (l *Logger) write(level Level, msg string, context []Context) {
	if level > l.level {
		return
	}

	record := make(map[string]interface{}, 8)

	for k, v := range l.context {
		record[k] = v
	}

	for _, ctx := range context {
		for k, v := range ctx {
			record[k] = v
		}
	}

	record[l.timeKey] = time.Now()
	record[l.messageKey] = msg
	record[l.levelKey] = l.level.String()

	if data, err := json.Marshal(record); err == nil {
		data = append(data, '\n')
		l.writer.Write(data)
	}
}

// String returns the name of a Level.
func (l Level) String() string {
	switch l {
	case LevelDebug:
		return "dbug"
	case LevelInfo:
		return "info"
	case LevelError:
		return "eror"
	case LevelFatal:
		return "fatal"
	default:
		return "unknown"
	}
}

// LevelFromString returns the appropriate Level from a string name.
// Useful for parsing command line args and configuration files.
func LevelFromString(levelString string) (Level, bool) {
	switch levelString {
	case "debug":
		return LevelDebug, true
	case "info":
		return LevelInfo, true
	case "error", "eror", "err":
		return LevelError, true
	case "fatal":
		return LevelFatal, true
	default:
		return LevelDebug, false
	}
}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"fmt"
	"os"

	"github.com/opencontainers/runc/libcontainer"
	"github.com/urfave/cli"
)

var restoreCommand = cli.Command{
	Name:  "restore",
	Usage: "restore a container from a previous checkpoint",
	ArgsUsage: `<container-id>

Where "<container-id>" is the name for the instance of the container to be
restored.`,
	Description: `Restores the saved state of the container instance that was previously saved
using the runc checkpoint command.`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console-socket",
			Value: "",
			Usage: "path to an AF_UNIX socket which will receive a file descriptor referencing the master end of the console's pseudoterminal",
		},
		cli.StringFlag{
			Name:  "image-path",
			Value: "",
			Usage: "path to criu image files for restoring",
		},
		cli.StringFlag{
			Name:  "work-path",
			Value: "",
			Usage: "path for saving work files and logs",
		},
		cli.BoolFlag{
			Name:  "tcp-established",
			Usage: "allow open tcp connections",
		},
		cli.BoolFlag{
			Name:  "ext-unix-sk",
			Usage: "allow external unix sockets",
		},
		cli.BoolFlag{
			Name:  "shell-job",
			Usage: "allow shell jobs",
		},
		cli.BoolFlag{
			Name:  "file-locks",
			Usage: "handle file locks, for safety",
		},
		cli.StringFlag{
			Name:  "manage-cgroups-mode",
			Value: "",
			Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'",
		},
		cli.StringFlag{
			Name:  "bundle, b",
			Value: "",
			Usage: "path to the root of the bundle directory",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.BoolFlag{
			Name:  "no-subreaper",
			Usage: "disable the use of the subreaper used to reap reparented processes",
		},
		cli.BoolFlag{
			Name:  "no-pivot",
			Usage: "do not use pivot root to jail process inside rootfs.  This should be used whenever the rootfs is on top of a ramdisk",
		},
		cli.StringSliceFlag{
			Name:  "empty-ns",
			Usage: "create a namespace, but don't restore its properties",
		},
		cli.BoolFlag{
			Name:  "auto-dedup",
			Usage: "enable auto deduplication of memory images",
		},
		cli.BoolFlag{
			Name:  "lazy-pages",
			Usage: "use userfaultfd to lazily restore memory pages",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 1, exactArgs); err != nil {
			return err
		}
		// XXX: Currently this is untested with rootless containers.
		rootless, err := isRootless(context)
		if err != nil {
			return err
		}
		if rootless {
			return fmt.Errorf("runc restore requires root")
		}

		spec, err := setupSpec(context)
		if err != nil {
			return err
		}
		options := criuOptions(context)
		status, err := startContainer(context, spec, CT_ACT_RESTORE, options)
		if err != nil {
			return err
		}
		// exit with the container's exit status so any external supervisor is
		// notified of the exit with the correct exit status.
		os.Exit(status)
		return nil
	},
}

func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
	imagePath := getCheckpointImagePath(context)
	if err := os.MkdirAll(imagePath, 0655); err != nil {
		fatal(err)
	}
	return &libcontainer.CriuOpts{
		ImagesDirectory:         imagePath,
		WorkDirectory:           context.String("work-path"),
		ParentImage:             context.String("parent-path"),
		LeaveRunning:            context.Bool("leave-running"),
		TcpEstablished:          context.Bool("tcp-established"),
		ExternalUnixConnections: context.Bool("ext-unix-sk"),
		ShellJob:                context.Bool("shell-job"),
		FileLocks:               context.Bool("file-locks"),
		PreDump:                 context.Bool("pre-dump"),
		AutoDedup:               context.Bool("auto-dedup"),
		LazyPages:               context.Bool("lazy-pages"),
		StatusFd:                context.String("status-fd"),
	}
}
<commit_msg>cr: don't restore net namespace by default<commit_after>// +build linux

package main

import (
	"fmt"
	"os"

	"github.com/opencontainers/runc/libcontainer"
	"github.com/urfave/cli"
)

var restoreCommand = cli.Command{
	Name:  "restore",
	Usage: "restore a container from a previous checkpoint",
	ArgsUsage: `<container-id>

Where "<container-id>" is the name for the instance of the container to be
restored.`,
	Description: `Restores the saved state of the container instance that was previously saved
using the runc checkpoint command.`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console-socket",
			Value: "",
			Usage: "path to an AF_UNIX socket which will receive a file descriptor referencing the master end of the console's pseudoterminal",
		},
		cli.StringFlag{
			Name:  "image-path",
			Value: "",
			Usage: "path to criu image files for restoring",
		},
		cli.StringFlag{
			Name:  "work-path",
			Value: "",
			Usage: "path for saving work files and logs",
		},
		cli.BoolFlag{
			Name:  "tcp-established",
			Usage: "allow open tcp connections",
		},
		cli.BoolFlag{
			Name:  "ext-unix-sk",
			Usage: "allow external unix sockets",
		},
		cli.BoolFlag{
			Name:  "shell-job",
			Usage: "allow shell jobs",
		},
		cli.BoolFlag{
			Name:  "file-locks",
			Usage: "handle file locks, for safety",
		},
		cli.StringFlag{
			Name:  "manage-cgroups-mode",
			Value: "",
			Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'",
		},
		cli.StringFlag{
			Name:  "bundle, b",
			Value: "",
			Usage: "path to the root of the bundle directory",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.BoolFlag{
			Name:  "no-subreaper",
			Usage: "disable the use of the subreaper used to reap reparented processes",
		},
		cli.BoolFlag{
			Name:  "no-pivot",
			Usage: "do not use pivot root to jail process inside rootfs.  This should be used whenever the rootfs is on top of a ramdisk",
		},
		cli.StringSliceFlag{
			Name:  "empty-ns",
			Usage: "create a namespace, but don't restore its properties",
		},
		cli.BoolFlag{
			Name:  "auto-dedup",
			Usage: "enable auto deduplication of memory images",
		},
		cli.BoolFlag{
			Name:  "lazy-pages",
			Usage: "use userfaultfd to lazily restore memory pages",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 1, exactArgs); err != nil {
			return err
		}
		// XXX: Currently this is untested with rootless containers.
		rootless, err := isRootless(context)
		if err != nil {
			return err
		}
		if rootless {
			return fmt.Errorf("runc restore requires root")
		}

		spec, err := setupSpec(context)
		if err != nil {
			return err
		}
		options := criuOptions(context)
		if err := setEmptyNsMask(context, options); err != nil {
			return err
		}
		status, err := startContainer(context, spec, CT_ACT_RESTORE, options)
		if err != nil {
			return err
		}
		// exit with the container's exit status so any external supervisor is
		// notified of the exit with the correct exit status.
		os.Exit(status)
		return nil
	},
}

func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
	imagePath := getCheckpointImagePath(context)
	if err := os.MkdirAll(imagePath, 0655); err != nil {
		fatal(err)
	}
	return &libcontainer.CriuOpts{
		ImagesDirectory:         imagePath,
		WorkDirectory:           context.String("work-path"),
		ParentImage:             context.String("parent-path"),
		LeaveRunning:            context.Bool("leave-running"),
		TcpEstablished:          context.Bool("tcp-established"),
		ExternalUnixConnections: context.Bool("ext-unix-sk"),
		ShellJob:                context.Bool("shell-job"),
		FileLocks:               context.Bool("file-locks"),
		PreDump:                 context.Bool("pre-dump"),
		AutoDedup:               context.Bool("auto-dedup"),
		LazyPages:               context.Bool("lazy-pages"),
		StatusFd:                context.String("status-fd"),
	}
}
<|endoftext|>


<commit_before>package reporting

import (
	"runtime"
	"strings"
)

type Report struct {
	File       string
	Line       int
	Failure    string
	Error      interface{}
	stackTrace string
}

func NewFailureReport(failure string) *Report {
	file, line := caller()
	stack := stackTrace()
	report := Report{file, line, failure, nil, stack}
	return &report
}
func NewErrorReport(err interface{}) *Report {
	file, line := caller()
	stack := fullStackTrace()
	report := Report{file, line, "", err, stack}
	return &report
}
func NewSuccessReport() *Report {
	file, line := caller()
	stack := stackTrace()
	report := Report{file, line, "", nil, stack}
	return &report
}

func caller() (file string, line int) {
	_, file, line, _ = runtime.Caller(3)
	return
}
func stackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, false)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func fullStackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, true)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func removeInternalEntries(stack string) string {
	lines := strings.Split(stack, newline)
	filtered := []string{}
	for _, line := range lines {
		if isExternal(line) {
			filtered = append(filtered, line)
		}
	}
	return strings.Join(filtered, newline)
}
func isExternal(line string) bool {
	if strings.Contains(line, "goconvey/convey") {
		return false
	} else if strings.Contains(line, "goconvey/execution") {
		return false
	} else if strings.Contains(line, "goconvey/gotest") {
		return false
	} else if strings.Contains(line, "goconvey/printing") {
		return false
	} else if strings.Contains(line, "goconvey/reporting") {
		return false
	}
	return true
}

const newline = "\n"

const (
	greenColor  = "\033[32m"
	yellowColor = "\033[33m"
	redColor    = "\033[31m"
	resetColor  = "\033[0m"
)

const (
	success         = "✔"
	failure         = "✘"
	error_          = "🔥"
	dotSuccess      = "."
	dotFailure      = "x"
	dotError        = "E"
	errorTemplate   = "* %s \nLine %d: - %v \n%s\n"
	failureTemplate = "* %s \nLine %d:\n%s\n"
)
<commit_msg>Colors are disabled for non-developer terminals (ie. Build Server).<commit_after>package reporting

import (
	"fmt"
	"os"
	"runtime"
	"strings"
)

type Report struct {
	File       string
	Line       int
	Failure    string
	Error      interface{}
	stackTrace string
}

func NewFailureReport(failure string) *Report {
	file, line := caller()
	stack := stackTrace()
	report := Report{file, line, failure, nil, stack}
	return &report
}
func NewErrorReport(err interface{}) *Report {
	file, line := caller()
	stack := fullStackTrace()
	report := Report{file, line, "", err, stack}
	return &report
}
func NewSuccessReport() *Report {
	file, line := caller()
	stack := stackTrace()
	report := Report{file, line, "", nil, stack}
	return &report
}

func caller() (file string, line int) {
	_, file, line, _ = runtime.Caller(3)
	return
}
func stackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, false)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func fullStackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, true)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func removeInternalEntries(stack string) string {
	lines := strings.Split(stack, newline)
	filtered := []string{}
	for _, line := range lines {
		if isExternal(line) {
			filtered = append(filtered, line)
		}
	}
	return strings.Join(filtered, newline)
}
func isExternal(line string) bool {
	if strings.Contains(line, "goconvey/convey") {
		return false
	} else if strings.Contains(line, "goconvey/execution") {
		return false
	} else if strings.Contains(line, "goconvey/gotest") {
		return false
	} else if strings.Contains(line, "goconvey/printing") {
		return false
	} else if strings.Contains(line, "goconvey/reporting") {
		return false
	}
	return true
}

const newline = "\n"

const (
	success         = "✔"
	failure         = "✘"
	error_          = "🔥"
	dotSuccess      = "."
	dotFailure      = "x"
	dotError        = "E"
	errorTemplate   = "* %s \nLine %d: - %v \n%s\n"
	failureTemplate = "* %s \nLine %d:\n%s\n"
)

var (
	greenColor  = "\033[32m"
	yellowColor = "\033[33m"
	redColor    = "\033[31m"
	resetColor  = "\033[0m"
)

func init() {
	if !xterm() {
		greenColor, yellowColor, redColor, resetColor = "", "", "", ""
	}
}

func xterm() bool {
	return strings.Contains(fmt.Sprintf("%v", os.Environ()), " TERM=xterm")
}
<|endoftext|>


<commit_before>package exstruct

import (
	"a"
)

// MyType is an exposed type.
type MyType struct {
	// A is a public member of a type provided by a dependency. This is
	// dependency bleeding.
	A a.Type
}
<commit_msg>add classical type export to the struct examples<commit_after>package exstruct

import (
	"a"
)

// MyType is an exposed type.
type MyType struct {
	// A is a public member of a type provided by a dependency. This is
	// dependency bleeding.
	A a.Type
	//B is a public member of a type provided by Go; nothing wrong here.
	B string
	//C is a public member of a type by this package; nothing wrong here.
	C MyOtherType
}

//MyOtherType is another type exposed here
type MyOtherType struct {
}
<|endoftext|>


<commit_before>package gophercloud

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"strconv"
	"time"
)

/*
Result is an internal type to be used by individual resource packages, but its
methods will be available on a wide variety of user-facing embedding types.

It acts as a base struct that other Result types, returned from request
functions, can embed for convenience. All Results capture basic information
from the HTTP transaction that was performed, including the response body,
HTTP headers, and any errors that happened.

Generally, each Result type will have an Extract method that can be used to
further interpret the result's payload in a specific context. Extensions or
providers can then provide additional extraction functions to pull out
provider- or extension-specific information as well.
*/
type Result struct {
	// Body is the payload of the HTTP response from the server. In most cases,
	// this will be the deserialized JSON structure.
	Body interface{}

	// Header contains the HTTP header structure from the original response.
	Header http.Header

	// Err is an error that occurred during the operation. It's deferred until
	// extraction to make it easier to chain the Extract call.
	Err error
}

// ExtractInto allows users to provide an object into which `Extract` will extract
// the `Result.Body`. This would be useful for OpenStack providers that have
// different fields in the response object than OpenStack proper.
func (r Result) ExtractInto(to interface{}) error {
	if r.Err != nil {
		return r.Err
	}

	if reader, ok := r.Body.(io.Reader); ok {
		if readCloser, ok := reader.(io.Closer); ok {
			defer readCloser.Close()
		}
		return json.NewDecoder(reader).Decode(to)
	}

	b, err := json.Marshal(r.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, to)

	return err
}

func (r Result) extractIntoPtr(to interface{}, label string) error {
	if r.Err != nil {
		return r.Err
	}

	t := reflect.TypeOf(to)
	if k := t.Kind(); k != reflect.Ptr {
		return fmt.Errorf("Expected pointer, got %v", k)
	}
	t = t.Elem()
	switch t.Kind() {
	case reflect.Struct, reflect.Slice:
	default:
		return fmt.Errorf("Invalid type: %v", t)
	}

	var (
		b   []byte
		err error
	)

	switch label {
	case "":
		var m interface{}
		err = r.ExtractInto(&m)
		if err != nil {
			return err
		}
		b, err = json.Marshal(m)
	default:
		var m map[string]interface{}
		err = r.ExtractInto(&m)
		if err != nil {
			return err
		}
		b, err = json.Marshal(m[label])
	}
	if err != nil {
		return err
	}

	err = json.Unmarshal(b, &to)
	return err
}

func (r Result) ExtractIntoStructPtr(to interface{}, label string) error {
	return r.extractIntoPtr(to, label)
}

func (r Result) ExtractIntoSlicePtr(to interface{}, label string) error {
	return r.extractIntoPtr(to, label)
}

// PrettyPrintJSON creates a string containing the full response body as
// pretty-printed JSON. It's useful for capturing test fixtures and for
// debugging extraction bugs. If you include its output in an issue related to
// a buggy extraction function, we will all love you forever.
func (r Result) PrettyPrintJSON() string {
	pretty, err := json.MarshalIndent(r.Body, "", "  ")
	if err != nil {
		panic(err.Error())
	}
	return string(pretty)
}

// ErrResult is an internal type to be used by individual resource packages, but
// its methods will be available on a wide variety of user-facing embedding
// types.
//
// It represents results that only contain a potential error and
// nothing else. Usually, if the operation executed successfully, the Err field
// will be nil; otherwise it will be stocked with a relevant error. Use the
// ExtractErr method
// to cleanly pull it out.
type ErrResult struct {
	Result
}

// ExtractErr is a function that extracts error information, or nil, from a result.
func (r ErrResult) ExtractErr() error {
	return r.Err
}

/*
HeaderResult is an internal type to be used by individual resource packages, but
its methods will be available on a wide variety of user-facing embedding types.

It represents a result that only contains an error (possibly nil) and an
http.Header. This is used, for example, by the objectstorage packages in
openstack, because most of the operations don't return response bodies, but do
have relevant information in headers.
*/
type HeaderResult struct {
	Result
}

// ExtractHeader will return the http.Header and error from the HeaderResult.
//
//   header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
func (r HeaderResult) ExtractInto(to interface{}) error {
	if r.Err != nil {
		return r.Err
	}

	tmpHeaderMap := map[string]string{}
	for k, v := range r.Header {
		if len(v) > 0 {
			tmpHeaderMap[k] = v[0]
		}
	}

	b, err := json.Marshal(tmpHeaderMap)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, to)

	return err
}

// RFC3339Milli describes a common time format used by some API responses.
const RFC3339Milli = "2006-01-02T15:04:05.999999Z"

type JSONRFC3339Milli time.Time

func (jt *JSONRFC3339Milli) UnmarshalJSON(data []byte) error {
	b := bytes.NewBuffer(data)
	dec := json.NewDecoder(b)
	var s string
	if err := dec.Decode(&s); err != nil {
		return err
	}
	t, err := time.Parse(RFC3339Milli, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339Milli(t)
	return nil
}

const RFC3339MilliNoZ = "2006-01-02T15:04:05.999999"

type JSONRFC3339MilliNoZ time.Time

func (jt *JSONRFC3339MilliNoZ) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(RFC3339MilliNoZ, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339MilliNoZ(t)
	return nil
}

type JSONRFC1123 time.Time

func (jt *JSONRFC1123) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(time.RFC1123, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC1123(t)
	return nil
}

type JSONUnix time.Time

func (jt *JSONUnix) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	unix, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return err
	}
	t = time.Unix(unix, 0)
	*jt = JSONUnix(t)
	return nil
}

// RFC3339NoZ is the time format used in Heat (Orchestration).
const RFC3339NoZ = "2006-01-02T15:04:05"

type JSONRFC3339NoZ time.Time

func (jt *JSONRFC3339NoZ) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(RFC3339NoZ, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339NoZ(t)
	return nil
}

/*
Link is an internal type to be used in packages of collection resources that are
paginated in a certain way.

It's a response substructure common to many paginated collection results that is
used to point to related pages. Usually, the one we care about is the one with
Rel field set to "next".
*/
type Link struct {
	Href string `json:"href"`
	Rel  string `json:"rel"`
}

/*
ExtractNextURL is an internal function useful for packages of collection
resources that are paginated in a certain way.

It attempts to extract the "next" URL from slice of Link structs, or
"" if no such URL is present.
*/
func ExtractNextURL(links []Link) (string, error) {
	var url string

	for _, l := range links {
		if l.Rel == "next" {
			url = l.Href
		}
	}

	if url == "" {
		return "", nil
	}

	return url, nil
}
<commit_msg>clean up extractIntoPtr and add comments for new exported methods<commit_after>package gophercloud

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"strconv"
	"time"
)

/*
Result is an internal type to be used by individual resource packages, but its
methods will be available on a wide variety of user-facing embedding types.

It acts as a base struct that other Result types, returned from request
functions, can embed for convenience. All Results capture basic information
from the HTTP transaction that was performed, including the response body,
HTTP headers, and any errors that happened.

Generally, each Result type will have an Extract method that can be used to
further interpret the result's payload in a specific context. Extensions or
providers can then provide additional extraction functions to pull out
provider- or extension-specific information as well.
*/
type Result struct {
	// Body is the payload of the HTTP response from the server. In most cases,
	// this will be the deserialized JSON structure.
	Body interface{}

	// Header contains the HTTP header structure from the original response.
	Header http.Header

	// Err is an error that occurred during the operation. It's deferred until
	// extraction to make it easier to chain the Extract call.
	Err error
}

// ExtractInto allows users to provide an object into which `Extract` will extract
// the `Result.Body`. This would be useful for OpenStack providers that have
// different fields in the response object than OpenStack proper.
func (r Result) ExtractInto(to interface{}) error {
	if r.Err != nil {
		return r.Err
	}

	if reader, ok := r.Body.(io.Reader); ok {
		if readCloser, ok := reader.(io.Closer); ok {
			defer readCloser.Close()
		}
		return json.NewDecoder(reader).Decode(to)
	}

	b, err := json.Marshal(r.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, to)

	return err
}

func (r Result) extractIntoPtr(to interface{}, label string) error {
	if r.Err != nil {
		return r.Err
	}

	if label == "" {
		return r.ExtractInto(&to)
	}

	var m map[string]interface{}
	err := r.ExtractInto(&m)
	if err != nil {
		return err
	}

	b, err := json.Marshal(m[label])
	if err != nil {
		return err
	}

	err = json.Unmarshal(b, &to)
	return err
}

// ExtractIntoStructPtr will unmarshal the Result (r) into the provided
// interface{} (to).
//
// `to` must be a pointer to an underlying struct type
//
// If provided, `label` will be filtered out of the response
// body prior to `r` being unmarshalled into `to`.
func (r Result) ExtractIntoStructPtr(to interface{}, label string) error {
	t := reflect.TypeOf(to)
	if k := t.Kind(); k != reflect.Ptr {
		return fmt.Errorf("Expected pointer, got %v", k)
	}
	switch t.Elem().Kind() {
	case reflect.Struct:
		return r.extractIntoPtr(to, label)
	default:
		return fmt.Errorf("Expected pointer to struct, got: %v", t)
	}
}

// ExtractIntoSlicePtr will unmarshal the Result (r) into the provided
// interface{} (to).
//
// `to` must be a pointer to an underlying slice type
//
// If provided, `label` will be filtered out of the response
// body prior to `r` being unmarshalled into `to`.
func (r Result) ExtractIntoSlicePtr(to interface{}, label string) error {
	t := reflect.TypeOf(to)
	if k := t.Kind(); k != reflect.Ptr {
		return fmt.Errorf("Expected pointer, got %v", k)
	}
	switch t.Elem().Kind() {
	case reflect.Slice:
		return r.extractIntoPtr(to, label)
	default:
		return fmt.Errorf("Expected pointer to slice, got: %v", t)
	}
}

// PrettyPrintJSON creates a string containing the full response body as
// pretty-printed JSON. It's useful for capturing test fixtures and for
// debugging extraction bugs. If you include its output in an issue related to
// a buggy extraction function, we will all love you forever.
func (r Result) PrettyPrintJSON() string {
	pretty, err := json.MarshalIndent(r.Body, "", "  ")
	if err != nil {
		panic(err.Error())
	}
	return string(pretty)
}

// ErrResult is an internal type to be used by individual resource packages, but
// its methods will be available on a wide variety of user-facing embedding
// types.
//
// It represents results that only contain a potential error and
// nothing else. Usually, if the operation executed successfully, the Err field
// will be nil; otherwise it will be stocked with a relevant error. Use the
// ExtractErr method
// to cleanly pull it out.
type ErrResult struct {
	Result
}

// ExtractErr is a function that extracts error information, or nil, from a result.
func (r ErrResult) ExtractErr() error {
	return r.Err
}

/*
HeaderResult is an internal type to be used by individual resource packages, but
its methods will be available on a wide variety of user-facing embedding types.

It represents a result that only contains an error (possibly nil) and an
http.Header. This is used, for example, by the objectstorage packages in
openstack, because most of the operations don't return response bodies, but do
have relevant information in headers.
*/
type HeaderResult struct {
	Result
}

// ExtractHeader will return the http.Header and error from the HeaderResult.
//
//   header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
func (r HeaderResult) ExtractInto(to interface{}) error {
	if r.Err != nil {
		return r.Err
	}

	tmpHeaderMap := map[string]string{}
	for k, v := range r.Header {
		if len(v) > 0 {
			tmpHeaderMap[k] = v[0]
		}
	}

	b, err := json.Marshal(tmpHeaderMap)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, to)

	return err
}

// RFC3339Milli describes a common time format used by some API responses.
const RFC3339Milli = "2006-01-02T15:04:05.999999Z"

type JSONRFC3339Milli time.Time

func (jt *JSONRFC3339Milli) UnmarshalJSON(data []byte) error {
	b := bytes.NewBuffer(data)
	dec := json.NewDecoder(b)
	var s string
	if err := dec.Decode(&s); err != nil {
		return err
	}
	t, err := time.Parse(RFC3339Milli, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339Milli(t)
	return nil
}

const RFC3339MilliNoZ = "2006-01-02T15:04:05.999999"

type JSONRFC3339MilliNoZ time.Time

func (jt *JSONRFC3339MilliNoZ) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(RFC3339MilliNoZ, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339MilliNoZ(t)
	return nil
}

type JSONRFC1123 time.Time

func (jt *JSONRFC1123) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(time.RFC1123, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC1123(t)
	return nil
}

type JSONUnix time.Time

func (jt *JSONUnix) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	unix, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return err
	}
	t = time.Unix(unix, 0)
	*jt = JSONUnix(t)
	return nil
}

// RFC3339NoZ is the time format used in Heat (Orchestration).
const RFC3339NoZ = "2006-01-02T15:04:05"

type JSONRFC3339NoZ time.Time

func (jt *JSONRFC3339NoZ) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	if s == "" {
		return nil
	}
	t, err := time.Parse(RFC3339NoZ, s)
	if err != nil {
		return err
	}
	*jt = JSONRFC3339NoZ(t)
	return nil
}

/*
Link is an internal type to be used in packages of collection resources that are
paginated in a certain way.

It's a response substructure common to many paginated collection results that is
used to point to related pages. Usually, the one we care about is the one with
Rel field set to "next".
*/
type Link struct {
	Href string `json:"href"`
	Rel  string `json:"rel"`
}

/*
ExtractNextURL is an internal function useful for packages of collection
resources that are paginated in a certain way.

It attempts to extract the "next" URL from slice of Link structs, or
"" if no such URL is present.
*/
func ExtractNextURL(links []Link) (string, error) {
	var url string

	for _, l := range links {
		if l.Rel == "next" {
			url = l.Href
		}
	}

	if url == "" {
		return "", nil
	}

	return url, nil
}
<|endoftext|>


<commit_before>package gostore

import (
	"fmt"
	r "github.com/dancannon/gorethink"
	"github.com/dustin/gojson"
	"github.com/mgutz/logxi/v1"
	"strings"
	"github.com/jinzhu/now"
	"github.com/asaskevich/govalidator"
	"time"
)

var logger = log.New("gostore.rethink")

func NewRethinkObjectStore(session *r.Session, database string) RethinkStore {
	s := RethinkStore{session, database}
	s.CreateDatabase()
	return s
}

type RethinkStore struct {
	Session  *r.Session
	Database string
}

type RethinkRows struct {
	cursor *r.Cursor
}

func (s RethinkRows) Next(dst interface{}) (bool, error) {
	if !s.cursor.Next(dst) {
		//		logger.Debug("Error getting next", "err", s.cursor.Err(), "isNil", s.cursor.IsNil())
		return false, s.cursor.Err()
	}
	return true, nil
}

func (s RethinkRows) Close() {
	s.cursor.Close()
}

func (s RethinkStore) CreateDatabase() (err error) {
	return r.DBCreate(s.Database).Exec(s.Session)
}

func (s RethinkStore) GetStore() interface{} {
	return s.Session
}

func (rs RethinkStore) CreateTable(store string, schema interface{}) (err error) {
	_, err = r.DB(rs.Database).TableCreate(store).RunWrite(rs.Session)
	//also create indexes
	if schema != nil {
		s := schema.(map[string]interface{})
		if indexes, ok := s["index"].(map[string]interface{}); ok {
			for name, index_vals := range indexes {
				if _, ok := index_vals.([]string); ok {
					//				if _, err = r.DB(rs.Database).Table(store).IndexCreate(name).RunWrite(rs.Session); err != nil{
					//					return
					//				}
				} else {
					if _, err = r.DB(rs.Database).Table(store).IndexCreate(name).Run(rs.Session); err != nil {
						// logger.Warn("cannot create index [" + name + "] in " + store)
						println("cannot create index")
						println(err.Error())

					} else {
						logger.Info("created index [" + name + "] in " + store)
					}
				}
			}
		}
	}

	return
}

type TermOperators map[string]func(args ...interface{}) interface{}

var filterOps TermOperators = TermOperators{
	">": func(args ...interface{}) interface{} {
		//this also handles args
		vals := strings.Split(args[1].(string), "|")
		baseTerm := args[0].(r.Term)
		if len(vals) > 0{
			//check type
			if vals[1] == "dt"{
				if it, err := govalidator.ToInt(vals[0]); err == nil{
					logger.Info("> op date", "time", it)
					return baseTerm.Gt(r.EpochTime(it))
				}
//				t, err := now.Parse(vals[0])
				if t, err := time.Parse(
					time.RFC3339,
					vals[0]);err == nil {
					return baseTerm.Gt(r.EpochTime(t.Unix()))
				}
				if t, err := now.Parse(vals[0]);err == nil {
					return baseTerm.Gt(r.EpochTime(t.Unix()))
				}
			}
		}
		return baseTerm.Gt(vals[0])
	},
	"<": func(args ...interface{}) interface{} {
		baseTerm := args[0].(r.Term)
		return baseTerm.Lt(args[1])
	},
}

// TODO: Transforms filter args into rethinkdb filter args
func (s RethinkStore) ParseFilterArgs(filter map[string]interface{}, indexes []string) r.Term {
	var (
		t r.Term = r.And(1)
	)
	//TODO: Optimize this by passing indexes as well as field types
	for k, v := range filter {
		val := v.(string)
		first := string([]rune(val)[0])
		if strings.Contains("/>!<", first) {
			if op, ok := filterOps[first]; ok {
//				var rv interface{}
				tv := string([]rune(val)[1:])
//				if _rv, err := govalidator.ToInt(tv); err == nil{
//					rv = _rv
//				}else{
//					rv = tv
//				}
				t = t.And(op(r.Row.Field(k), tv))
			}
		}else{
//			var rv interface{}
//			if _rv, err := govalidator.ToInt(v.(string)); err == nil{
//				rv = _rv
//			}else{
//				rv = v
//			}
			t = t.And(r.Row.Field(k).Eq(v))
		}
	}
	println(t.String())
	return t
}

func (s RethinkStore) All(count int, skip int, store string) (rrows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).OrderBy(r.OrderByOpts{Index: r.Desc("id")}).Run(s.Session)
	if err != nil {
		return
	}
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) AllCursor(store string) (ObjectRows, error) {
	result, err := r.DB(s.Database).Table(store).Run(s.Session)
	if err != nil {
		return nil, err
	}
	defer result.Close()
	return RethinkRows{result}, nil
}

//Before will retrieve all old rows that were created before the row with id was created
// [1, 2, 3, 4], before 2 will return [3, 4]
//r.db('worksmart').table('store').orderBy({'index': r.desc('id')}).filter(r.row('schemas')
// .eq('osiloke_tsaboin_silverbird').and(r.row('id').lt('55b54e93f112a16514000057')))
// .pluck('schemas', 'id','tid', 'timestamp', 'created_at').limit(100)
func (s RethinkStore) Before(id string, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field("id").Lt(id)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	//	result.All(dst)
	rows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterBefore(id string, filter map[string]interface{}, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Between(
		r.MinVal, id, r.BetweenOpts{RightBound: "closed"}).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Limit(count).Run(s.Session)
	if err != nil {
		return
	}
	//	var dst interface{}
	f, _ := json.Marshal(filter)
	logger.Debug("FilterBefore", "query",
		fmt.Sprintf("r.db('%s').table('%s').between(r.minval, '%s').orderBy({index:r.desc('id')}).filter(%s).limit(%d)",
			s.Database, store, id, string(f), count))
	rows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterBeforeCount(id string, filter map[string]interface{}, count int, skip int, store string) (int64, error) {
	result, err := r.DB(s.Database).Table(store).Between(
		r.MinVal, id).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Count().Run(s.Session)
	defer result.Close()

	var cnt int64
	if err = result.One(&cnt); err != nil {
		return 0, ErrNotFound
	}
	return cnt, nil
}

func (s RethinkStore) FilterSince(id string, filter map[string]interface{}, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Between(
		id, r.MaxVal, r.BetweenOpts{LeftBound: "open", Index: "id"}).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Limit(count).Run(s.Session)
	if err != nil {
		return
	}
	//	result.All(dst)
	rows = RethinkRows{result}
	return
}

//This will retrieve all new rows that were created since the row with id was created
// [1, 2, 3, 4], since 2 will return [1]
func (s RethinkStore) Since(id string, count, skip int, store string) (rrows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field("id").Gt(id)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	//	result.All(dst)
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) Get(id, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Get(id).Run(s.Session)
	if err != nil {
		//		logger.Error("Get", "err", err)
		return
	}
	defer result.Close()
	if result.Err() != nil {
		return result.Err()
	}
	if err = result.One(dst); err == r.ErrEmptyResult {
		//		logger.Error("Get", "err", err)
		return ErrNotFound
	}
	return nil
}

func (s RethinkStore) Save(store string, src interface{}) (key string, err error) {
	result, err := r.DB(s.Database).Table(store).Insert(src, r.InsertOpts{Durability: "soft"}).RunWrite(s.Session)
	if err != nil {
		if strings.Contains(err.Error(), "Duplicate primary key") {
			err = ErrDuplicatePk
		}
		return
	}
	if len(result.GeneratedKeys) > 0 {
		key = result.GeneratedKeys[0]
	}
	return

}

func (s RethinkStore) Update(id string, store string, src interface{}) (err error) {
	_, err = r.DB(s.Database).Table(store).Get(id).Update(src, r.UpdateOpts{Durability: "soft"}).RunWrite(s.Session)
	return

}

func (s RethinkStore) Delete(id string, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Get(id).Delete(r.DeleteOpts{Durability: "hard"}).RunWrite(s.Session)
	return
}

func (s RethinkStore) Stats(store string) (map[string]interface{}, error) {
	result, err := r.DB(s.Database).Table(store).Count().Run(s.Session)
	if err != nil {
		return nil, err
	}
	defer result.Close()
	var cnt int64
	if err = result.One(&cnt); err != nil {
		return nil, ErrNotFound
	}
	return map[string]interface{}{"count": cnt}, nil
}

func (s RethinkStore) GetByField(name, val, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field(name).Eq(val)).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterUpdate(filter map[string]interface{}, src interface{}, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Limit(1).Update(src, r.UpdateOpts{Durability: "soft"}).RunWrite(s.Session)
	return
}

func (s RethinkStore) FilterGet(filter map[string]interface{}, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(filter).Limit(1).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterGetAll(filter map[string]interface{}, count int, skip int, store string) (rrows ObjectRows, err error) {
	//	logger.Debug("Filter get all", "store", store, "filter", filter)
	result, err := r.DB(s.Database).Table(store).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(s.ParseFilterArgs(filter, nil)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterDelete(filter map[string]interface{}, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Delete(r.DeleteOpts{Durability: "soft"}).RunWrite(s.Session)
	if err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterCount(filter map[string]interface{}, store string) (int64, error) {
	result, err := r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Count().Run(s.Session)
	if err != nil {
		return 0, err
	}
	defer result.Close()
	var cnt int64
	if err = result.One(&cnt); err != nil {
		return 0, ErrNotFound
	}
	return cnt, nil
}

func (s RethinkStore) GetByFieldsByField(name, val, store string, fields []string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field(name).Eq(val)).Pluck(fields).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) Close() {
	s.Session.Close()
}
<commit_msg>add some new filter operators<commit_after>package gostore

import (
	"fmt"
	"github.com/asaskevich/govalidator"
	r "github.com/dancannon/gorethink"
	"github.com/dustin/gojson"
	"github.com/jinzhu/now"
	"github.com/mgutz/logxi/v1"
	"strings"
	"time"
)

var logger = log.New("gostore.rethink")

func NewRethinkObjectStore(session *r.Session, database string) RethinkStore {
	s := RethinkStore{session, database}
	s.CreateDatabase()
	return s
}

type RethinkStore struct {
	Session  *r.Session
	Database string
}

type RethinkRows struct {
	cursor *r.Cursor
}

func (s RethinkRows) Next(dst interface{}) (bool, error) {
	if !s.cursor.Next(dst) {
		//		logger.Debug("Error getting next", "err", s.cursor.Err(), "isNil", s.cursor.IsNil())
		return false, s.cursor.Err()
	}
	return true, nil
}

func (s RethinkRows) Close() {
	s.cursor.Close()
}

func (s RethinkStore) CreateDatabase() (err error) {
	return r.DBCreate(s.Database).Exec(s.Session)
}

func (s RethinkStore) GetStore() interface{} {
	return s.Session
}

func (rs RethinkStore) CreateTable(store string, schema interface{}) (err error) {
	_, err = r.DB(rs.Database).TableCreate(store).RunWrite(rs.Session)
	//also create indexes
	if schema != nil {
		s := schema.(map[string]interface{})
		if indexes, ok := s["index"].(map[string]interface{}); ok {
			for name, index_vals := range indexes {
				if _, ok := index_vals.([]string); ok {
					//				if _, err = r.DB(rs.Database).Table(store).IndexCreate(name).RunWrite(rs.Session); err != nil{
					//					return
					//				}
				} else {
					if _, err = r.DB(rs.Database).Table(store).IndexCreate(name).Run(rs.Session); err != nil {
						// logger.Warn("cannot create index [" + name + "] in " + store)
						println("cannot create index")
						println(err.Error())

					} else {
						logger.Info("created index [" + name + "] in " + store)
					}
				}
			}
		}
	}

	return
}

type TermOperators map[string]func(args ...interface{}) interface{}

var filterOps TermOperators = TermOperators{
	"~": func(args ...interface{}) interface{} {
		vals := strings.Split(args[1].(string), "|")
		baseTerm := args[0].(r.Term)
		if len(vals) > 0 {

		}
		return baseTerm.Match(vals[0])
	},
	">": func(args ...interface{}) interface{} {
		//this also handles args
		vals := strings.Split(args[1].(string), "|")
		baseTerm := args[0].(r.Term)
		if len(vals) > 0 {
			//check type
			if vals[1] == "dt" {
				if it, err := govalidator.ToInt(vals[0]); err == nil {
					logger.Info("> op date", "time", it)
					return baseTerm.Gt(r.EpochTime(it))
				}
				//				t, err := now.Parse(vals[0])
				if t, err := time.Parse(
					time.RFC3339,
					vals[0]); err == nil {
					return baseTerm.Gt(r.EpochTime(t.Unix()))
				}
				if t, err := now.Parse(vals[0]); err == nil {
					return baseTerm.Gt(r.EpochTime(t.Unix()))
				}
			}
		}
		return baseTerm.Gt(vals[0])
	},
	"<": func(args ...interface{}) interface{} {
		baseTerm := args[0].(r.Term)
		return baseTerm.Lt(args[1])
	},
}

// TODO: Transforms filter args into rethinkdb filter args
func (s RethinkStore) ParseFilterArgs(filter map[string]interface{}, indexes []string) r.Term {
	var (
		t r.Term = r.And(1)
	)
	//TODO: Optimize this by passing indexes as well as field types
	for k, v := range filter {
		val := v.(string)
		first := string([]rune(val)[0])
		// if strings.Contains("/>!<~", first) {
		if op, ok := filterOps[first]; ok {
			//				var rv interface{}
			tv := string([]rune(val)[1:])
			//				if _rv, err := govalidator.ToInt(tv); err == nil{
			//					rv = _rv
			//				}else{
			//					rv = tv
			//				}
			t = t.And(op(r.Row.Field(k), tv))
		} else {
			//			var rv interface{}
			//			if _rv, err := govalidator.ToInt(v.(string)); err == nil{
			//				rv = _rv
			//			}else{
			//				rv = v
			//			}
			t = t.And(r.Row.Field(k).Eq(v))
		}
	}
	println(t.String())
	return t
}

func (s RethinkStore) All(count int, skip int, store string) (rrows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).OrderBy(r.OrderByOpts{Index: r.Desc("id")}).Run(s.Session)
	if err != nil {
		return
	}
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) AllCursor(store string) (ObjectRows, error) {
	result, err := r.DB(s.Database).Table(store).Run(s.Session)
	if err != nil {
		return nil, err
	}
	defer result.Close()
	return RethinkRows{result}, nil
}

//Before will retrieve all old rows that were created before the row with id was created
// [1, 2, 3, 4], before 2 will return [3, 4]
//r.db('worksmart').table('store').orderBy({'index': r.desc('id')}).filter(r.row('schemas')
// .eq('osiloke_tsaboin_silverbird').and(r.row('id').lt('55b54e93f112a16514000057')))
// .pluck('schemas', 'id','tid', 'timestamp', 'created_at').limit(100)
func (s RethinkStore) Before(id string, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field("id").Lt(id)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	//	result.All(dst)
	rows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterBefore(id string, filter map[string]interface{}, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Between(
		r.MinVal, id, r.BetweenOpts{RightBound: "closed"}).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Limit(count).Run(s.Session)
	if err != nil {
		return
	}
	//	var dst interface{}
	f, _ := json.Marshal(filter)
	logger.Debug("FilterBefore", "query",
		fmt.Sprintf("r.db('%s').table('%s').between(r.minval, '%s').orderBy({index:r.desc('id')}).filter(%s).limit(%d)",
			s.Database, store, id, string(f), count))
	rows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterBeforeCount(id string, filter map[string]interface{}, count int, skip int, store string) (int64, error) {
	result, err := r.DB(s.Database).Table(store).Between(
		r.MinVal, id).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Count().Run(s.Session)
	defer result.Close()

	var cnt int64
	if err = result.One(&cnt); err != nil {
		return 0, ErrNotFound
	}
	return cnt, nil
}

func (s RethinkStore) FilterSince(id string, filter map[string]interface{}, count int, skip int, store string) (rows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Between(
		id, r.MaxVal, r.BetweenOpts{LeftBound: "open", Index: "id"}).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(
		s.ParseFilterArgs(filter, nil)).Limit(count).Run(s.Session)
	if err != nil {
		return
	}
	//	result.All(dst)
	rows = RethinkRows{result}
	return
}

//This will retrieve all new rows that were created since the row with id was created
// [1, 2, 3, 4], since 2 will return [1]
func (s RethinkStore) Since(id string, count, skip int, store string) (rrows ObjectRows, err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field("id").Gt(id)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	//	result.All(dst)
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) Get(id, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Get(id).Run(s.Session)
	if err != nil {
		//		logger.Error("Get", "err", err)
		return
	}
	defer result.Close()
	if result.Err() != nil {
		return result.Err()
	}
	if err = result.One(dst); err == r.ErrEmptyResult {
		//		logger.Error("Get", "err", err)
		return ErrNotFound
	}
	return nil
}

func (s RethinkStore) Save(store string, src interface{}) (key string, err error) {
	result, err := r.DB(s.Database).Table(store).Insert(src, r.InsertOpts{Durability: "soft"}).RunWrite(s.Session)
	if err != nil {
		if strings.Contains(err.Error(), "Duplicate primary key") {
			err = ErrDuplicatePk
		}
		return
	}
	if len(result.GeneratedKeys) > 0 {
		key = result.GeneratedKeys[0]
	}
	return

}

func (s RethinkStore) Update(id string, store string, src interface{}) (err error) {
	_, err = r.DB(s.Database).Table(store).Get(id).Update(src, r.UpdateOpts{Durability: "soft"}).RunWrite(s.Session)
	return

}

func (s RethinkStore) Delete(id string, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Get(id).Delete(r.DeleteOpts{Durability: "hard"}).RunWrite(s.Session)
	return
}

func (s RethinkStore) Stats(store string) (map[string]interface{}, error) {
	result, err := r.DB(s.Database).Table(store).Count().Run(s.Session)
	if err != nil {
		return nil, err
	}
	defer result.Close()
	var cnt int64
	if err = result.One(&cnt); err != nil {
		return nil, ErrNotFound
	}
	return map[string]interface{}{"count": cnt}, nil
}

func (s RethinkStore) GetByField(name, val, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field(name).Eq(val)).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterUpdate(filter map[string]interface{}, src interface{}, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Limit(1).Update(src, r.UpdateOpts{Durability: "soft"}).RunWrite(s.Session)
	return
}

func (s RethinkStore) FilterGet(filter map[string]interface{}, store string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(filter).Limit(1).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterGetAll(filter map[string]interface{}, count int, skip int, store string) (rrows ObjectRows, err error) {
	//	logger.Debug("Filter get all", "store", store, "filter", filter)
	result, err := r.DB(s.Database).Table(store).OrderBy(
		r.OrderByOpts{Index: r.Desc("id")}).Filter(s.ParseFilterArgs(filter, nil)).Limit(count).Skip(skip).Run(s.Session)
	if err != nil {
		return
	}
	rrows = RethinkRows{result}
	return
}

func (s RethinkStore) FilterDelete(filter map[string]interface{}, store string) (err error) {
	_, err = r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Delete(r.DeleteOpts{Durability: "soft"}).RunWrite(s.Session)
	if err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) FilterCount(filter map[string]interface{}, store string) (int64, error) {
	result, err := r.DB(s.Database).Table(store).Filter(s.ParseFilterArgs(filter, nil)).Count().Run(s.Session)
	if err != nil {
		return 0, err
	}
	defer result.Close()
	var cnt int64
	if err = result.One(&cnt); err != nil {
		return 0, ErrNotFound
	}
	return cnt, nil
}

func (s RethinkStore) GetByFieldsByField(name, val, store string, fields []string, dst interface{}) (err error) {
	result, err := r.DB(s.Database).Table(store).Filter(r.Row.Field(name).Eq(val)).Pluck(fields).Run(s.Session)
	if err != nil {
		return
	}
	defer result.Close()
	if err = result.One(dst); err == r.ErrEmptyResult {
		return ErrNotFound
	}
	return
}

func (s RethinkStore) Close() {
	s.Session.Close()
}
<|endoftext|>


<commit_before>// Copied from the go source code src/cmd/gofmt/rewrite.go

// Copyright 2009 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.

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"reflect"
	"strings"
	"unicode"
	"unicode/utf8"
)

/*
func initRewrite() {
	if *rewriteRule == "" {
		rewrite = nil // disable any previous rewrite
		return
	}
	f := strings.Split(*rewriteRule, "->")
	if len(f) != 2 {
		fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
		os.Exit(2)
	}
	pattern := parseExpr(f[0], "pattern")
	replace := parseExpr(f[1], "replacement")
	rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }
}
*/

// parseExpr parses s as an expression.
// It might make sense to expand this to allow statement patterns,
// but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like.
func parseExpr(s string, what string) ast.Expr {
	x, err := parser.ParseExpr(s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
		os.Exit(2)
	}
	return x
}

// Keep this function for debugging.
/*
func dump(msg string, val reflect.Value) {
	fmt.Printf("%s:\n", msg)
	ast.Print(fset, val.Interface())
	fmt.Println()
}
*/

// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
func rewriteFile(fileSet *token.FileSet, pattern, replace ast.Expr, p *ast.File) *ast.File {
	cmap := ast.NewCommentMap(fileSet, p, p.Comments)
	m := make(map[string]reflect.Value)
	pat := reflect.ValueOf(pattern)
	repl := reflect.ValueOf(replace)
	var f func(val reflect.Value) reflect.Value // f is recursive
	f = func(val reflect.Value) reflect.Value {
		// don't bother if val is invalid to start with
		if !val.IsValid() {
			return reflect.Value{}
		}
		for k := range m {
			delete(m, k)
		}
		val = apply(f, val)
		if match(m, pat, val) {
			val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
		}
		return val
	}
	r := apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
	r.Comments = cmap.Filter(r).Comments() // recreate comments list
	return r
}

// setValue is a wrapper for x.SetValue(y); it protects
// the caller from panics if x cannot be changed to y.
func setValue(x, y reflect.Value) {
	// don't bother if y is invalid to start with
	if !y.IsValid() {
		return
	}
	defer func() {
		if x := recover(); x != nil {
			if s, ok := x.(string); ok &&
				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
				// x cannot be set to y - ignore this rewrite
				return
			}
			panic(x)
		}
	}()
	x.Set(y)
}

// Values/types for special cases.
var (
	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))

	identType     = reflect.TypeOf((*ast.Ident)(nil))
	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
	positionType  = reflect.TypeOf(token.NoPos)
	scopePtrType  = reflect.TypeOf((*ast.Scope)(nil))
)

// apply replaces each AST field x in val with f(x), returning val.
// To avoid extra conversions, f operates on the reflect.Value form.
func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
	if !val.IsValid() {
		return reflect.Value{}
	}

	// *ast.Objects introduce cycles and are likely incorrect after
	// rewrite; don't follow them but replace with nil instead
	if val.Type() == objectPtrType {
		return objectPtrNil
	}

	// similarly for scopes: they are likely incorrect after a rewrite;
	// replace them with nil
	if val.Type() == scopePtrType {
		return scopePtrNil
	}

	switch v := reflect.Indirect(val); v.Kind() {
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			e := v.Index(i)
			setValue(e, f(e))
		}
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			e := v.Field(i)
			setValue(e, f(e))
		}
	case reflect.Interface:
		e := v.Elem()
		setValue(v, f(e))
	}
	return val
}

func isWildcard(s string) bool {
	rune, size := utf8.DecodeRuneInString(s)
	return size == len(s) && unicode.IsLower(rune)
}

// match returns true if pattern matches val,
// recording wildcard submatches in m.
// If m == nil, match checks whether pattern == val.
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
	// Wildcard matches any expression.  If it appears multiple
	// times in the pattern, it must match the same expression
	// each time.
	if m != nil && pattern.IsValid() && pattern.Type() == identType {
		name := pattern.Interface().(*ast.Ident).Name
		if isWildcard(name) && val.IsValid() {
			// wildcards only match valid (non-nil) expressions.
			if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
				if old, ok := m[name]; ok {
					return match(nil, old, val)
				}
				m[name] = val
				return true
			}
		}
	}

	// Otherwise, pattern and val must match recursively.
	if !pattern.IsValid() || !val.IsValid() {
		return !pattern.IsValid() && !val.IsValid()
	}
	if pattern.Type() != val.Type() {
		return false
	}

	// Special cases.
	switch pattern.Type() {
	case identType:
		// For identifiers, only the names need to match
		// (and none of the other *ast.Object information).
		// This is a common case, handle it all here instead
		// of recursing down any further via reflection.
		p := pattern.Interface().(*ast.Ident)
		v := val.Interface().(*ast.Ident)
		return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
	case objectPtrType, positionType:
		// object pointers and token positions don't need to match
		return true
	}

	p := reflect.Indirect(pattern)
	v := reflect.Indirect(val)
	if !p.IsValid() || !v.IsValid() {
		return !p.IsValid() && !v.IsValid()
	}

	switch p.Kind() {
	case reflect.Slice:
		if p.Len() != v.Len() {
			return false
		}
		for i := 0; i < p.Len(); i++ {
			if !match(m, p.Index(i), v.Index(i)) {
				return false
			}
		}
		return true

	case reflect.Struct:
		if p.NumField() != v.NumField() {
			return false
		}
		for i := 0; i < p.NumField(); i++ {
			if !match(m, p.Field(i), v.Field(i)) {
				return false
			}
		}
		return true

	case reflect.Interface:
		return match(m, p.Elem(), v.Elem())
	}

	// Handle token integers, etc.
	return p.Interface() == v.Interface()
}

// subst returns a copy of pattern with values from m substituted in place
// of wildcards and pos used as the position of tokens from the pattern.
// if m == nil, subst returns a copy of pattern and doesn't change the line
// number information.
func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
	if !pattern.IsValid() {
		return reflect.Value{}
	}

	// Wildcard gets replaced with map value.
	if m != nil && pattern.Type() == identType {
		name := pattern.Interface().(*ast.Ident).Name
		if isWildcard(name) {
			if old, ok := m[name]; ok {
				return subst(nil, old, reflect.Value{})
			}
		}
	}

	if pos.IsValid() && pattern.Type() == positionType {
		// use new position only if old position was valid in the first place
		if old := pattern.Interface().(token.Pos); !old.IsValid() {
			return pattern
		}
		return pos
	}

	// Otherwise copy.
	switch p := pattern; p.Kind() {
	case reflect.Slice:
		v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
		for i := 0; i < p.Len(); i++ {
			v.Index(i).Set(subst(m, p.Index(i), pos))
		}
		return v

	case reflect.Struct:
		v := reflect.New(p.Type()).Elem()
		for i := 0; i < p.NumField(); i++ {
			v.Field(i).Set(subst(m, p.Field(i), pos))
		}
		return v

	case reflect.Ptr:
		v := reflect.New(p.Type()).Elem()
		if elem := p.Elem(); elem.IsValid() {
			v.Set(subst(m, elem, pos).Addr())
		}
		return v

	case reflect.Interface:
		v := reflect.New(p.Type()).Elem()
		if elem := p.Elem(); elem.IsValid() {
			v.Set(subst(m, elem, pos))
		}
		return v
	}

	return pattern
}
<commit_msg>Apply updated rewrite.go from gofmt from go 1.3.1<commit_after>// Copied from the go source code src/cmd/gofmt/rewrite.go

// Copyright 2009 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.

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"reflect"
	"strings"
	"unicode"
	"unicode/utf8"
)

/*
func initRewrite() {
	if *rewriteRule == "" {
		rewrite = nil // disable any previous rewrite
		return
	}
	f := strings.Split(*rewriteRule, "->")
	if len(f) != 2 {
		fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
		os.Exit(2)
	}
	pattern := parseExpr(f[0], "pattern")
	replace := parseExpr(f[1], "replacement")
	rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }
}
*/

// parseExpr parses s as an expression.
// It might make sense to expand this to allow statement patterns,
// but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like.
func parseExpr(s string, what string) ast.Expr {
	x, err := parser.ParseExpr(s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
		os.Exit(2)
	}
	return x
}

// Keep this function for debugging.
/*
func dump(msg string, val reflect.Value) {
	fmt.Printf("%s:\n", msg)
	ast.Print(fileSet, val.Interface())
	fmt.Println()
}
*/

// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
func rewriteFile(fileSet *token.FileSet, pattern, replace ast.Expr, p *ast.File) *ast.File {
	cmap := ast.NewCommentMap(fileSet, p, p.Comments)
	m := make(map[string]reflect.Value)
	pat := reflect.ValueOf(pattern)
	repl := reflect.ValueOf(replace)

	var rewriteVal func(val reflect.Value) reflect.Value
	rewriteVal = func(val reflect.Value) reflect.Value {
		// don't bother if val is invalid to start with
		if !val.IsValid() {
			return reflect.Value{}
		}
		for k := range m {
			delete(m, k)
		}
		val = apply(rewriteVal, val)
		if match(m, pat, val) {
			val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
		}
		return val
	}

	r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File)
	r.Comments = cmap.Filter(r).Comments() // recreate comments list
	return r
}

// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y.
func set(x, y reflect.Value) {
	// don't bother if x cannot be set or y is invalid
	if !x.CanSet() || !y.IsValid() {
		return
	}
	defer func() {
		if x := recover(); x != nil {
			if s, ok := x.(string); ok &&
				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
				// x cannot be set to y - ignore this rewrite
				return
			}
			panic(x)
		}
	}()
	x.Set(y)
}

// Values/types for special cases.
var (
	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))

	identType     = reflect.TypeOf((*ast.Ident)(nil))
	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
	positionType  = reflect.TypeOf(token.NoPos)
	callExprType  = reflect.TypeOf((*ast.CallExpr)(nil))
	scopePtrType  = reflect.TypeOf((*ast.Scope)(nil))
)

// apply replaces each AST field x in val with f(x), returning val.
// To avoid extra conversions, f operates on the reflect.Value form.
func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
	if !val.IsValid() {
		return reflect.Value{}
	}

	// *ast.Objects introduce cycles and are likely incorrect after
	// rewrite; don't follow them but replace with nil instead
	if val.Type() == objectPtrType {
		return objectPtrNil
	}

	// similarly for scopes: they are likely incorrect after a rewrite;
	// replace them with nil
	if val.Type() == scopePtrType {
		return scopePtrNil
	}

	switch v := reflect.Indirect(val); v.Kind() {
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			e := v.Index(i)
			set(e, f(e))
		}
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			e := v.Field(i)
			set(e, f(e))
		}
	case reflect.Interface:
		e := v.Elem()
		set(v, f(e))
	}
	return val
}

func isWildcard(s string) bool {
	rune, size := utf8.DecodeRuneInString(s)
	return size == len(s) && unicode.IsLower(rune)
}

// match returns true if pattern matches val,
// recording wildcard submatches in m.
// If m == nil, match checks whether pattern == val.
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
	// Wildcard matches any expression.  If it appears multiple
	// times in the pattern, it must match the same expression
	// each time.
	if m != nil && pattern.IsValid() && pattern.Type() == identType {
		name := pattern.Interface().(*ast.Ident).Name
		if isWildcard(name) && val.IsValid() {
			// wildcards only match valid (non-nil) expressions.
			if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
				if old, ok := m[name]; ok {
					return match(nil, old, val)
				}
				m[name] = val
				return true
			}
		}
	}

	// Otherwise, pattern and val must match recursively.
	if !pattern.IsValid() || !val.IsValid() {
		return !pattern.IsValid() && !val.IsValid()
	}
	if pattern.Type() != val.Type() {
		return false
	}

	// Special cases.
	switch pattern.Type() {
	case identType:
		// For identifiers, only the names need to match
		// (and none of the other *ast.Object information).
		// This is a common case, handle it all here instead
		// of recursing down any further via reflection.
		p := pattern.Interface().(*ast.Ident)
		v := val.Interface().(*ast.Ident)
		return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
	case objectPtrType, positionType:
		// object pointers and token positions always match
		return true
	case callExprType:
		// For calls, the Ellipsis fields (token.Position) must
		// match since that is how f(x) and f(x...) are different.
		// Check them here but fall through for the remaining fields.
		p := pattern.Interface().(*ast.CallExpr)
		v := val.Interface().(*ast.CallExpr)
		if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
			return false
		}
	}

	p := reflect.Indirect(pattern)
	v := reflect.Indirect(val)
	if !p.IsValid() || !v.IsValid() {
		return !p.IsValid() && !v.IsValid()
	}

	switch p.Kind() {
	case reflect.Slice:
		if p.Len() != v.Len() {
			return false
		}
		for i := 0; i < p.Len(); i++ {
			if !match(m, p.Index(i), v.Index(i)) {
				return false
			}
		}
		return true

	case reflect.Struct:
		if p.NumField() != v.NumField() {
			return false
		}
		for i := 0; i < p.NumField(); i++ {
			if !match(m, p.Field(i), v.Field(i)) {
				return false
			}
		}
		return true

	case reflect.Interface:
		return match(m, p.Elem(), v.Elem())
	}

	// Handle token integers, etc.
	return p.Interface() == v.Interface()
}

// subst returns a copy of pattern with values from m substituted in place
// of wildcards and pos used as the position of tokens from the pattern.
// if m == nil, subst returns a copy of pattern and doesn't change the line
// number information.
func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
	if !pattern.IsValid() {
		return reflect.Value{}
	}

	// Wildcard gets replaced with map value.
	if m != nil && pattern.Type() == identType {
		name := pattern.Interface().(*ast.Ident).Name
		if isWildcard(name) {
			if old, ok := m[name]; ok {
				return subst(nil, old, reflect.Value{})
			}
		}
	}

	if pos.IsValid() && pattern.Type() == positionType {
		// use new position only if old position was valid in the first place
		if old := pattern.Interface().(token.Pos); !old.IsValid() {
			return pattern
		}
		return pos
	}

	// Otherwise copy.
	switch p := pattern; p.Kind() {
	case reflect.Slice:
		v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
		for i := 0; i < p.Len(); i++ {
			v.Index(i).Set(subst(m, p.Index(i), pos))
		}
		return v

	case reflect.Struct:
		v := reflect.New(p.Type()).Elem()
		for i := 0; i < p.NumField(); i++ {
			v.Field(i).Set(subst(m, p.Field(i), pos))
		}
		return v

	case reflect.Ptr:
		v := reflect.New(p.Type()).Elem()
		if elem := p.Elem(); elem.IsValid() {
			v.Set(subst(m, elem, pos).Addr())
		}
		return v

	case reflect.Interface:
		v := reflect.New(p.Type()).Elem()
		if elem := p.Elem(); elem.IsValid() {
			v.Set(subst(m, elem, pos))
		}
		return v
	}

	return pattern
}
<|endoftext|>


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

// +build example

package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 640
	screenHeight = 480
)

func update(screen *ebiten.Image) error {
	ids := ebiten.GamepadIDs()
	axes := map[int][]string{}
	pressedButtons := map[int][]string{}

	for _, id := range ids {
		maxAxis := ebiten.GamepadAxisNum(id)
		for a := 0; a < maxAxis; a++ {
			v := ebiten.GamepadAxis(id, a)
			axes[id] = append(axes[id], fmt.Sprintf("%d:%0.2f", a, v))
		}
		maxButton := ebiten.GamepadButton(ebiten.GamepadButtonNum(id))
		for b := ebiten.GamepadButton(id); b < maxButton; b++ {
			if ebiten.IsGamepadButtonPressed(id, b) {
				pressedButtons[id] = append(pressedButtons[id], strconv.Itoa(int(b)))
			}
		}
	}

	if ebiten.IsRunningSlowly() {
		return nil
	}

	// Draw the current gamepad status.
	str := ""
	if len(ids) > 0 {
		for _, id := range ids {
			str += fmt.Sprintf("Gamepad (ID: %d):\n", id)
			str += fmt.Sprintf("  Axes:    %s\n", strings.Join(axes[id], ", "))
			str += fmt.Sprintf("  Buttons: %s\n", strings.Join(pressedButtons[id], ", "))
			str += "\n"
		}
	} else {
		str = "Please connect your gamepad."
	}
	ebitenutil.DebugPrint(screen, str)
	return nil
}

func main() {
	if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Gamepad (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>examples/gamepad: Add usage of inpututil<commit_after>// Copyright 2015 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build example

package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
	"github.com/hajimehoshi/ebiten/inpututil"
)

const (
	screenWidth  = 640
	screenHeight = 480
)

func update(screen *ebiten.Image) error {
	ids := ebiten.GamepadIDs()
	axes := map[int][]string{}
	pressedButtons := map[int][]string{}

	for _, id := range ids {
		maxAxis := ebiten.GamepadAxisNum(id)
		for a := 0; a < maxAxis; a++ {
			v := ebiten.GamepadAxis(id, a)
			axes[id] = append(axes[id], fmt.Sprintf("%d:%0.2f", a, v))
		}
		maxButton := ebiten.GamepadButton(ebiten.GamepadButtonNum(id))
		for b := ebiten.GamepadButton(id); b < maxButton; b++ {
			if ebiten.IsGamepadButtonPressed(id, b) {
				pressedButtons[id] = append(pressedButtons[id], strconv.Itoa(int(b)))
			}

			// Log some events.
			if inpututil.IsGamepadButtonJustPressed(id, b) {
				log.Printf("Button Just Pressed: id(%d), button(%d)", id, b)
			}
			if inpututil.IsGamepadButtonJustReleased(id, b) {
				log.Printf("Button Just Released: id(%d), button(%d)", id, b)
			}
		}
	}

	if ebiten.IsRunningSlowly() {
		return nil
	}

	// Draw the current gamepad status.
	str := ""
	if len(ids) > 0 {
		for _, id := range ids {
			str += fmt.Sprintf("Gamepad (ID: %d):\n", id)
			str += fmt.Sprintf("  Axes:    %s\n", strings.Join(axes[id], ", "))
			str += fmt.Sprintf("  Buttons: %s\n", strings.Join(pressedButtons[id], ", "))
			str += "\n"
		}
	} else {
		str = "Please connect your gamepad."
	}
	ebitenutil.DebugPrint(screen, str)
	return nil
}

func main() {
	if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Gamepad (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>