<commit_before>// Copyright 2014 Brian J. Downs
//
// 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.

// Package formatifier is a library to easily format strings in a user defined
// and predefined manner.
package formatifier

import (
	"crypto/rand"
	"regexp"
	"strings"
)

const (
	lengthError = "ERROR: String not long enough to convert."
	pirateLink  = "http://www.isithackday.com/arrpi.php?text=%s"
)

// Type to hold user input string.
type formatifier struct {
	theString string
	length    int
}

// New will create an instance of the String object.
func New(s string) *formatifier { return &formatifier{theString: s, length: len(s)} }

// makeLower will turn the user entered string to lower case
func (f *formatifier) makeLower() { f.theString = strings.ToLower(f.theString) }

// removeNonDigits removes any non digit characters from the string.
func (f *formatifier) removeNonDigits() {
	rp := regexp.MustCompile(`\D`)
	f.theString = rp.ReplaceAllString(f.theString, "")
}

// removeNonWordChars removes all non word characters.
func (f *formatifier) removeNonWordChars() {
	if len(f.theString) > 0 {
		rp := regexp.MustCompile(`\W|\s|_`)
		f.theString = rp.ReplaceAllString(f.theString, "")
	}
}

// urlEncodeSpaces will replace spaces with "%20"'s
func (f *formatifier) urlEncodeSpaces() {
	rp := regexp.MustCompile(`\s`)
	f.theString = rp.ReplaceAllString(f.theString, "%20")
}

// random select will return a random selection from an int slice
func randomSelect(a []int) int {
	var tmpIndex int
	length := len(a)
	randBytes := make([]byte, length)
	if _, err := rand.Read(randBytes); err == nil {
		tmpIndex = int(randBytes[0]) % length
	}
	return a[tmpIndex]
}

// leet speak map of string slices
var leet = map[string][]string{
	"leet":     []string{"1337"},
	"the":      []string{"teh"},
	"cool":     []string{"kewl"},
	"dude":     []string{"d00d"},
	"you":      []string{"u"},
	"noob":     []string{"n00b"},
	"noobs":    []string{"n00bs"},
	"own":      []string{"pwn"},
	"owned":    []string{"pwned"},
	"rocks":    []string{"roxx0rs"},
	"exploits": []string{"sploitz"},
	"woot":     []string{"w00t"},
	"hacker":   []string{"hax0r"},
	"hackers":  []string{"hax0rz"},
	"a":        []string{"4", "@"},
	"b":        []string{"8", "]3", "]8", "|3", "|8", "13"},
	"c":        []string{"(", "{"},
	"d":        []string{")", "[}", "|)", "|}", "|>"},
	"e":        []string{"3"},
	"f":        []string{"|=", "ph"},
	"g":        []string{"6", "9", "&"},
	"h":        []string{"#", "|-|"},
	"i":        []string{"1", "!", "|"},
	"j":        []string{"_|", "u|"},
	"k":        []string{"|<", "|{"},
	"l":        []string{"|", "1", "|_"},
	"m":        []string{"/\\/\\", "|\\/|"},
	"n":        []string{"/\\/", "|\\|"},
	"o":        []string{"0", "()"},
	"p":        []string{"|D", "|*"},
	"q":        []string{"(,)", "O\\", "[]\\"},
	"r":        []string{"|2", "|?", "][2"},
	"s":        []string{"5", "$"},
	"t":        []string{"7", "+"},
	"u":        []string{"(_)", "|_|"},
	"v":        []string{"\\/", "\\\\//"},
	"w":        []string{"\\/\\/", "|/\\|", "VV"},
	"x":        []string{"><", "}{"},
	"y":        []string{"'/", "%"},
	"z":        []string{"2", "7_"},
}

// irsa conversion map
var irsa = map[string]string{
	" ": " | ",
	"a": "alfa",
	"b": "bravo",
	"c": "charlie",
	"d": "delta",
	"e": "echo",
	"f": "foxtrot",
	"g": "golf",
	"h": "hotel",
	"i": "india",
	"j": "juliet",
	"k": "kilo",
	"l": "lima",
	"m": "mike",
	"n": "november",
	"o": "oscar",
	"p": "papa",
	"q": "quebec",
	"r": "romeo",
	"s": "sierra",
	"t": "tango",
	"u": "uniform",
	"v": "victor",
	"w": "whiskey",
	"x": "x-ray",
	"y": "yankee",
	"z": "zulu",
}

// morese holds conversion chars for Morse Code
var morse = map[string]string{
	"a":  ". _",
	"b":  "_ . . .",
	"c":  "_ . _ .",
	"d":  "_ . .",
	"e":  ".",
	"f":  ". . _ .",
	"g":  "_ _ .",
	"h":  ". . . .",
	"i":  ". .",
	"j":  ". _ _ _",
	"k":  "_ . _",
	"l":  ". _ . .",
	"m":  "_ _",
	"n":  "_ .",
	"o":  "_ _ _",
	"p":  ". _ _ .",
	"q":  "_ _ . _",
	"r":  ". _ .",
	"s":  ". . .",
	"t":  "_",
	"u":  ". . _",
	"v":  ". . . _",
	"w":  ". _ _",
	"x":  "_ . . _",
	"y":  "_ . _ _",
	"z":  "_ _ . .",
	"0":  "_ _ _ _ _",
	"1":  ". _ _ _ _",
	"2":  ". . _ _ _",
	"3":  ". . . _ _",
	"4":  ". . . . _",
	"5":  ". . . . .",
	"6":  "_ . . . .",
	"7":  "_ _ . . .",
	"8":  "_ _ _ . .",
	"9":  "_ _ _ _ .",
	".":  "·–·–·– ",
	",":  "––··–– ",
	"?":  "··––·· ",
	"'":  "·––––· ",
	"!":  "–·–·–– ",
	"/":  "–··–· ",
	"(":  "–·––· ",
	")":  "–·––·– ",
	"&":  "·–··· ",
	":":  "–––··· ",
	";":  "–·–·–· ",
	"=":  "–···– ",
	"+":  "·–·–· ",
	"–":  "–····– ",
	"_":  "··––·– ",
	"\"": "·–··–· ",
	"$":  "···–··– ",
	"@":  "·––·–· ",
}
<commit_msg>removed unnecessary redundancy<commit_after>// Copyright 2014 Brian J. Downs
//
// 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.

// Package formatifier is a library to easily format strings in a user defined
// and predefined manner.
package formatifier

import (
	"crypto/rand"
	"regexp"
	"strings"
)

const (
	lengthError = "ERROR: String not long enough to convert."
	pirateLink  = "http://www.isithackday.com/arrpi.php?text=%s"
)

// Type to hold user input string.
type formatifier struct {
	theString string
	length    int
}

// New will create an instance of the String object.
func New(s string) *formatifier { return &formatifier{theString: s, length: len(s)} }

// makeLower will turn the user entered string to lower case
func (f *formatifier) makeLower() { f.theString = strings.ToLower(f.theString) }

// removeNonDigits removes any non digit characters from the string.
func (f *formatifier) removeNonDigits() {
	rp := regexp.MustCompile(`\D`)
	f.theString = rp.ReplaceAllString(f.theString, "")
}

// removeNonWordChars removes all non word characters.
func (f *formatifier) removeNonWordChars() {
	if len(f.theString) > 0 {
		rp := regexp.MustCompile(`\W|\s|_`)
		f.theString = rp.ReplaceAllString(f.theString, "")
	}
}

// urlEncodeSpaces will replace spaces with "%20"'s
func (f *formatifier) urlEncodeSpaces() {
	rp := regexp.MustCompile(`\s`)
	f.theString = rp.ReplaceAllString(f.theString, "%20")
}

// random select will return a random selection from an int slice
func randomSelect(a []int) int {
	var tmpIndex int
	length := len(a)
	randBytes := make([]byte, length)
	if _, err := rand.Read(randBytes); err == nil {
		tmpIndex = int(randBytes[0]) % length
	}
	return a[tmpIndex]
}

// leet speak map of string slices
var leet = map[string][]string{
	"leet":     {"1337"},
	"the":      {"teh"},
	"cool":     {"kewl"},
	"dude":     {"d00d"},
	"you":      {"u"},
	"noob":     {"n00b"},
	"noobs":    {"n00bs"},
	"own":      {"pwn"},
	"owned":    {"pwned"},
	"rocks":    {"roxx0rs"},
	"exploits": {"sploitz"},
	"woot":     {"w00t"},
	"hacker":   {"hax0r"},
	"hackers":  {"hax0rz"},
	"a":        {"4", "@"},
	"b":        {"8", "]3", "]8", "|3", "|8", "13"},
	"c":        {"(", "{"},
	"d":        {")", "[}", "|)", "|}", "|>"},
	"e":        {"3"},
	"f":        {"|=", "ph"},
	"g":        {"6", "9", "&"},
	"h":        {"#", "|-|"},
	"i":        {"1", "!", "|"},
	"j":        {"_|", "u|"},
	"k":        {"|<", "|{"},
	"l":        {"|", "1", "|_"},
	"m":        {"/\\/\\", "|\\/|"},
	"n":        {"/\\/", "|\\|"},
	"o":        {"0", "()"},
	"p":        {"|D", "|*"},
	"q":        {"(,)", "O\\", "[]\\"},
	"r":        {"|2", "|?", "][2"},
	"s":        {"5", "$"},
	"t":        {"7", "+"},
	"u":        {"(_)", "|_|"},
	"v":        {"\\/", "\\\\//"},
	"w":        {"\\/\\/", "|/\\|", "VV"},
	"x":        {"><", "}{"},
	"y":        {"'/", "%"},
	"z":        {"2", "7_"},
}

// irsa conversion map
var irsa = map[string]string{
	" ": " | ",
	"a": "alfa",
	"b": "bravo",
	"c": "charlie",
	"d": "delta",
	"e": "echo",
	"f": "foxtrot",
	"g": "golf",
	"h": "hotel",
	"i": "india",
	"j": "juliet",
	"k": "kilo",
	"l": "lima",
	"m": "mike",
	"n": "november",
	"o": "oscar",
	"p": "papa",
	"q": "quebec",
	"r": "romeo",
	"s": "sierra",
	"t": "tango",
	"u": "uniform",
	"v": "victor",
	"w": "whiskey",
	"x": "x-ray",
	"y": "yankee",
	"z": "zulu",
}

// morese holds conversion chars for Morse Code
var morse = map[string]string{
	"a":  ". _",
	"b":  "_ . . .",
	"c":  "_ . _ .",
	"d":  "_ . .",
	"e":  ".",
	"f":  ". . _ .",
	"g":  "_ _ .",
	"h":  ". . . .",
	"i":  ". .",
	"j":  ". _ _ _",
	"k":  "_ . _",
	"l":  ". _ . .",
	"m":  "_ _",
	"n":  "_ .",
	"o":  "_ _ _",
	"p":  ". _ _ .",
	"q":  "_ _ . _",
	"r":  ". _ .",
	"s":  ". . .",
	"t":  "_",
	"u":  ". . _",
	"v":  ". . . _",
	"w":  ". _ _",
	"x":  "_ . . _",
	"y":  "_ . _ _",
	"z":  "_ _ . .",
	"0":  "_ _ _ _ _",
	"1":  ". _ _ _ _",
	"2":  ". . _ _ _",
	"3":  ". . . _ _",
	"4":  ". . . . _",
	"5":  ". . . . .",
	"6":  "_ . . . .",
	"7":  "_ _ . . .",
	"8":  "_ _ _ . .",
	"9":  "_ _ _ _ .",
	".":  "·–·–·– ",
	",":  "––··–– ",
	"?":  "··––·· ",
	"'":  "·––––· ",
	"!":  "–·–·–– ",
	"/":  "–··–· ",
	"(":  "–·––· ",
	")":  "–·––·– ",
	"&":  "·–··· ",
	":":  "–––··· ",
	";":  "–·–·–· ",
	"=":  "–···– ",
	"+":  "·–·–· ",
	"–":  "–····– ",
	"_":  "··––·– ",
	"\"": "·–··–· ",
	"$":  "···–··– ",
	"@":  "·––·–· ",
}
<|endoftext|>


<commit_before>package rabbithole

import "strconv"

// Extra arguments as a map (on queues, bindings, etc)
type Properties map[string]interface{}

// Port used by RabbitMQ or clients
type Port int

func (p *Port) UnmarshalJSON(b []byte) error {
	stringValue := string(b)
	var parsed int64
	var err error
	if stringValue[0] == '"' && stringValue[len(stringValue)-1] == '"' {
		parsed, err = strconv.ParseInt(stringValue[1:len(stringValue)-1], 10, 32)
	} else {
		parsed, err = strconv.ParseInt(stringValue, 10, 32)
	}
	if err == nil {
		*p = Port(int(parsed))
	}
	return err
}

// RateDetailSample single touple
type RateDetailSample struct {
	Sample    int64 `json:"sample"`
	Timestamp int64 `json:"timestamp"`
}

// Rate of change of a numerical value
type RateDetails struct {
	Rate    float32            `json:"rate"`
	Samples []RateDetailSample `json:"samples"`
}

// RabbitMQ context (Erlang app) running on
// a node
type BrokerContext struct {
	Node        string `json:"node"`
	Description string `json:"description"`
	Path        string `json:"path"`
	Port        Port   `json:"port"`
	Ignore      bool   `json:"ignore_in_use"`
}

// Basic published messages statistics
type MessageStats struct {
	Publish             int         `json:"publish"`
	PublishDetails      RateDetails `json:"publish_details"`
	Deliver             int         `json:"deliver"`
	DeliverDetails      RateDetails `json:"deliver_details"`
	DeliverNoAck        int         `json:"deliver_noack"`
	DeliverNoAckDetails RateDetails `json:"deliver_noack_details"`
	DeliverGet          int         `json:"deliver_get"`
	DeliverGetDetails   RateDetails `json:"deliver_get_details"`
	Redeliver           int         `json:"redeliver"`
	RedeliverDetails    RateDetails `json:"redeliver_details"`
	Get                 int         `json:"get"`
	GetDetails          RateDetails `json:"get_details"`
	GetNoAck            int         `json:"get_no_ack"`
	GetNoAckDetails     RateDetails `json:"get_no_ack_details"`
}
<commit_msg>concrete stat types for MessageStats. - DK<commit_after>package rabbithole

import "strconv"

// Extra arguments as a map (on queues, bindings, etc)
type Properties map[string]interface{}

// Port used by RabbitMQ or clients
type Port int

func (p *Port) UnmarshalJSON(b []byte) error {
	stringValue := string(b)
	var parsed int64
	var err error
	if stringValue[0] == '"' && stringValue[len(stringValue)-1] == '"' {
		parsed, err = strconv.ParseInt(stringValue[1:len(stringValue)-1], 10, 32)
	} else {
		parsed, err = strconv.ParseInt(stringValue, 10, 32)
	}
	if err == nil {
		*p = Port(int(parsed))
	}
	return err
}

// RateDetailSample single touple
type RateDetailSample struct {
	Sample    int64 `json:"sample"`
	Timestamp int64 `json:"timestamp"`
}

// Rate of change of a numerical value
type RateDetails struct {
	Rate    float32            `json:"rate"`
	Samples []RateDetailSample `json:"samples"`
}

// RabbitMQ context (Erlang app) running on
// a node
type BrokerContext struct {
	Node        string `json:"node"`
	Description string `json:"description"`
	Path        string `json:"path"`
	Port        Port   `json:"port"`
	Ignore      bool   `json:"ignore_in_use"`
}

// Basic published messages statistics
type MessageStats struct {
	Publish             int64       `json:"publish"`
	PublishDetails      RateDetails `json:"publish_details"`
	Deliver             int64       `json:"deliver"`
	DeliverDetails      RateDetails `json:"deliver_details"`
	DeliverNoAck        int64       `json:"deliver_noack"`
	DeliverNoAckDetails RateDetails `json:"deliver_noack_details"`
	DeliverGet          int64       `json:"deliver_get"`
	DeliverGetDetails   RateDetails `json:"deliver_get_details"`
	Redeliver           int64       `json:"redeliver"`
	RedeliverDetails    RateDetails `json:"redeliver_details"`
	Get                 int64       `json:"get"`
	GetDetails          RateDetails `json:"get_details"`
	GetNoAck            int64       `json:"get_no_ack"`
	GetNoAckDetails     RateDetails `json:"get_no_ack_details"`
}
<|endoftext|>


<commit_before>package siteengines

import (
	"strconv"
	"time"

	. "github.com/xyproto/browserspeak"
	. "github.com/xyproto/genericsite"
	"github.com/xyproto/instapage"
	"github.com/xyproto/simpleredis"
	"github.com/xyproto/web"
)

// An Engine is a specific piece of a website
// This part handles the "chat" pages

type ChatEngine struct {
	userState *UserState
	chatState *ChatState
}

type ChatState struct {
	active   *simpleredis.Set            // A list of all users that are in the chat, must correspond to the users in UserState.users
	said     *simpleredis.List           // A list of everything that has been said so far
	userInfo *simpleredis.HashMap        // Info about a chat user - last seen, preferred number of lines etc
	pool     *simpleredis.ConnectionPool // A connection pool for Redis
}

func NewChatEngine(userState *UserState) *ChatEngine {
	pool := userState.GetPool()
	chatState := new(ChatState)
	chatState.active = simpleredis.NewSet(pool, "active")
	chatState.said = simpleredis.NewList(pool, "said")
	chatState.userInfo = simpleredis.NewHashMap(pool, "userInfo") // lastSeen.time is an encoded timestamp for when the user was last seen chatting
	chatState.pool = pool
	return &ChatEngine{userState, chatState}
}

func (ce *ChatEngine) ServePages(basecp BaseCP, menuEntries MenuEntries) {
	chatCP := basecp(ce.userState)
	chatCP.ContentTitle = "Chat"
	chatCP.ExtraCSSurls = append(chatCP.ExtraCSSurls, "/css/chat.css")

	tvgf := DynamicMenuFactoryGenerator(menuEntries)
	tvg := tvgf(ce.userState)

	web.Get("/chat", chatCP.WrapSimpleContextHandle(ce.GenerateChatCurrentUser(), tvg))
	web.Post("/say", ce.GenerateSayCurrentUser())
	web.Get("/css/chat.css", ce.GenerateCSS(chatCP.ColorScheme))
	web.Post("/setchatlines", ce.GenerateSetChatLinesCurrentUser())
	// For debugging
	web.Get("/getchatlines", ce.GenerateGetChatLinesCurrentUser())
}

func (ce *ChatEngine) SetLines(username string, lines int) {
	ce.chatState.userInfo.Set(username, "lines", strconv.Itoa(lines))
}

func (ce *ChatEngine) GetLines(username string) int {
	val, err := ce.chatState.userInfo.Get(username, "lines")
	if err != nil {
		// The default
		return 20
	}
	num, err := strconv.Atoi(val)
	if err != nil {
		// The default
		return 20
	}
	return num
}

// Mark a user as seen
func (ce *ChatEngine) Seen(username string) {
	now := time.Now()
	encodedTime, err := now.GobEncode()
	if err != nil {
		panic("ERROR: Can't encode the time")
	}
	ce.chatState.userInfo.Set(username, "lastseen", string(encodedTime))
}

func (ce *ChatEngine) GetLastSeen(username string) string {
	encodedTime, err := ce.chatState.userInfo.Get(username, "lastseen")
	if err == nil {
		var then time.Time
		err = then.GobDecode([]byte(encodedTime))
		if err == nil {
			timestamp := then.String()
			return timestamp[11:19]
		}
	}
	return "never"
}

func (ce *ChatEngine) IsChatting(username string) bool {
	encodedTime, err := ce.chatState.userInfo.Get(username, "lastseen")
	if err == nil {
		var then time.Time
		err = then.GobDecode([]byte(encodedTime))
		if err == nil {
			elapsed := time.Since(then)
			if elapsed.Minutes() > 20 {
				// 20 minutes since last seen saying anything, set as not chatting
				ce.SetChatting(username, false)
				return false
			}
		}
	}
	// TODO: If the user was last seen more than N minutes ago, set as not chatting and return false
	return ce.userState.GetBooleanField(username, "chatting")
}

// Set "chatting" to "true" or "false" for a given user
func (ce *ChatEngine) SetChatting(username string, val bool) {
	ce.userState.SetBooleanField(username, "chatting", val)
}

func (ce *ChatEngine) JoinChat(username string) {
	// Join the chat
	ce.chatState.active.Add(username)
	// Change the chat status for the user
	ce.SetChatting(username, true)
	// Mark the user as seen
	ce.Seen(username)
}

func (ce *ChatEngine) Say(username, text string) {
	timestamp := time.Now().String()
	textline := timestamp[11:19] + "  " + username + "> " + text
	ce.chatState.said.Add(textline)
	// Store the timestamp for when the user was last seen as well
	ce.Seen(username)
}

func LeaveChat(ce *ChatEngine, username string) {
	// Leave the chat
	ce.chatState.active.Del(username)
	// Change the chat status for the user
	ce.SetChatting(username, false)
}

func (ce *ChatEngine) GetChatUsers() []string {
	chatUsernames, err := ce.chatState.active.GetAll()
	if err != nil {
		return []string{}
	}
	return chatUsernames
}

func (ce *ChatEngine) GetChatText() []string {
	chatText, err := ce.chatState.said.GetAll()
	if err != nil {
		return []string{}
	}
	return chatText
}

// Get the last N entries
func (ce *ChatEngine) GetLastChatText(n int) []string {
	chatText, err := ce.chatState.said.GetLastN(n)
	if err != nil {
		return []string{}
	}
	return chatText
}

func (ce *ChatEngine) chatText(lines int) string {
	if lines == -1 {
		return "BANANAS!"
	}
	retval := "
"
	// Show N lines of chat text
	for _, said := range ce.GetLastChatText(lines) {
		retval += said + "
"
	}
	return retval + "
"
}

func (ce *ChatEngine) GenerateChatCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}

		ce.JoinChat(username)

		// TODO: Add a button for someone to see the entire chat
		// TODO: Add some protection against random monkeys that only fling poo

		retval := "Hi " + username + "
"
		retval += "
"
		retval += "Participants:" + "
"
		// TODO: If the person has not been seen the last 96 hours, don't list him/her
		for _, otherUser := range ce.GetChatUsers() {
			if otherUser == username {
				continue
			}
			retval += "  " + otherUser + ", last seen " + ce.GetLastSeen(otherUser) + "
"
		}
		retval += "
"
		retval += "
"
		retval += ce.chatText(ce.GetLines(username))
		retval += "
"
		retval += "
"
		// The say() function for submitting text over ajax (a post request), clearing the text intput field and updating the chat text
		retval += JS("function say(text) { $.post('/say', {said:$('#sayText').val()}, function(data) { $('#sayText').val(''); $('#chatText').html(data); }); }")
		// Call say() at return
		retval += "<input size='60' id='sayText' name='said' type='text' onKeypress=\"if (event.keyCode == 13) { say($('#sayText').val()); };\">"
		// Cal say() at the click of the button
		retval += "<button onClick='say();'>Say</button>"
		// Focus on the text input
		retval += JS(Focus("#sayText"))
		// TODO: Update the chat every 64 seconds. If something happens, update every 200ms, then 400ms, then 800ms etc until it's at 64 seconds again. This should happen in javascript.
		// Update the chat text every 500 ms
		retval += JS("setInterval(function(){$.post('/say', {}, function(data) { $('#chatText').html(data); });}, 500);")
		// A function for setting the preferred number of lines
		retval += JS("function setlines(numlines) { $.post('/setchatlines', {lines:numlines}, function(data) { $('#chatText').html(data); }); }")
		// A button for viewing 20 lines at a time
		retval += "<button onClick='setlines(20);'>20</button>"
		// A button for viewing 50 lines at a time
		retval += "<button onClick='setlines(50);'>50</button>"
		// A button for viewing all lines at a time
		retval += "<button onClick='setlines(-1);'>all</button>"
		// A button for viewing 99999 lines at a time
		retval += "<button onClick='setlines(99999);'>99999</button>"
		// For viewing all the text so far

		return retval
	}
}

func (ce *ChatEngine) GenerateSayCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		said, found := ctx.Params["said"]
		if !found || said == "" {
			// Return the text instead of giving an error for easy use of /say to refresh the content
			// Note that as long as Say below isn't called, the user will be marked as inactive eventually
			return ce.chatText(ce.GetLines(username))
		}

		ce.Say(username, CleanUpUserInput(said))

		return ce.chatText(ce.GetLines(username))
	}
}

func (ce *ChatEngine) GenerateGetChatLinesCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		num := ce.GetLines(username)

		return strconv.Itoa(num)
	}
}

func (ce *ChatEngine) GenerateSetChatLinesCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		lines, found := ctx.Params["lines"]
		if !found || lines == "" {
			return instapage.MessageOKback("Set chat lines", "Missing value for preferred number of lines")
		}
		num, err := strconv.Atoi(lines)
		if err != nil {
			return instapage.MessageOKback("Set chat lines", "Invalid number of lines: "+lines)
		}

		// Set the preferred number of lines for this user
		ce.SetLines(username, num)

		return ce.chatText(num)
	}
}

func (ce *ChatEngine) GenerateCSS(cs *ColorScheme) SimpleContextHandle {
	return func(ctx *web.Context) string {
		ctx.ContentType("css")
		return `
.yes {
	background-color: #90ff90;
	color: black;
}
.no {
	background-color: #ff9090;
	color: black;
}

.username:link { color: green; }
.username:visited { color: green; }
.username:hover { color: green; }
.username:active { color: green; }

.whitebg {
	background-color: white;
}

.darkgrey:link { color: #404040; }
.darkgrey:visited { color: #404040; }
.darkgrey:hover { color: #404040; }
.darkgrey:active { color: #404040; }

#chatText {
	background-color: white;
}

`
		//
	}
}
<commit_msg>Chat now reduces the polling if there's no activity for a while<commit_after>package siteengines

import (
	"strconv"
	"time"

	. "github.com/xyproto/browserspeak"
	. "github.com/xyproto/genericsite"
	"github.com/xyproto/instapage"
	"github.com/xyproto/simpleredis"
	"github.com/xyproto/web"
)

// An Engine is a specific piece of a website
// This part handles the "chat" pages

type ChatEngine struct {
	userState *UserState
	chatState *ChatState
}

type ChatState struct {
	active   *simpleredis.Set            // A list of all users that are in the chat, must correspond to the users in UserState.users
	said     *simpleredis.List           // A list of everything that has been said so far
	userInfo *simpleredis.HashMap        // Info about a chat user - last seen, preferred number of lines etc
	pool     *simpleredis.ConnectionPool // A connection pool for Redis
}

func NewChatEngine(userState *UserState) *ChatEngine {
	pool := userState.GetPool()
	chatState := new(ChatState)
	chatState.active = simpleredis.NewSet(pool, "active")
	chatState.said = simpleredis.NewList(pool, "said")
	chatState.userInfo = simpleredis.NewHashMap(pool, "userInfo") // lastSeen.time is an encoded timestamp for when the user was last seen chatting
	chatState.pool = pool
	return &ChatEngine{userState, chatState}
}

func (ce *ChatEngine) ServePages(basecp BaseCP, menuEntries MenuEntries) {
	chatCP := basecp(ce.userState)
	chatCP.ContentTitle = "Chat"
	chatCP.ExtraCSSurls = append(chatCP.ExtraCSSurls, "/css/chat.css")

	tvgf := DynamicMenuFactoryGenerator(menuEntries)
	tvg := tvgf(ce.userState)

	web.Get("/chat", chatCP.WrapSimpleContextHandle(ce.GenerateChatCurrentUser(), tvg))
	web.Post("/say", ce.GenerateSayCurrentUser())
	web.Get("/css/chat.css", ce.GenerateCSS(chatCP.ColorScheme))
	web.Post("/setchatlines", ce.GenerateSetChatLinesCurrentUser())
	// For debugging
	web.Get("/getchatlines", ce.GenerateGetChatLinesCurrentUser())
}

func (ce *ChatEngine) SetLines(username string, lines int) {
	ce.chatState.userInfo.Set(username, "lines", strconv.Itoa(lines))
}

func (ce *ChatEngine) GetLines(username string) int {
	val, err := ce.chatState.userInfo.Get(username, "lines")
	if err != nil {
		// The default
		return 20
	}
	num, err := strconv.Atoi(val)
	if err != nil {
		// The default
		return 20
	}
	return num
}

// Mark a user as seen
func (ce *ChatEngine) Seen(username string) {
	now := time.Now()
	encodedTime, err := now.GobEncode()
	if err != nil {
		panic("ERROR: Can't encode the time")
	}
	ce.chatState.userInfo.Set(username, "lastseen", string(encodedTime))
}

func (ce *ChatEngine) GetLastSeen(username string) string {
	encodedTime, err := ce.chatState.userInfo.Get(username, "lastseen")
	if err == nil {
		var then time.Time
		err = then.GobDecode([]byte(encodedTime))
		if err == nil {
			timestamp := then.String()
			return timestamp[11:19]
		}
	}
	return "never"
}

func (ce *ChatEngine) IsChatting(username string) bool {
	encodedTime, err := ce.chatState.userInfo.Get(username, "lastseen")
	if err == nil {
		var then time.Time
		err = then.GobDecode([]byte(encodedTime))
		if err == nil {
			elapsed := time.Since(then)
			if elapsed.Minutes() > 20 {
				// 20 minutes since last seen saying anything, set as not chatting
				ce.SetChatting(username, false)
				return false
			}
		}
	}
	// TODO: If the user was last seen more than N minutes ago, set as not chatting and return false
	return ce.userState.GetBooleanField(username, "chatting")
}

// Set "chatting" to "true" or "false" for a given user
func (ce *ChatEngine) SetChatting(username string, val bool) {
	ce.userState.SetBooleanField(username, "chatting", val)
}

func (ce *ChatEngine) JoinChat(username string) {
	// Join the chat
	ce.chatState.active.Add(username)
	// Change the chat status for the user
	ce.SetChatting(username, true)
	// Mark the user as seen
	ce.Seen(username)
}

func (ce *ChatEngine) Say(username, text string) {
	timestamp := time.Now().String()
	textline := timestamp[11:19] + "  " + username + "> " + text
	ce.chatState.said.Add(textline)
	// Store the timestamp for when the user was last seen as well
	ce.Seen(username)
}

func LeaveChat(ce *ChatEngine, username string) {
	// Leave the chat
	ce.chatState.active.Del(username)
	// Change the chat status for the user
	ce.SetChatting(username, false)
}

func (ce *ChatEngine) GetChatUsers() []string {
	chatUsernames, err := ce.chatState.active.GetAll()
	if err != nil {
		return []string{}
	}
	return chatUsernames
}

func (ce *ChatEngine) GetChatText() []string {
	chatText, err := ce.chatState.said.GetAll()
	if err != nil {
		return []string{}
	}
	return chatText
}

// Get the last N entries
func (ce *ChatEngine) GetLastChatText(n int) []string {
	chatText, err := ce.chatState.said.GetLastN(n)
	if err != nil {
		return []string{}
	}
	return chatText
}

func (ce *ChatEngine) chatText(lines int) string {
	if lines == -1 {
		return "BANANAS!"
	}
	retval := "
"
	// Show N lines of chat text
	for _, said := range ce.GetLastChatText(lines) {
		retval += said + "
"
	}
	return retval + "
"
}

func (ce *ChatEngine) GenerateChatCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}

		ce.JoinChat(username)

		// TODO: Add a button for someone to see the entire chat
		// TODO: Add some protection against random monkeys that only fling poo

		retval := "Hi " + username + "
"
		retval += "
"
		retval += "Participants:" + "
"
		// TODO: If the person has not been seen the last 96 hours, don't list him/her
		for _, otherUser := range ce.GetChatUsers() {
			if otherUser == username {
				continue
			}
			retval += "  " + otherUser + ", last seen " + ce.GetLastSeen(otherUser) + "
"
		}
		retval += "
"
		retval += "
"
		retval += ce.chatText(ce.GetLines(username))
		retval += "
"
		retval += "
"
		retval += JS("var fastestPolling = 500;")
		retval += JS("var slowestPolling = 64000;")
		retval += JS("var pollInterval = fastestPolling;")
		retval += JS("var pollID = 0;")
		// The say() function for submitting text over ajax (a post request), clearing the text intput field and updating the chat text.
		// Also sets the polling interval to the fastest value.
		retval += JS("function say(text) { pollInterval = fastestPolling; $.post('/say', {said:$('#sayText').val()}, function(data) { $('#sayText').val(''); $('#chatText').html(data); }); }")
		// Call say() at return
		retval += "<input size='60' id='sayText' name='said' type='text' onKeypress=\"if (event.keyCode == 13) { say($('#sayText').val()); };\">"
		// Cal say() at the click of the button
		retval += "<button onClick='say();'>Say</button>"
		// Focus on the text input
		retval += JS(Focus("#sayText"))
		// Update the chat text. Reduce the poll interval at every poll.
		// When the user does something, the polling interval will be reset to something quicker.
		retval += JS(`function UpdateChat() {
		    if (pollInterval < slowestPolling) {
			    pollInterval *= 2;
				clearInterval(pollID);
				pollID = setInterval(UpdateChat, pollInterval);
			};
			$.post('/say', {}, function(data) { $('#chatText').html(data); });
		}`)
		retval += JS("pollID = setInterval(UpdateChat, pollInterval);")
		// A function for setting the preferred number of lines
		retval += JS("function setlines(numlines) { $.post('/setchatlines', {lines:numlines}, function(data) { $('#chatText').html(data); }); }")
		// A button for viewing 20 lines at a time
		retval += "<button onClick='setlines(20);'>20</button>"
		// A button for viewing 50 lines at a time
		retval += "<button onClick='setlines(50);'>50</button>"
		// A button for viewing 99999 lines at a time
		retval += "<button onClick='setlines(99999);'>99999</button>"
		// For viewing all the text so far

		return retval
	}
}

func (ce *ChatEngine) GenerateSayCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		said, found := ctx.Params["said"]
		if !found || said == "" {
			// Return the text instead of giving an error for easy use of /say to refresh the content
			// Note that as long as Say below isn't called, the user will be marked as inactive eventually
			return ce.chatText(ce.GetLines(username))
		}

		ce.Say(username, CleanUpUserInput(said))

		return ce.chatText(ce.GetLines(username))
	}
}

func (ce *ChatEngine) GenerateGetChatLinesCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		num := ce.GetLines(username)

		return strconv.Itoa(num)
	}
}

func (ce *ChatEngine) GenerateSetChatLinesCurrentUser() SimpleContextHandle {
	return func(ctx *web.Context) string {
		username := GetBrowserUsername(ctx)
		if username == "" {
			return "No user logged in"
		}
		if !ce.userState.IsLoggedIn(username) {
			return "Not logged in"
		}
		if !ce.IsChatting(username) {
			return "Not currently chatting"
		}
		lines, found := ctx.Params["lines"]
		if !found || lines == "" {
			return instapage.MessageOKback("Set chat lines", "Missing value for preferred number of lines")
		}
		num, err := strconv.Atoi(lines)
		if err != nil {
			return instapage.MessageOKback("Set chat lines", "Invalid number of lines: "+lines)
		}

		// Set the preferred number of lines for this user
		ce.SetLines(username, num)

		return ce.chatText(num)
	}
}

func (ce *ChatEngine) GenerateCSS(cs *ColorScheme) SimpleContextHandle {
	return func(ctx *web.Context) string {
		ctx.ContentType("css")
		return `
.yes {
	background-color: #90ff90;
	color: black;
}
.no {
	background-color: #ff9090;
	color: black;
}

.username:link { color: green; }
.username:visited { color: green; }
.username:hover { color: green; }
.username:active { color: green; }

.whitebg {
	background-color: white;
}

.darkgrey:link { color: #404040; }
.darkgrey:visited { color: #404040; }
.darkgrey:hover { color: #404040; }
.darkgrey:active { color: #404040; }

#chatText {
	background-color: white;
}

`
		//
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"errors"
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

// How long to sleep if a limit-exceeded event happens
var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id" +
	"nat_gateway_id, instance_id, network_interface_id, route_table_id or" +
	"vpc_peering_connection_id is allowed.")

// AWS Route resource Schema declaration
func resourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRouteCreate,
		Read:   resourceAwsRouteRead,
		Update: resourceAwsRouteUpdate,
		Delete: resourceAwsRouteDelete,
		Exists: resourceAwsRouteExists,

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"destination_prefix_list_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"nat_gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"instance_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"instance_owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"network_interface_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"origin": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"route_table_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_peering_connection_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
		},
	}
}

func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	createOpts := &ec2.CreateRouteInput{}
	// Formulate CreateRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
		}
	case "network_interface_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route create config: %s", createOpts)

	// Create the route
	_, err := conn.CreateRoute(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating route: %s", err)
	}

	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		return err
	}

	d.SetId(routeIDHash(d, route))

	return resourceAwsRouteRead(d, meta)
}

func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		return err
	}

	d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("instance_owner_id", route.InstanceOwnerId)
	d.Set("network_interface_id", route.NetworkInterfaceId)
	d.Set("origin", route.Origin)
	d.Set("state", route.State)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)

	return nil
}

func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}
	replaceOpts := &ec2.ReplaceRouteInput{}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	// Formulate ReplaceRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
			//NOOP: Ensure we don't blow away network interface id that is set after instance is launched
			NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
		}
	case "network_interface_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route replace config: %s", replaceOpts)

	// Replace the route
	_, err := conn.ReplaceRoute(replaceOpts)
	if err != nil {
		return err
	}

	return nil
}

func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	deleteOpts := &ec2.DeleteRouteInput{
		RouteTableId:         aws.String(d.Get("route_table_id").(string)),
		DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
	}
	log.Printf("[DEBUG] Route delete opts: %s", deleteOpts)

	resp, err := conn.DeleteRoute(deleteOpts)
	log.Printf("[DEBUG] Route delete result: %s", resp)
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*AWSClient).ec2conn
	routeTableId := d.Get("route_table_id").(string)

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableId},
	}

	res, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return false, err
	}

	cidr := d.Get("destination_cidr_block").(string)
	for _, route := range (*res.RouteTables[0]).Routes {
		if *route.DestinationCidrBlock == cidr {
			return true, nil
		}
	}

	return false, nil
}

// Create an ID for a route
func routeIDHash(d *schema.ResourceData, r *ec2.Route) string {
	return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock))
}

// Helper: retrieve a route
func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) {
	routeTableID := rtbid

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableID},
	}

	resp, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return nil, err
	}

	for _, route := range (*resp.RouteTables[0]).Routes {
		if *route.DestinationCidrBlock == cidr {
			return route, nil
		}
	}

	return nil, nil
}
<commit_msg>provider/aws: Return an error if no route is found for an AWS Route<commit_after>package aws

import (
	"errors"
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

// How long to sleep if a limit-exceeded event happens
var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id" +
	"nat_gateway_id, instance_id, network_interface_id, route_table_id or" +
	"vpc_peering_connection_id is allowed.")

// AWS Route resource Schema declaration
func resourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRouteCreate,
		Read:   resourceAwsRouteRead,
		Update: resourceAwsRouteUpdate,
		Delete: resourceAwsRouteDelete,
		Exists: resourceAwsRouteExists,

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"destination_prefix_list_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"nat_gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"instance_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"instance_owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"network_interface_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"origin": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"route_table_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_peering_connection_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
		},
	}
}

func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	createOpts := &ec2.CreateRouteInput{}
	// Formulate CreateRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
		}
	case "network_interface_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route create config: %s", createOpts)

	// Create the route
	_, err := conn.CreateRoute(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating route: %s", err)
	}

	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		return err
	}

	d.SetId(routeIDHash(d, route))

	return resourceAwsRouteRead(d, meta)
}

func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		return err
	}

	d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("instance_owner_id", route.InstanceOwnerId)
	d.Set("network_interface_id", route.NetworkInterfaceId)
	d.Set("origin", route.Origin)
	d.Set("state", route.State)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)

	return nil
}

func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}
	replaceOpts := &ec2.ReplaceRouteInput{}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	// Formulate ReplaceRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
			//NOOP: Ensure we don't blow away network interface id that is set after instance is launched
			NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
		}
	case "network_interface_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route replace config: %s", replaceOpts)

	// Replace the route
	_, err := conn.ReplaceRoute(replaceOpts)
	if err != nil {
		return err
	}

	return nil
}

func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	deleteOpts := &ec2.DeleteRouteInput{
		RouteTableId:         aws.String(d.Get("route_table_id").(string)),
		DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
	}
	log.Printf("[DEBUG] Route delete opts: %s", deleteOpts)

	resp, err := conn.DeleteRoute(deleteOpts)
	log.Printf("[DEBUG] Route delete result: %s", resp)
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*AWSClient).ec2conn
	routeTableId := d.Get("route_table_id").(string)

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableId},
	}

	res, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return false, err
	}

	cidr := d.Get("destination_cidr_block").(string)
	for _, route := range (*res.RouteTables[0]).Routes {
		if *route.DestinationCidrBlock == cidr {
			return true, nil
		}
	}

	return false, nil
}

// Create an ID for a route
func routeIDHash(d *schema.ResourceData, r *ec2.Route) string {
	return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock))
}

// Helper: retrieve a route
func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) {
	routeTableID := rtbid

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableID},
	}

	resp, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return nil, err
	}

	for _, route := range (*resp.RouteTables[0]).Routes {
		if *route.DestinationCidrBlock == cidr {
			return route, nil
		}
	}

	return nil, fmt.Errorf(`
error finding matching route for Route table (%s) and destination CIDR block (%s)`,
		rtbid, cidr)
}
<|endoftext|>


<commit_before>package s3git

import (
	"encoding/hex"
	"errors"
	"time"
	"github.com/s3git/s3git-go/internal/core"
	"github.com/s3git/s3git-go/internal/kv"
)

type Commit struct {
	Hash    string
	Message string
	TimeStamp string
	Parent	string
}

// Perform a commit for the repository
func (repo Repository) Commit(message string) (hash string, empty bool, err error) {
	return repo.commit(message, "master", []string{})
}

// Perform a commit for the named branch of the repository
func (repo Repository) CommitToBranch(message, branch string) (hash string, empty bool, err error) {
	return repo.commit(message, branch, []string{})
}

func (repo Repository) commit(message, branch string, parents []string) (hash string, empty bool, err error) {

	warmParents := []string{}
	coldParents := []string{}

	commits, err := kv.ListTopMostCommits()
	if err != nil {
		return "", false, err
	}

	if len(parents) == 0 {
		for c := range commits {
			warmParents = append(warmParents, hex.EncodeToString(c))
		}
		if len(warmParents) > 1 {
			// TODO: Do extra check whether the trees are the same, in that case we can safely ignore the warning
			return "", false, errors.New("Multiple top most commits founds as parents")
		}
	} else {
		for c := range commits {
			p := hex.EncodeToString(c)
			if contains(parents, p) {
				warmParents = append(warmParents, p)
			} else {
				coldParents = append(coldParents, p)
			}
		}
	}

	return repo.commitWithWarmAndColdParents(message, branch, warmParents, coldParents)
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func (repo Repository) commitWithWarmAndColdParents(message, branch string, warmParents, coldParents []string) (hash string, empty bool, err error) {

	list, err := kv.ListStage()
	if err != nil {
		return "", false, err
	}

	// Create commit object on disk
	commitHash, empty, err := core.StoreCommitObject(message, branch, warmParents, coldParents, list, []string{})
	if err != nil {
		return "", false, err
	}
	if empty {
		return "", true, nil
	}

	// Remove added blobs from staging area
	err = kv.ClearStage()
	if err != nil {
		return "", false, err
	}

	err = core.StorePrefixObject(commitHash)
	if err != nil {
		return "", false, err
	}

	return commitHash, false, nil
}

// List the commits for a repository
func (repo Repository) ListCommits() (<-chan Commit, error) {

	commits, err := kv.ListTopMostCommits()
	if err != nil {
		return nil, err
	}

	var commit string
	// TODO: Deal with multiple top most commits
	for c := range commits {
		commit = hex.EncodeToString(c)
	}

	result := make(chan Commit)

	go func() {
		defer close(result)

		for {
			co, err := core.GetCommitObject(commit)
			if err != nil {
				return
			}
			result <- Commit{Hash: commit, Message: co.S3gitMessage}

			if len(co.S3gitWarmParents) == 0 {
				break
			} else {
				// TODO: Deal with commits after first one
				commit = co.S3gitWarmParents[0]
			}
		}
	}()

	return result, nil
}
<commit_msg>Let listing of commits deal with forks<commit_after>package s3git

import (
	"encoding/hex"
	"errors"
	"time"
	"github.com/s3git/s3git-go/internal/core"
	"github.com/s3git/s3git-go/internal/kv"
)

type Commit struct {
	Hash    string
	Message string
	TimeStamp string
	Parent	string
}

// Perform a commit for the repository
func (repo Repository) Commit(message string) (hash string, empty bool, err error) {
	return repo.commit(message, "master", []string{})
}

// Perform a commit for the named branch of the repository
func (repo Repository) CommitToBranch(message, branch string) (hash string, empty bool, err error) {
	return repo.commit(message, branch, []string{})
}

func (repo Repository) commit(message, branch string, parents []string) (hash string, empty bool, err error) {

	warmParents := []string{}
	coldParents := []string{}

	commits, err := kv.ListTopMostCommits()
	if err != nil {
		return "", false, err
	}

	if len(parents) == 0 {
		for c := range commits {
			warmParents = append(warmParents, hex.EncodeToString(c))
		}
		if len(warmParents) > 1 {
			// TODO: Do extra check whether the trees are the same, in that case we can safely ignore the warning
			return "", false, errors.New("Multiple top most commits founds as parents")
		}
	} else {
		for c := range commits {
			p := hex.EncodeToString(c)
			if contains(parents, p) {
				warmParents = append(warmParents, p)
			} else {
				coldParents = append(coldParents, p)
			}
		}
	}

	return repo.commitWithWarmAndColdParents(message, branch, warmParents, coldParents)
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func (repo Repository) commitWithWarmAndColdParents(message, branch string, warmParents, coldParents []string) (hash string, empty bool, err error) {

	list, err := kv.ListStage()
	if err != nil {
		return "", false, err
	}

	// Create commit object on disk
	commitHash, empty, err := core.StoreCommitObject(message, branch, warmParents, coldParents, list, []string{})
	if err != nil {
		return "", false, err
	}
	if empty {
		return "", true, nil
	}

	// Remove added blobs from staging area
	err = kv.ClearStage()
	if err != nil {
		return "", false, err
	}

	err = core.StorePrefixObject(commitHash)
	if err != nil {
		return "", false, err
	}

	return commitHash, false, nil
}

// List the commits for a repository
func (repo Repository) ListCommits(branch string) (<-chan Commit, error) {

	// TODO: Implement support for branches
	commits, err := kv.ListTopMostCommits()
	if err != nil {
		return nil, err
	}

	inputs := []Commit{}

	for c := range commits {
		commit := hex.EncodeToString(c)
		start, _, err := getCommit(commit)
		if err != nil {
			return nil, err
		}
		inputs = append(inputs, *start)
	}

	result := make(chan Commit)

	go func() {
		defer close(result)

		for {
			if len(inputs) == 1 {
				result <- inputs[0]
				input, done, err := getCommit(inputs[0].Parent)
				if err != nil {
					return
				} else if done {
					return // no more new parent --> we are done
				}
				inputs[0] = *input
			} else if len(inputs) == 2 {
				t1, _ := time.Parse(time.RFC3339Nano, inputs[0].TimeStamp)
				t2, _ := time.Parse(time.RFC3339Nano, inputs[1].TimeStamp)

				if inputs[0].Hash == inputs[1].Hash {
					// Same commit object so discard second instance
					pos := 0
					inputs = append(inputs[0:pos], inputs[pos+1:len(inputs)]...)
					result <- inputs[pos]

					input, done, err := getCommit(inputs[pos].Parent)
					if err != nil {
						return
					} else if done {
						return // no more new parent --> we are done
					}
					inputs[pos] = *input

				} else if t1.After(t2) {
					result <- inputs[0]

					input, done, err := getCommit(inputs[0].Parent)
					if err != nil {
						return
					} else if done {
						return // no more new parent --> we are done
					}
					inputs[0] = *input
				} else {
					result <- inputs[1]

					input, done, err := getCommit(inputs[1].Parent)
					if err != nil {
						return
					} else if done {
						return // no more new parent --> we are done
					}
					inputs[1] = *input
				}
			}
		}
	}()

	return result, nil
}

func getCommit(commit string) (*Commit, bool, error) {
	if commit == "" {
		return nil, true, nil	// we are done
	}
	co, err := core.GetCommitObject(commit)
	if err != nil {
		return nil, false,  err
	}
	result := Commit{Hash: commit, Message: co.S3gitMessage, TimeStamp: co.S3gitTimeStamp}
	if len(co.S3gitWarmParents) == 1 {
		result.Parent = co.S3gitWarmParents[0]
	} else if len(co.S3gitWarmParents) > 1 {
		// TODO: Add other parents to inputs
		result.Parent = co.S3gitWarmParents[0]
	}
	return &result, false, err
}
<|endoftext|>


<commit_before>package stripe

import (
	"encoding/json"
	"net/url"
)

// Currency is the list of supported currencies.
// For more details see https://support.stripe.com/questions/which-currencies-does-stripe-support.
type Currency string

// FraudReport is the list of allowed values for reporting fraud.
// Allowed values are "fraudulent", "safe".
type FraudReport string

// ChargeParams is the set of parameters that can be used when creating or updating a charge.
// For more details see https://stripe.com/docs/api#create_charge and https://stripe.com/docs/api#update_charge.
type ChargeParams struct {
	Params
	Amount                       uint64
	Currency                     Currency
	Customer, Token              string
	Desc, Statement, Email, Dest string
	NoCapture                    bool
	Fee                          uint64
	Fraud                        FraudReport
	Source                       *SourceParams
	Shipping                     *ShippingDetails
}

// SetSource adds valid sources to a ChargeParams object,
// returning an error for unsupported sources.
func (cp *ChargeParams) SetSource(sp interface{}) error {
	source, err := SourceParamsFor(sp)
	cp.Source = source
	return err
}

// ChargeListParams is the set of parameters that can be used when listing charges.
// For more details see https://stripe.com/docs/api#list_charges.
type ChargeListParams struct {
	ListParams
	Created  int64
	Customer string
}

// CaptureParams is the set of parameters that can be used when capturing a charge.
// For more details see https://stripe.com/docs/api#charge_capture.
type CaptureParams struct {
	Params
	Amount, Fee uint64
	Email       string
}

// Charge is the resource representing a Stripe charge.
// For more details see https://stripe.com/docs/api#charges.
type Charge struct {
	ID             string            `json:"id"`
	Live           bool              `json:"livemode"`
	Amount         uint64            `json:"amount"`
	Captured       bool              `json:"captured"`
	Created        int64             `json:"created"`
	Currency       Currency          `json:"currency"`
	Paid           bool              `json:"paid"`
	Refunded       bool              `json:"refunded"`
	Refunds        *RefundList       `json:"refunds"`
	AmountRefunded uint64            `json:"amount_refunded"`
	Tx             *Transaction      `json:"balance_transaction"`
	Customer       *Customer         `json:"customer"`
	Desc           string            `json:"description"`
	Dispute        *Dispute          `json:"dispute"`
	FailMsg        string            `json:"failure_message"`
	FailCode       string            `json:"failure_code"`
	Invoice        *Invoice          `json:"invoice"`
	Meta           map[string]string `json:"metadata"`
	Email          string            `json:"receipt_email"`
	Statement      string            `json:"statement_descriptor"`
	FraudDetails   *FraudDetails     `json:"fraud_details"`
	Status         string            `json:"status"`
	Source         *PaymentSource    `json:"source"`
	Shipping       *ShippingDetails  `json:"shipping"`
	Dest           *Account          `json:"destination"`
	Fee            *Fee              `json:"application_fee"`
	Transfer       *Transfer         `json:"transfer"`
	SourceTransfer *Transfer         `json:"source_transfer"`
}

// FraudDetails is the structure detailing fraud status.
type FraudDetails struct {
	UserReport   FraudReport `json:"user_report"`
	StripeReport FraudReport `json:"stripe_report"`
}

// ShippingDetails is the structure containing shipping information.
type ShippingDetails struct {
	Name     string  `json:"name"`
	Address  Address `json:"address"`
	Phone    string  `json:"phone"`
	Tracking string  `json:"tracking_number"`
	Carrier  string  `json:"carrier"`
}

// AppendDetails adds the shipping details to the query string.
func (s *ShippingDetails) AppendDetails(values *url.Values) {
	values.Add("shipping[name]", s.Name)

	values.Add("shipping[address][line1]", s.Address.Line1)
	if len(s.Address.Line2) > 0 {
		values.Add("shipping[address][line2]", s.Address.Line2)
	}
	if len(s.Address.City) > 0 {
		values.Add("shipping[address][city]", s.Address.City)
	}

	if len(s.Address.State) > 0 {
		values.Add("shipping[address][state]", s.Address.State)
	}

	if len(s.Address.Country) > 0 {
		values.Add("shipping[address][country]", s.Address.Country)
	}

	if len(s.Address.Zip) > 0 {
		values.Add("shipping[address][postal_code]", s.Address.Zip)
	}

	if len(s.Phone) > 0 {
		values.Add("shipping[phone]", s.Phone)
	}

	if len(s.Tracking) > 0 {
		values.Add("shipping[tracking_number]", s.Tracking)
	}

	if len(s.Carrier) > 0 {
		values.Add("shipping[carrier]", s.Carrier)
	}
}

// UnmarshalJSON handles deserialization of a Charge.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (c *Charge) UnmarshalJSON(data []byte) error {
	type charge Charge
	var cc charge
	err := json.Unmarshal(data, &cc)
	if err == nil {
		*c = Charge(cc)
	} else {
		// the id is surrounded by "\" characters, so strip them
		c.ID = string(data[1 : len(data)-1])
	}

	return nil
}
<commit_msg>charge: add outcome fields<commit_after>package stripe

import (
	"encoding/json"
	"net/url"
)

// Currency is the list of supported currencies.
// For more details see https://support.stripe.com/questions/which-currencies-does-stripe-support.
type Currency string

// FraudReport is the list of allowed values for reporting fraud.
// Allowed values are "fraudulent", "safe".
type FraudReport string

// ChargeParams is the set of parameters that can be used when creating or updating a charge.
// For more details see https://stripe.com/docs/api#create_charge and https://stripe.com/docs/api#update_charge.
type ChargeParams struct {
	Params
	Amount                       uint64
	Currency                     Currency
	Customer, Token              string
	Desc, Statement, Email, Dest string
	NoCapture                    bool
	Fee                          uint64
	Fraud                        FraudReport
	Source                       *SourceParams
	Shipping                     *ShippingDetails
}

// SetSource adds valid sources to a ChargeParams object,
// returning an error for unsupported sources.
func (cp *ChargeParams) SetSource(sp interface{}) error {
	source, err := SourceParamsFor(sp)
	cp.Source = source
	return err
}

// ChargeListParams is the set of parameters that can be used when listing charges.
// For more details see https://stripe.com/docs/api#list_charges.
type ChargeListParams struct {
	ListParams
	Created  int64
	Customer string
}

// CaptureParams is the set of parameters that can be used when capturing a charge.
// For more details see https://stripe.com/docs/api#charge_capture.
type CaptureParams struct {
	Params
	Amount, Fee uint64
	Email       string
}

// Charge is the resource representing a Stripe charge.
// For more details see https://stripe.com/docs/api#charges.
type Charge struct {
	Amount         uint64            `json:"amount"`
	AmountRefunded uint64            `json:"amount_refunded"`
	Captured       bool              `json:"captured"`
	Created        int64             `json:"created"`
	Currency       Currency          `json:"currency"`
	Customer       *Customer         `json:"customer"`
	Desc           string            `json:"description"`
	Dest           *Account          `json:"destination"`
	Dispute        *Dispute          `json:"dispute"`
	Email          string            `json:"receipt_email"`
	FailCode       string            `json:"failure_code"`
	FailMsg        string            `json:"failure_message"`
	Fee            *Fee              `json:"application_fee"`
	FraudDetails   *FraudDetails     `json:"fraud_details"`
	ID             string            `json:"id"`
	Invoice        *Invoice          `json:"invoice"`
	Live           bool              `json:"livemode"`
	Meta           map[string]string `json:"metadata"`
	Outcome        *Outcome          `json:"outcome"`
	Paid           bool              `json:"paid"`
	Refunded       bool              `json:"refunded"`
	Refunds        *RefundList       `json:"refunds"`
	Shipping       *ShippingDetails  `json:"shipping"`
	Source         *PaymentSource    `json:"source"`
	SourceTransfer *Transfer         `json:"source_transfer"`
	Statement      string            `json:"statement_descriptor"`
	Status         string            `json:"status"`
	Transfer       *Transfer         `json:"transfer"`
	Tx             *Transaction      `json:"balance_transaction"`
}

// FraudDetails is the structure detailing fraud status.
type FraudDetails struct {
	UserReport   FraudReport `json:"user_report"`
	StripeReport FraudReport `json:"stripe_report"`
}

// Outcome is the charge's outcome that details whether a payment
// was accepted and why.
type Outcome struct {
	NetworkStatus string `json:"network_status"`
	Reason        string `json:"reason"`
	SellerMessage string `json:"seller_message"`
	Type          string `json:"type"`
}

// ShippingDetails is the structure containing shipping information.
type ShippingDetails struct {
	Name     string  `json:"name"`
	Address  Address `json:"address"`
	Phone    string  `json:"phone"`
	Tracking string  `json:"tracking_number"`
	Carrier  string  `json:"carrier"`
}

// AppendDetails adds the shipping details to the query string.
func (s *ShippingDetails) AppendDetails(values *url.Values) {
	values.Add("shipping[name]", s.Name)

	values.Add("shipping[address][line1]", s.Address.Line1)
	if len(s.Address.Line2) > 0 {
		values.Add("shipping[address][line2]", s.Address.Line2)
	}
	if len(s.Address.City) > 0 {
		values.Add("shipping[address][city]", s.Address.City)
	}

	if len(s.Address.State) > 0 {
		values.Add("shipping[address][state]", s.Address.State)
	}

	if len(s.Address.Country) > 0 {
		values.Add("shipping[address][country]", s.Address.Country)
	}

	if len(s.Address.Zip) > 0 {
		values.Add("shipping[address][postal_code]", s.Address.Zip)
	}

	if len(s.Phone) > 0 {
		values.Add("shipping[phone]", s.Phone)
	}

	if len(s.Tracking) > 0 {
		values.Add("shipping[tracking_number]", s.Tracking)
	}

	if len(s.Carrier) > 0 {
		values.Add("shipping[carrier]", s.Carrier)
	}
}

// UnmarshalJSON handles deserialization of a Charge.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (c *Charge) UnmarshalJSON(data []byte) error {
	type charge Charge
	var cc charge
	err := json.Unmarshal(data, &cc)
	if err == nil {
		*c = Charge(cc)
	} else {
		// the id is surrounded by "\" characters, so strip them
		c.ID = string(data[1 : len(data)-1])
	}

	return nil
}
<|endoftext|>


<commit_before>package rest

import (
	"encoding/json"
	"fmt"
	"socialapi/models"
)

func GetInteractions(interactionType string, postId int64) ([]string, error) {
	url := fmt.Sprintf("/message/%d/interaction/%s", postId, interactionType)
	res, err := sendRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	var interactions []string
	err = json.Unmarshal(res, &interactions)
	if err != nil {
		return nil, err
	}

	return interactions, nil
}

func AddInteraction(iType string, postId, accountId int64) (*models.Interaction, error) {
	cm := models.NewInteraction()
	cm.AccountId = accountId
	cm.MessageId = postId

	url := fmt.Sprintf("/message/%d/interaction/%s/add", postId, iType)
	_, err := sendModel("POST", url, cm)
	if err != nil {
		return cm, err
	}

	return cm, nil
}

func DeleteInteraction(interactionType string, postId, accountId int64) error {
	cm := models.NewInteraction()
	cm.AccountId = accountId
	cm.MessageId = postId

	url := fmt.Sprintf("/message/%d/interaction/%s/delete", postId, interactionType)
	_, err := marshallAndSendRequest("POST", url, cm)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>socialapi: rest func is added<commit_after>package rest

import (
	"encoding/json"
	"fmt"
	"socialapi/models"
)

func GetInteractions(interactionType string, postId int64) ([]string, error) {
	url := fmt.Sprintf("/message/%d/interaction/%s", postId, interactionType)
	res, err := sendRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	var interactions []string
	err = json.Unmarshal(res, &interactions)
	if err != nil {
		return nil, err
	}

	return interactions, nil
}

func AddInteraction(iType string, postId, accountId int64) (*models.Interaction, error) {
	cm := models.NewInteraction()
	cm.AccountId = accountId
	cm.MessageId = postId

	url := fmt.Sprintf("/message/%d/interaction/%s/add", postId, iType)
	_, err := sendModel("POST", url, cm)
	if err != nil {
		return cm, err
	}

	return cm, nil
}

func DeleteInteraction(interactionType string, postId, accountId int64) error {
	cm := models.NewInteraction()
	cm.AccountId = accountId
	cm.MessageId = postId

	url := fmt.Sprintf("/message/%d/interaction/%s/delete", postId, interactionType)
	_, err := marshallAndSendRequest("POST", url, cm)
	if err != nil {
		return err
	}
	return nil
}

func ListInteractedMesssagesInteraction(iType string, accountId int64, token string) ([]*models.ChannelMessageContainer, error) {
	url := fmt.Sprintf("/account/%d/interactions/%s", accountId, iType)

	var cm []*models.ChannelMessageContainer
	res, err := sendRequestWithAuth("GET", url, nil, token)
	if err != nil {
		return cm, err
	}

	err = json.Unmarshal(res, &cm)
	if err != nil {
		return nil, err
	}
	return cm, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/Symantec/tricorder/go/tricorder/messages"
	"log"
	"net/rpc"
	"os"
	"time"
)

func printAsJson(desc string, value interface{}) {
	fmt.Println(desc)
	var buffer bytes.Buffer
	content, err := json.Marshal(value)
	if err != nil {
		log.Fatal("Marshalling:", err)
	}
	json.Indent(&buffer, content, "", "\t")
	buffer.WriteTo(os.Stdin)
	fmt.Println()
}

func main() {
	client, err := rpc.DialHTTP("tcp", ":8080")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	defer client.Close()
	var metrics messages.MetricList
	err = client.Call("MetricsServer.ListMetrics", "", &metrics)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("All metrics", metrics)

	err = client.Call("MetricsServer.ListMetrics", "/aaa/bbb", &metrics)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("aaa/bbb metrics", metrics)

	var single messages.Metric
	err = client.Call("MetricsServer.GetMetric", "/proc/foo/bar/baz", &single)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("/proc/foo/bar/baz metric", single)

	err = client.Call("MetricsServer.GetMetric", "/proc/foo/ddd", &single)
	if err != nil {
		log.Println("Got error for /proc/foo/ddd:", err)
	} else {
		printAsJson("/proc/foo/ddd metric", single)
	}
	time.Sleep(5 * time.Second)

}
<commit_msg>Add list metric in tricorderclient.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/Symantec/tricorder/go/tricorder/messages"
	"log"
	"net/rpc"
	"os"
	"time"
)

func printAsJson(desc string, value interface{}) {
	fmt.Println(desc)
	var buffer bytes.Buffer
	content, err := json.Marshal(value)
	if err != nil {
		log.Fatal("Marshalling:", err)
	}
	json.Indent(&buffer, content, "", "\t")
	buffer.WriteTo(os.Stdin)
	fmt.Println()
}

func main() {
	client, err := rpc.DialHTTP("tcp", ":8080")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	defer client.Close()
	var metrics messages.MetricList
	err = client.Call("MetricsServer.ListMetrics", "", &metrics)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("All metrics", metrics)

	err = client.Call("MetricsServer.ListMetrics", "/aaa/bbb", &metrics)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("aaa/bbb metrics", metrics)

	var single messages.Metric
	err = client.Call("MetricsServer.GetMetric", "/proc/foo/bar/baz", &single)
	if err != nil {
		log.Fatal("Calling:", err)
	}
	printAsJson("/proc/foo/bar/baz metric", single)

	err = client.Call("MetricsServer.GetMetric", "/proc/foo/ddd", &single)
	if err != nil {
		log.Println("Got error for /proc/foo/ddd:", err)
	} else {
		printAsJson("/proc/foo/ddd metric", single)
	}

	err = client.Call("MetricsServer.GetMetric", "/list/squares", &single)
	if err != nil {
		log.Println("Got error for /list/squares:", err)
	} else {
		printAsJson("/list/squares metric", single)
	}

	time.Sleep(5 * time.Second)

}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"fmt"
	"strconv"
	"strings"

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

var checkpointCommand = cli.Command{
	Name:  "checkpoint",
	Usage: "checkpoint a running container",
	Flags: []cli.Flag{
		cli.StringFlag{Name: "image-path", Value: "", Usage: "path for saving criu image files"},
		cli.StringFlag{Name: "work-path", Value: "", Usage: "path for saving work files and logs"},
		cli.BoolFlag{Name: "leave-running", Usage: "leave the process running after checkpointing"},
		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.StringFlag{Name: "page-server", Value: "", Usage: "ADDRESS:PORT of the page server"},
		cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"},
	},
	Action: func(context *cli.Context) {
		container, err := getContainer(context)
		if err != nil {
			fatal(err)
		}
		options := criuOptions(context)
		// these are the mandatory criu options for a container
		setPageServer(context, options)
		if err := container.Checkpoint(options); err != nil {
			fatal(err)
		}
	},
}

func getCheckpointImagePath(context *cli.Context) string {
	imagePath := context.String("image-path")
	if imagePath == "" {
		imagePath = getDefaultImagePath(context)
	}
	return imagePath
}

func setPageServer(context *cli.Context, options *libcontainer.CriuOpts) {
	// xxx following criu opts are optional
	// The dump image can be sent to a criu page server
	if psOpt := context.String("page-server"); psOpt != "" {
		addressPort := strings.Split(psOpt, ":")
		if len(addressPort) != 2 {
			fatal(fmt.Errorf("Use --page-server ADDRESS:PORT to specify page server"))
		}
		portInt, err := strconv.Atoi(addressPort[1])
		if err != nil {
			fatal(fmt.Errorf("Invalid port number"))
		}
		options.PageServer = libcontainer.CriuPageServerInfo{
			Address: addressPort[0],
			Port:    int32(portInt),
		}
	}
}
<commit_msg>Fixing checkpoint issue<commit_after>// +build linux

package main

import (
	"fmt"
	"strconv"
	"strings"

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

var checkpointCommand = cli.Command{
	Name:  "checkpoint",
	Usage: "checkpoint a running container",
	Flags: []cli.Flag{
		cli.StringFlag{Name: "image-path", Value: "", Usage: "path for saving criu image files"},
		cli.StringFlag{Name: "work-path", Value: "", Usage: "path for saving work files and logs"},
		cli.BoolFlag{Name: "leave-running", Usage: "leave the process running after checkpointing"},
		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.StringFlag{Name: "page-server", Value: "", Usage: "ADDRESS:PORT of the page server"},
		cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"},
	},
	Action: func(context *cli.Context) {
		container, err := getContainer(context)
		if err != nil {
			fatal(err)
		}
		options := criuOptions(context)
		status, err := container.Status()
		if err != nil {
			fatal(err)
		}
		if status == libcontainer.Checkpointed {
			fatal(fmt.Errorf("Container with id %s already checkpointed", context.GlobalString("id")))
		}
		// these are the mandatory criu options for a container
		setPageServer(context, options)
		if err := container.Checkpoint(options); err != nil {
			fatal(err)
		}
	},
}

func getCheckpointImagePath(context *cli.Context) string {
	imagePath := context.String("image-path")
	if imagePath == "" {
		imagePath = getDefaultImagePath(context)
	}
	return imagePath
}

func setPageServer(context *cli.Context, options *libcontainer.CriuOpts) {
	// xxx following criu opts are optional
	// The dump image can be sent to a criu page server
	if psOpt := context.String("page-server"); psOpt != "" {
		addressPort := strings.Split(psOpt, ":")
		if len(addressPort) != 2 {
			fatal(fmt.Errorf("Use --page-server ADDRESS:PORT to specify page server"))
		}
		portInt, err := strconv.Atoi(addressPort[1])
		if err != nil {
			fatal(fmt.Errorf("Invalid port number"))
		}
		options.PageServer = libcontainer.CriuPageServerInfo{
			Address: addressPort[0],
			Port:    int32(portInt),
		}
	}
}
<|endoftext|>


<commit_before>package printer

import (
	"fmt"
	"io"
)

//
// DebugPrinter wraps a Printer with debug messages
//
type DebugPrinter struct {
	P Printer
}

func (d *DebugPrinter) Reset() {
	d.P.Reset()
}

func (d *DebugPrinter) PushContext() {
	d.P.PushContext()
}

func (d *DebugPrinter) PopContext() {
	d.P.PopContext()
}

func (d *DebugPrinter) SetWriter(w io.Writer) {
	d.P.SetWriter(w)
}

func (d *DebugPrinter) UpdateLevel(delta int) {
	d.P.UpdateLevel(delta)
}

func (d *DebugPrinter) SameLine() {
	d.P.SameLine()
}

func (d *DebugPrinter) IsSameLine() bool {
	return d.P.IsSameLine()
}

func (d *DebugPrinter) Chop(line string) string {
	return d.P.Chop(line)
}

func (d *DebugPrinter) Print(values ...string) {
	d.P.Print(values...)
}

func (d *DebugPrinter) PrintLevel(term string, values ...string) {
	d.P.PrintLevel(term, values...)
}

func (d *DebugPrinter) PrintBlockStart(b BlockType, empty bool) {
	d.P.PrintBlockStart(b, empty)
}

func (d *DebugPrinter) PrintBlockEnd(b BlockType) {
	d.P.PrintBlockEnd(b)
}

func (d *DebugPrinter) PrintPackage(name string) {
	fmt.Println("/* PrintPackage", name, "*/")
	d.P.PrintPackage(name)
}

func (d *DebugPrinter) PrintImport(name, path string) {
	fmt.Println("/* PrintImport", name, path, "*/")
	d.P.PrintImport(name, path)
}

func (d *DebugPrinter) PrintType(name, typedef string) {
	fmt.Println("/* PrintType", name, typedef, "*/")
	d.P.PrintType(name, typedef)
}

func (d *DebugPrinter) PrintValue(vtype, typedef, names, values string, ntuple, vtuple bool) {
	fmt.Println("/* PrintValue", vtype, typedef, names, values, ntuple, vtuple, "*/")
	d.P.PrintValue(vtype, typedef, names, values, ntuple, vtuple)
}

func (d *DebugPrinter) PrintStmt(stmt, expr string) {
	fmt.Println("/* PrintStmt", stmt, expr, "*/")
	d.P.PrintStmt(stmt, expr)
}

func (d *DebugPrinter) PrintReturn(expr string, tuple bool) {
	fmt.Println("/* PrintReturn", expr, tuple, "*/")
	d.P.PrintReturn(expr, tuple)
}

func (d *DebugPrinter) PrintFunc(receiver, name, params, results string) {
	fmt.Println("/* PrintFunc", receiver, name, params, results, "*/")
	d.P.PrintFunc(receiver, name, params, results)
}

func (d *DebugPrinter) PrintFor(init, cond, post string) {
	fmt.Println("/* PrintFor", init, cond, post, "*/")
	d.P.PrintFor(init, cond, post)
}

func (d *DebugPrinter) PrintRange(key, value, expr string) {
	fmt.Println("/* PrintRange", key, value, expr, "*/")
	d.P.PrintRange(key, value, expr)
}

func (d *DebugPrinter) PrintSwitch(init, expr string) {
	fmt.Println("/* PrintSwitch", init, expr, "*/")
	d.P.PrintSwitch(init, expr)
}

func (d *DebugPrinter) PrintCase(expr string) {
	fmt.Println("/* PrintCase", expr, "*/")
	d.P.PrintCase(expr)
}

func (d *DebugPrinter) PrintEndCase() {
	fmt.Println("/* PrintEndCase", "*/")
	d.P.PrintEndCase()
}

func (d *DebugPrinter) PrintIf(init, cond string) {
	fmt.Println("/* PrintIf", init, cond, "*/")
	d.P.PrintIf(init, cond)
}

func (d *DebugPrinter) PrintElse() {
	fmt.Println("/* PrintElse", "*/")
	d.P.PrintElse()
}

func (d *DebugPrinter) PrintEmpty() {
	fmt.Println("/* PrintEmpty", "*/")
	d.P.PrintEmpty()
}

func (d *DebugPrinter) PrintAssignment(lhs, op, rhs string, ltuple, rtuple bool) {
	fmt.Println("/* PrintAssignment", lhs, op, rhs, ltuple, rtuple, "*/")
	d.P.PrintAssignment(lhs, op, rhs, ltuple, rtuple)
}

func (d *DebugPrinter) PrintSend(ch, value string) {
	fmt.Println("/* PrintSend", ch, value, "*/")
	d.P.PrintSend(ch, value)
}

func (d *DebugPrinter) FormatIdent(id string) string {
	fmt.Println("/* FormatIdent", id, "*/")
	return d.P.FormatIdent(id)
}

func (d *DebugPrinter) FormatLiteral(lit string) string {
	fmt.Println("/* FormatLiteral", lit, "*/")
	return d.P.FormatLiteral(lit)
}

func (d *DebugPrinter) FormatCompositeLit(typedef, elt string) string {
	fmt.Println("/* FormatCompositeLit", typedef, elt, "*/")
	return d.P.FormatCompositeLit(typedef, elt)
}

func (d *DebugPrinter) FormatEllipsis(expr string) string {
	fmt.Println("/* FormatEllipsis", expr, "*/")
	return d.P.FormatEllipsis(expr)
}

func (d *DebugPrinter) FormatStar(expr string) string {
	fmt.Println("/* FormatStar", expr, "*/")
	return d.P.FormatStar(expr)
}

func (d *DebugPrinter) FormatParen(expr string) string {
	fmt.Println("/* FormatParen", expr, "*/")
	return d.P.FormatParen(expr)
}

func (d *DebugPrinter) FormatUnary(op, operand string) string {
	fmt.Println("/* FormatUnary", op, operand, "*/")
	return d.P.FormatUnary(op, operand)
}

func (d *DebugPrinter) FormatBinary(lhs, op, rhs string) string {
	fmt.Println("/* FormatBinary", lhs, op, rhs, "*/")
	return d.P.FormatBinary(lhs, op, rhs)
}

func (d *DebugPrinter) FormatPair(v Pair, t FieldType) string {
	fmt.Println("/* FormatPair", v, t, "*/")
	return d.P.FormatPair(v, t)
}

func (d *DebugPrinter) FormatArray(len, elt string) string {
	fmt.Println("/* FormatArray", len, elt, "*/")
	return d.P.FormatArray(len, elt)
}

func (d *DebugPrinter) FormatArrayIndex(array, index string) string {
	fmt.Println("/* FormatArrayIndex", array, index, "*/")
	return d.P.FormatArrayIndex(array, index)
}

func (d *DebugPrinter) FormatSlice(slice, low, high, max string) string {
	fmt.Println("/* FormatSlice", low, high, max, "*/")
	return d.P.FormatSlice(slice, low, high, max)
}

func (d *DebugPrinter) FormatMap(key, elt string) string {
	fmt.Println("/* FormatMap", key, elt, "*/")
	return d.P.FormatMap(key, elt)
}

func (d *DebugPrinter) FormatKeyValue(key, value string) string {
	fmt.Println("/* FormatKeyValue", key, value, "*/")
	return d.P.FormatKeyValue(key, value)
}

func (d *DebugPrinter) FormatStruct(fields string) string {
	fmt.Println("/* FormatStruct", fields, "*/")
	return d.P.FormatStruct(fields)
}

func (d *DebugPrinter) FormatInterface(methods string) string {
	fmt.Println("/* FormatInterface", methods, "*/")
	return d.P.FormatInterface(methods)
}

func (d *DebugPrinter) FormatChan(chdir, mtype string) string {
	fmt.Println("/* FormatChan", chdir, mtype, "*/")
	return d.P.FormatChan(chdir, mtype)
}

func (d *DebugPrinter) FormatCall(fun, args string, isFuncLit bool) string {
	fmt.Println("/* FormatCall", fun, args, isFuncLit, "*/")
	return d.P.FormatCall(fun, args, isFuncLit)
}

func (d *DebugPrinter) FormatFuncType(params, results string, withFunc bool) string {
	fmt.Println("/* FormatFuncType", params, results, withFunc, "*/")
	return d.P.FormatFuncType(params, results, withFunc)
}

func (d *DebugPrinter) FormatFuncLit(ftype, body string) string {
	fmt.Println("/* FormatFuncLit", ftype, body, "*/")
	return d.P.FormatFuncLit(ftype, body)
}

func (d *DebugPrinter) FormatSelector(pname, sel string, isObject bool) string {
	fmt.Println("/* FormatSelector", pname, sel, isObject, "*/")
	return d.P.FormatSelector(pname, sel, isObject)
}

func (d *DebugPrinter) FormatTypeAssert(orig, assert string) string {
	fmt.Println("/* FormatTypeAssert", orig, assert, "*/")
	return d.P.FormatTypeAssert(orig, assert)
}
<commit_msg>more debug info<commit_after>package printer

import (
	"fmt"
	"io"
)

//
// DebugPrinter wraps a Printer with debug messages
//
type DebugPrinter struct {
	P Printer
}

func (d *DebugPrinter) Reset() {
	d.P.Reset()
}

func (d *DebugPrinter) PushContext() {
	d.P.PushContext()
}

func (d *DebugPrinter) PopContext() {
	d.P.PopContext()
}

func (d *DebugPrinter) SetWriter(w io.Writer) {
	d.P.SetWriter(w)
}

func (d *DebugPrinter) UpdateLevel(delta int) {
	d.P.UpdateLevel(delta)
}

func (d *DebugPrinter) SameLine() {
	fmt.Print("/* SameLine */")
	d.P.SameLine()
}

func (d *DebugPrinter) IsSameLine() bool {
	fmt.Print("/* IsSameLine */")
	return d.P.IsSameLine()
}

func (d *DebugPrinter) Chop(line string) string {
	return d.P.Chop(line)
}

func (d *DebugPrinter) Print(values ...string) {
	d.P.Print(values...)
}

func (d *DebugPrinter) PrintLevel(term string, values ...string) {
	d.P.PrintLevel(term, values...)
}

func (d *DebugPrinter) PrintBlockStart(b BlockType, empty bool) {
	fmt.Print("/* PrintBlockStart", b, "*/")
	d.P.PrintBlockStart(b, empty)
}

func (d *DebugPrinter) PrintBlockEnd(b BlockType) {
	d.P.PrintBlockEnd(b)
	fmt.Print("/* PrintBlockEnd", "*/")
}

func (d *DebugPrinter) PrintPackage(name string) {
	fmt.Println("/* PrintPackage", name, "*/")
	d.P.PrintPackage(name)
}

func (d *DebugPrinter) PrintImport(name, path string) {
	fmt.Println("/* PrintImport", name, path, "*/")
	d.P.PrintImport(name, path)
}

func (d *DebugPrinter) PrintType(name, typedef string) {
	fmt.Println("/* PrintType", name, typedef, "*/")
	d.P.PrintType(name, typedef)
}

func (d *DebugPrinter) PrintValue(vtype, typedef, names, values string, ntuple, vtuple bool) {
	fmt.Println("/* PrintValue", vtype, typedef, names, values, ntuple, vtuple, "*/")
	d.P.PrintValue(vtype, typedef, names, values, ntuple, vtuple)
}

func (d *DebugPrinter) PrintStmt(stmt, expr string) {
	fmt.Println("/* PrintStmt", stmt, expr, "*/")
	d.P.PrintStmt(stmt, expr)
}

func (d *DebugPrinter) PrintReturn(expr string, tuple bool) {
	fmt.Println("/* PrintReturn", expr, tuple, "*/")
	d.P.PrintReturn(expr, tuple)
}

func (d *DebugPrinter) PrintFunc(receiver, name, params, results string) {
	fmt.Println("/* PrintFunc", receiver, name, params, results, "*/")
	d.P.PrintFunc(receiver, name, params, results)
}

func (d *DebugPrinter) PrintFor(init, cond, post string) {
	fmt.Println("/* PrintFor", init, cond, post, "*/")
	d.P.PrintFor(init, cond, post)
}

func (d *DebugPrinter) PrintRange(key, value, expr string) {
	fmt.Println("/* PrintRange", key, value, expr, "*/")
	d.P.PrintRange(key, value, expr)
}

func (d *DebugPrinter) PrintSwitch(init, expr string) {
	fmt.Println("/* PrintSwitch", init, expr, "*/")
	d.P.PrintSwitch(init, expr)
}

func (d *DebugPrinter) PrintCase(expr string) {
	fmt.Println("/* PrintCase", expr, "*/")
	d.P.PrintCase(expr)
}

func (d *DebugPrinter) PrintEndCase() {
	fmt.Println("/* PrintEndCase", "*/")
	d.P.PrintEndCase()
}

func (d *DebugPrinter) PrintIf(init, cond string) {
	fmt.Println("/* PrintIf", init, cond, "*/")
	d.P.PrintIf(init, cond)
}

func (d *DebugPrinter) PrintElse() {
	fmt.Println("/* PrintElse", "*/")
	d.P.PrintElse()
}

func (d *DebugPrinter) PrintEmpty() {
	fmt.Println("/* PrintEmpty", "*/")
	d.P.PrintEmpty()
}

func (d *DebugPrinter) PrintAssignment(lhs, op, rhs string, ltuple, rtuple bool) {
	fmt.Println("/* PrintAssignment", lhs, op, rhs, ltuple, rtuple, "*/")
	d.P.PrintAssignment(lhs, op, rhs, ltuple, rtuple)
}

func (d *DebugPrinter) PrintSend(ch, value string) {
	fmt.Println("/* PrintSend", ch, value, "*/")
	d.P.PrintSend(ch, value)
}

func (d *DebugPrinter) FormatIdent(id string) string {
	fmt.Println("/* FormatIdent", id, "*/")
	return d.P.FormatIdent(id)
}

func (d *DebugPrinter) FormatLiteral(lit string) string {
	fmt.Println("/* FormatLiteral", lit, "*/")
	return d.P.FormatLiteral(lit)
}

func (d *DebugPrinter) FormatCompositeLit(typedef, elt string) string {
	fmt.Println("/* FormatCompositeLit", typedef, elt, "*/")
	return d.P.FormatCompositeLit(typedef, elt)
}

func (d *DebugPrinter) FormatEllipsis(expr string) string {
	fmt.Println("/* FormatEllipsis", expr, "*/")
	return d.P.FormatEllipsis(expr)
}

func (d *DebugPrinter) FormatStar(expr string) string {
	fmt.Println("/* FormatStar", expr, "*/")
	return d.P.FormatStar(expr)
}

func (d *DebugPrinter) FormatParen(expr string) string {
	fmt.Println("/* FormatParen", expr, "*/")
	return d.P.FormatParen(expr)
}

func (d *DebugPrinter) FormatUnary(op, operand string) string {
	fmt.Println("/* FormatUnary", op, operand, "*/")
	return d.P.FormatUnary(op, operand)
}

func (d *DebugPrinter) FormatBinary(lhs, op, rhs string) string {
	fmt.Println("/* FormatBinary", lhs, op, rhs, "*/")
	return d.P.FormatBinary(lhs, op, rhs)
}

func (d *DebugPrinter) FormatPair(v Pair, t FieldType) string {
	fmt.Println("/* FormatPair", v, t, "*/")
	return d.P.FormatPair(v, t)
}

func (d *DebugPrinter) FormatArray(len, elt string) string {
	fmt.Println("/* FormatArray", len, elt, "*/")
	return d.P.FormatArray(len, elt)
}

func (d *DebugPrinter) FormatArrayIndex(array, index string) string {
	fmt.Println("/* FormatArrayIndex", array, index, "*/")
	return d.P.FormatArrayIndex(array, index)
}

func (d *DebugPrinter) FormatSlice(slice, low, high, max string) string {
	fmt.Println("/* FormatSlice", low, high, max, "*/")
	return d.P.FormatSlice(slice, low, high, max)
}

func (d *DebugPrinter) FormatMap(key, elt string) string {
	fmt.Println("/* FormatMap", key, elt, "*/")
	return d.P.FormatMap(key, elt)
}

func (d *DebugPrinter) FormatKeyValue(key, value string) string {
	fmt.Println("/* FormatKeyValue", key, value, "*/")
	return d.P.FormatKeyValue(key, value)
}

func (d *DebugPrinter) FormatStruct(fields string) string {
	fmt.Println("/* FormatStruct", fields, "*/")
	return d.P.FormatStruct(fields)
}

func (d *DebugPrinter) FormatInterface(methods string) string {
	fmt.Println("/* FormatInterface", methods, "*/")
	return d.P.FormatInterface(methods)
}

func (d *DebugPrinter) FormatChan(chdir, mtype string) string {
	fmt.Println("/* FormatChan", chdir, mtype, "*/")
	return d.P.FormatChan(chdir, mtype)
}

func (d *DebugPrinter) FormatCall(fun, args string, isFuncLit bool) string {
	fmt.Println("/* FormatCall", fun, args, isFuncLit, "*/")
	return d.P.FormatCall(fun, args, isFuncLit)
}

func (d *DebugPrinter) FormatFuncType(params, results string, withFunc bool) string {
	fmt.Println("/* FormatFuncType", params, results, withFunc, "*/")
	return d.P.FormatFuncType(params, results, withFunc)
}

func (d *DebugPrinter) FormatFuncLit(ftype, body string) string {
	fmt.Println("/* FormatFuncLit", ftype, body, "*/")
	return d.P.FormatFuncLit(ftype, body)
}

func (d *DebugPrinter) FormatSelector(pname, sel string, isObject bool) string {
	fmt.Println("/* FormatSelector", pname, sel, isObject, "*/")
	return d.P.FormatSelector(pname, sel, isObject)
}

func (d *DebugPrinter) FormatTypeAssert(orig, assert string) string {
	fmt.Println("/* FormatTypeAssert", orig, assert, "*/")
	return d.P.FormatTypeAssert(orig, assert)
}
<|endoftext|>