<commit_before>package twse

import (
	"encoding/csv"
	"errors"
	"fmt"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/toomore/gogrs/utils"
)

// TWSECLASS is a class list of TWSE.
var TWSECLASS = map[string]string{
	"MS":         "大盤統計資訊",
	"0049":       "封閉式基金",
	"0099P":      "ETF",
	"01":         "水泥工業",
	"019919T":    "受益證券",
	"02":         "食品工業",
	"03":         "塑膠工業",
	"04":         "紡織纖維",
	"05":         "電機機械",
	"06":         "電器電纜",
	"07":         "化學生技醫療",
	"08":         "玻璃陶瓷",
	"09":         "造紙工業",
	"0999":       "認購權證", //(不含牛證)
	"0999B":      "熊證",
	"0999C":      "牛證",
	"0999G9":     "認股權憑證",
	"0999GA":     "附認股權特別股",
	"0999GD":     "附認股權公司債",
	"0999P":      "認售權證", //(不含熊證)
	"0999X":      "可展延牛證",
	"0999Y":      "可展延熊證",
	"10":         "鋼鐵工業",
	"11":         "橡膠工業",
	"12":         "汽車工業",
	"13":         "電子工業",
	"14":         "建材營造",
	"15":         "航運業",
	"16":         "觀光事業",
	"17":         "金融保險",
	"18":         "貿易百貨",
	"19":         "綜合",
	"20":         "其他",
	"21":         "化學工業",
	"22":         "生技醫療業",
	"23":         "油電燃氣業",
	"24":         "半導體業",
	"25":         "電腦及週邊設備業",
	"26":         "光電業",
	"27":         "通信網路業",
	"28":         "電子零組件業",
	"29":         "電子通路業",
	"30":         "資訊服務業",
	"31":         "其他電子業",
	"9299":       "存託憑證",
	"ALL":        "全部",
	"ALLBUT0999": "全部(不含權證、牛熊證、可展延牛熊證)",
	"CB":         "可轉換公司債",
}

// StockInfo is simple stock info for no, name.
type StockInfo struct {
	No   string
	Name string
}

// Lists is to get TWSE list.
type Lists struct {
	Date            time.Time
	FmtData         map[string]FmtListData
	categoryRawData map[string][][]string
	categoryNoList  map[string][]StockInfo
}

var errorNotSupport = errors.New("Not support.")

// NewLists new a Lists.
func NewLists(t time.Time) *Lists {
	return &Lists{
		Date:            t,
		FmtData:         make(map[string]FmtListData),
		categoryRawData: make(map[string][][]string),
		categoryNoList:  make(map[string][]StockInfo),
	}
}

// Get is to get TWSE csv data.
func (l *Lists) Get(category string) ([][]string, error) {
	if TWSECLASS[category] == "" {
		return nil, errorNotSupport
	}

	year, month, day := l.Date.Date()
	data, err := hCache.PostForm(fmt.Sprintf("%s%s", utils.TWSEHOST, utils.TWSELISTCSV),
		url.Values{"download": {"csv"}, "selectType": {category},
			"qdate": {fmt.Sprintf("%d/%02d/%02d", year-1911, month, day)}})

	if err != nil {
		return nil, fmt.Errorf(errorNetworkFail.Error(), err)
	}

	csvArrayContent := strings.Split(string(data), "\n")

	var csvReader *csv.Reader
	switch category {
	case "MS":
		if len(csvArrayContent) > 6 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:51], "\n")))
		}
	case "ALLBUT0999", "ALL":
		if len(csvArrayContent) > 155 {
			re := regexp.MustCompile("^=?[\"]{1}[0-9A-Z]{4,}")
			var pickdata []string
			for _, v := range csvArrayContent {
				if re.MatchString(v) {
					if v[0] == 61 {
						pickdata = append(pickdata, v[1:])
					} else {
						pickdata = append(pickdata, v)
					}
				}
			}
			csvReader = csv.NewReader(strings.NewReader(strings.Join(pickdata, "\n")))
		}
	default:
		if len(csvArrayContent) > 9 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:len(csvArrayContent)-7], "\n")))
		}
	}
	if csvReader != nil {
		returnData, err := csvReader.ReadAll()
		switch category {
		default:
			if err == nil {
				l.categoryRawData[category] = returnData
				l.formatData(category)
			}
		case "MS":
		}
		return returnData, err
	}
	return nil, errorNotEnoughData
}

// GetCategoryList 取得分類的股票代碼與名稱列表
func (l Lists) GetCategoryList(category string) []StockInfo {
	if _, ok := l.categoryNoList[category]; !ok {
		l.Get(category)
	}
	return l.categoryNoList[category]
}

// FmtListData 格式化個股的資料資訊
type FmtListData struct {
	No             string
	Name           string
	Volume         uint64  //成交股數
	TotalPrice     uint64  //成交金額
	Open           float64 //開盤價
	High           float64 //最高價
	Low            float64 //最低價
	Price          float64 //收盤價
	Range          float64 //漲跌價差
	Totalsale      uint64  //成交筆數
	LastBuyPrice   float64 //最後揭示買價
	LastBuyVolume  uint64  //最後揭示買量
	LastSellPrice  float64 //最後揭示賣價
	LastSellVolume uint64  //最後揭示賣量
	PERatio        float64 //本益比
	IssuedShares   uint64  //發行股數
}

func (l *Lists) formatData(categoryNo string) {
	if _, ok := l.categoryNoList[categoryNo]; !ok {
		l.categoryNoList[categoryNo] = make([]StockInfo, len(l.categoryRawData[categoryNo]))
	}

	for i, v := range l.categoryRawData[categoryNo] {
		var data FmtListData
		data.No = strings.Trim(v[0], " ")
		data.Name = strings.Trim(v[1], " ")
		data.Volume, _ = strconv.ParseUint(v[2], 10, 32)
		data.Totalsale, _ = strconv.ParseUint(v[3], 10, 32)
		data.TotalPrice, _ = strconv.ParseUint(v[4], 10, 32)
		data.Open, _ = strconv.ParseFloat(v[5], 64)
		data.High, _ = strconv.ParseFloat(v[6], 64)
		data.Low, _ = strconv.ParseFloat(v[7], 64)
		data.Price, _ = strconv.ParseFloat(v[8], 64)
		data.Range, _ = strconv.ParseFloat(fmt.Sprintf("%s%s", v[9], v[10]), 64)
		data.LastBuyPrice, _ = strconv.ParseFloat(v[11], 64)
		data.LastBuyVolume, _ = strconv.ParseUint(v[12], 10, 32)
		data.LastSellPrice, _ = strconv.ParseFloat(v[13], 64)
		data.LastSellVolume, _ = strconv.ParseUint(v[14], 10, 32)
		data.PERatio, _ = strconv.ParseFloat(v[15], 64)

		l.FmtData[data.No] = data
		l.categoryNoList[categoryNo][i] = StockInfo{No: data.No, Name: data.Name}
	}
}

// OTCLists is to get OTC list.
type OTCLists struct {
	Date            time.Time
	FmtData         map[string]FmtListData
	categoryRawData map[string][][]string
	categoryNoList  map[string][]StockInfo
}

// NewOTCLists new a Lists.
func NewOTCLists(date time.Time) *OTCLists {
	return &OTCLists{
		Date:            date,
		FmtData:         make(map[string]FmtListData),
		categoryRawData: make(map[string][][]string),
		categoryNoList:  make(map[string][]StockInfo),
	}
}

// Get is to get OTC csv data.
func (o *OTCLists) Get(category string) ([][]string, error) {
	var (
		csvArrayContent []string
		csvReader       *csv.Reader
		data            []byte
		err             error
		rawData         [][]string
		url             string
	)

	url = fmt.Sprintf("%s%s", utils.OTCHOST, fmt.Sprintf(utils.OTCLISTCSV, fmt.Sprintf("%d/%02d/%02d", o.Date.Year()-1911, o.Date.Month(), o.Date.Day()), category))

	if data, err = hCache.Get(url, false); err == nil {
		csvArrayContent = strings.Split(string(data), "\n")
		//log.Println(csvArrayContent)
		//for i, v := range csvArrayContent {
		//	log.Println(i, v)
		//}
		if len(csvArrayContent) > 5 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:len(csvArrayContent)-1], "\n")))
			if rawData, err = csvReader.ReadAll(); err == nil {
				o.categoryRawData[category] = rawData
				o.formatData(category)
				return rawData, nil
			}
		}
		//log.Println(csvReader.ReadAll())
	}
	return nil, err
}

// GetCategoryList 取得分類的股票代碼與名稱列表
func (o OTCLists) GetCategoryList(category string) []StockInfo {
	if _, ok := o.categoryNoList[category]; !ok {
		o.Get(category)
	}
	return o.categoryNoList[category]
}

func (o *OTCLists) formatData(categoryNo string) {
	if _, ok := o.categoryNoList[categoryNo]; !ok {
		o.categoryNoList[categoryNo] = make([]StockInfo, len(o.categoryRawData[categoryNo]))
	}

	for i, v := range o.categoryRawData[categoryNo] {
		var data FmtListData
		data.No = strings.Trim(v[0], " ")
		data.Name = strings.Trim(v[1], " ")
		data.Volume, _ = strconv.ParseUint(strings.Replace(v[7], ",", "", -1), 10, 64)
		data.Totalsale, _ = strconv.ParseUint(strings.Replace(v[9], ",", "", -1), 10, 64)
		data.TotalPrice, _ = strconv.ParseUint(strings.Replace(v[8], ",", "", -1), 10, 64)
		data.Open, _ = strconv.ParseFloat(v[4], 64)
		data.High, _ = strconv.ParseFloat(v[5], 64)
		data.Low, _ = strconv.ParseFloat(v[6], 64)
		data.Price, _ = strconv.ParseFloat(v[2], 64)
		data.Range, _ = strconv.ParseFloat(strings.Replace(v[3], " ", "", -1), 64)
		data.LastBuyPrice, _ = strconv.ParseFloat(v[10], 64)
		data.LastSellPrice, _ = strconv.ParseFloat(v[11], 64)
		data.IssuedShares, _ = strconv.ParseUint(strings.Replace(v[12], ",", "", -1), 10, 64)

		o.FmtData[data.No] = data
		o.categoryNoList[categoryNo][i] = StockInfo{No: data.No, Name: data.Name}
	}
	//log.Println("FormatData:", o.FmtData)
	//log.Println("NoList:", o.categoryNoList)
}
<commit_msg>Fixed twselist raw data format.<commit_after>package twse

import (
	"encoding/csv"
	"errors"
	"fmt"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/toomore/gogrs/utils"
)

// TWSECLASS is a class list of TWSE.
var TWSECLASS = map[string]string{
	"MS":         "大盤統計資訊",
	"0049":       "封閉式基金",
	"0099P":      "ETF",
	"01":         "水泥工業",
	"019919T":    "受益證券",
	"02":         "食品工業",
	"03":         "塑膠工業",
	"04":         "紡織纖維",
	"05":         "電機機械",
	"06":         "電器電纜",
	"07":         "化學生技醫療",
	"08":         "玻璃陶瓷",
	"09":         "造紙工業",
	"0999":       "認購權證", //(不含牛證)
	"0999B":      "熊證",
	"0999C":      "牛證",
	"0999G9":     "認股權憑證",
	"0999GA":     "附認股權特別股",
	"0999GD":     "附認股權公司債",
	"0999P":      "認售權證", //(不含熊證)
	"0999X":      "可展延牛證",
	"0999Y":      "可展延熊證",
	"10":         "鋼鐵工業",
	"11":         "橡膠工業",
	"12":         "汽車工業",
	"13":         "電子工業",
	"14":         "建材營造",
	"15":         "航運業",
	"16":         "觀光事業",
	"17":         "金融保險",
	"18":         "貿易百貨",
	"19":         "綜合",
	"20":         "其他",
	"21":         "化學工業",
	"22":         "生技醫療業",
	"23":         "油電燃氣業",
	"24":         "半導體業",
	"25":         "電腦及週邊設備業",
	"26":         "光電業",
	"27":         "通信網路業",
	"28":         "電子零組件業",
	"29":         "電子通路業",
	"30":         "資訊服務業",
	"31":         "其他電子業",
	"9299":       "存託憑證",
	"ALL":        "全部",
	"ALLBUT0999": "全部(不含權證、牛熊證、可展延牛熊證)",
	"CB":         "可轉換公司債",
}

// StockInfo is simple stock info for no, name.
type StockInfo struct {
	No   string
	Name string
}

// Lists is to get TWSE list.
type Lists struct {
	Date            time.Time
	FmtData         map[string]FmtListData
	categoryRawData map[string][][]string
	categoryNoList  map[string][]StockInfo
}

var errorNotSupport = errors.New("Not support.")

// NewLists new a Lists.
func NewLists(t time.Time) *Lists {
	return &Lists{
		Date:            t,
		FmtData:         make(map[string]FmtListData),
		categoryRawData: make(map[string][][]string),
		categoryNoList:  make(map[string][]StockInfo),
	}
}

// Get is to get TWSE csv data.
func (l *Lists) Get(category string) ([][]string, error) {
	if TWSECLASS[category] == "" {
		return nil, errorNotSupport
	}

	year, month, day := l.Date.Date()
	data, err := hCache.PostForm(fmt.Sprintf("%s%s", utils.TWSEHOST, utils.TWSELISTCSV),
		url.Values{"download": {"csv"}, "selectType": {category},
			"qdate": {fmt.Sprintf("%d/%02d/%02d", year-1911, month, day)}})

	if err != nil {
		return nil, fmt.Errorf(errorNetworkFail.Error(), err)
	}

	csvArrayContent := strings.Split(string(data), "\n")

	var csvReader *csv.Reader
	switch category {
	case "MS":
		if len(csvArrayContent) > 6 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:51], "\n")))
		}
	case "ALLBUT0999", "ALL":
		if len(csvArrayContent) > 155 {
			re := regexp.MustCompile("^=?[\"]{1}[0-9A-Z]{4,}")
			var pickdata []string
			for _, v := range csvArrayContent {
				if re.MatchString(v) {
					if v[0] == 61 {
						pickdata = append(pickdata, v[1:])
					} else {
						pickdata = append(pickdata, v)
					}
				}
			}
			csvReader = csv.NewReader(strings.NewReader(strings.Join(pickdata, "\n")))
		}
	default:
		if len(csvArrayContent) > 9 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:len(csvArrayContent)-7], "\n")))
		}
	}
	if csvReader != nil {
		returnData, err := csvReader.ReadAll()
		switch category {
		default:
			if err == nil {
				l.categoryRawData[category] = returnData
				l.formatData(category)
			}
		case "MS":
		}
		return returnData, err
	}
	return nil, errorNotEnoughData
}

// GetCategoryList 取得分類的股票代碼與名稱列表
func (l Lists) GetCategoryList(category string) []StockInfo {
	if _, ok := l.categoryNoList[category]; !ok {
		l.Get(category)
	}
	return l.categoryNoList[category]
}

// FmtListData 格式化個股的資料資訊
type FmtListData struct {
	No             string
	Name           string
	Volume         uint64  //成交股數
	TotalPrice     uint64  //成交金額
	Open           float64 //開盤價
	High           float64 //最高價
	Low            float64 //最低價
	Price          float64 //收盤價
	Range          float64 //漲跌價差
	Totalsale      uint64  //成交筆數
	LastBuyPrice   float64 //最後揭示買價
	LastBuyVolume  uint64  //最後揭示買量
	LastSellPrice  float64 //最後揭示賣價
	LastSellVolume uint64  //最後揭示賣量
	PERatio        float64 //本益比
	IssuedShares   uint64  //發行股數
}

func (l *Lists) formatData(categoryNo string) {
	if _, ok := l.categoryNoList[categoryNo]; !ok {
		l.categoryNoList[categoryNo] = make([]StockInfo, len(l.categoryRawData[categoryNo]))
	}

	for i, v := range l.categoryRawData[categoryNo] {
		var data FmtListData
		data.No = strings.Trim(v[0], " ")
		data.Name = strings.Trim(v[1], " ")
		data.Volume, _ = strconv.ParseUint(strings.Replace(v[2], ",", "", -1), 10, 64)
		data.Totalsale, _ = strconv.ParseUint(v[3], 10, 32)
		data.TotalPrice, _ = strconv.ParseUint(strings.Replace(v[4], ",", "", -1), 10, 64)
		data.Open, _ = strconv.ParseFloat(v[5], 64)
		data.High, _ = strconv.ParseFloat(v[6], 64)
		data.Low, _ = strconv.ParseFloat(v[7], 64)
		data.Price, _ = strconv.ParseFloat(v[8], 64)
		data.Range, _ = strconv.ParseFloat(fmt.Sprintf("%s%s", v[9], v[10]), 64)
		data.LastBuyPrice, _ = strconv.ParseFloat(v[11], 64)
		data.LastBuyVolume, _ = strconv.ParseUint(v[12], 10, 32)
		data.LastSellPrice, _ = strconv.ParseFloat(v[13], 64)
		data.LastSellVolume, _ = strconv.ParseUint(v[14], 10, 32)
		data.PERatio, _ = strconv.ParseFloat(v[15], 64)

		l.FmtData[data.No] = data
		l.categoryNoList[categoryNo][i] = StockInfo{No: data.No, Name: data.Name}
	}
}

// OTCLists is to get OTC list.
type OTCLists struct {
	Date            time.Time
	FmtData         map[string]FmtListData
	categoryRawData map[string][][]string
	categoryNoList  map[string][]StockInfo
}

// NewOTCLists new a Lists.
func NewOTCLists(date time.Time) *OTCLists {
	return &OTCLists{
		Date:            date,
		FmtData:         make(map[string]FmtListData),
		categoryRawData: make(map[string][][]string),
		categoryNoList:  make(map[string][]StockInfo),
	}
}

// Get is to get OTC csv data.
func (o *OTCLists) Get(category string) ([][]string, error) {
	var (
		csvArrayContent []string
		csvReader       *csv.Reader
		data            []byte
		err             error
		rawData         [][]string
		url             string
	)

	url = fmt.Sprintf("%s%s", utils.OTCHOST, fmt.Sprintf(utils.OTCLISTCSV, fmt.Sprintf("%d/%02d/%02d", o.Date.Year()-1911, o.Date.Month(), o.Date.Day()), category))

	if data, err = hCache.Get(url, false); err == nil {
		csvArrayContent = strings.Split(string(data), "\n")
		//log.Println(csvArrayContent)
		//for i, v := range csvArrayContent {
		//	log.Println(i, v)
		//}
		if len(csvArrayContent) > 5 {
			csvReader = csv.NewReader(strings.NewReader(strings.Join(csvArrayContent[4:len(csvArrayContent)-1], "\n")))
			if rawData, err = csvReader.ReadAll(); err == nil {
				o.categoryRawData[category] = rawData
				o.formatData(category)
				return rawData, nil
			}
		}
		//log.Println(csvReader.ReadAll())
	}
	return nil, err
}

// GetCategoryList 取得分類的股票代碼與名稱列表
func (o OTCLists) GetCategoryList(category string) []StockInfo {
	if _, ok := o.categoryNoList[category]; !ok {
		o.Get(category)
	}
	return o.categoryNoList[category]
}

func (o *OTCLists) formatData(categoryNo string) {
	if _, ok := o.categoryNoList[categoryNo]; !ok {
		o.categoryNoList[categoryNo] = make([]StockInfo, len(o.categoryRawData[categoryNo]))
	}

	for i, v := range o.categoryRawData[categoryNo] {
		var data FmtListData
		data.No = strings.Trim(v[0], " ")
		data.Name = strings.Trim(v[1], " ")
		data.Volume, _ = strconv.ParseUint(strings.Replace(v[7], ",", "", -1), 10, 64)
		data.Totalsale, _ = strconv.ParseUint(strings.Replace(v[9], ",", "", -1), 10, 64)
		data.TotalPrice, _ = strconv.ParseUint(strings.Replace(v[8], ",", "", -1), 10, 64)
		data.Open, _ = strconv.ParseFloat(v[4], 64)
		data.High, _ = strconv.ParseFloat(v[5], 64)
		data.Low, _ = strconv.ParseFloat(v[6], 64)
		data.Price, _ = strconv.ParseFloat(v[2], 64)
		data.Range, _ = strconv.ParseFloat(strings.Replace(v[3], " ", "", -1), 64)
		data.LastBuyPrice, _ = strconv.ParseFloat(v[10], 64)
		data.LastSellPrice, _ = strconv.ParseFloat(v[11], 64)
		data.IssuedShares, _ = strconv.ParseUint(strings.Replace(v[12], ",", "", -1), 10, 64)

		o.FmtData[data.No] = data
		o.categoryNoList[categoryNo][i] = StockInfo{No: data.No, Name: data.Name}
	}
	//log.Println("FormatData:", o.FmtData)
	//log.Println("NoList:", o.categoryNoList)
}
<|endoftext|>


<commit_before>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"testing"
)

func TestBasicDecode(t *testing.T) {
	var b bytes.Buffer
	e := NewEncoder(1, &b)

	err := e.EncodeBOS(2, []byte("hello"))
	if err != nil {
		t.Fatal("unexpected EncodeBOS error:", err)
	}

	d := NewDecoder(&b)

	p, err := d.Decode()
	if err != nil {
		t.Fatal("unexpected Decode error:", err)
	}

	if p.Type != BOS {
		t.Fatal("expected BOS, got", p.Type)
	}

	if p.Serial != 1 {
		t.Fatal("expected serial 1, got", p.Serial)
	}

	if p.Granule != 2 {
		t.Fatal("expected granule 2, got", p.Granule)
	}

	expect := []byte{
		'h', 'e', 'l', 'l', 'o',
	}

	if !bytes.Equal(p.Packet, expect) {
		t.Fatalf("bytes != expected:\n%x\n%x", p.Packet, expect)
	}
}

func TestSyncDecode(t *testing.T) {
	var b bytes.Buffer
	b.Write([]byte("junk, junk, and more junk"))

	e := NewEncoder(1, &b)

	err := e.EncodeBOS(2, []byte("hello"))
	if err != nil {
		t.Fatal("unexpected EncodeBOS error:", err)
	}

	d := NewDecoder(&b)

	p, err := d.Decode()
	if err != nil {
		t.Fatal("unexpected Decode error:", err)
	}

	if p.Type != BOS {
		t.Fatal("expected BOS, got", p.Type)
	}

	if p.Serial != 1 {
		t.Fatal("expected serial 1, got", p.Serial)
	}

	if p.Granule != 2 {
		t.Fatal("expected granule 2, got", p.Granule)
	}

	expect := []byte{
		'h', 'e', 'l', 'l', 'o',
	}

	if !bytes.Equal(p.Packet, expect) {
		t.Fatalf("bytes != expected:\n%x\n%x", p.Packet, expect)
	}
}
<commit_msg>Add test for bad CRC<commit_after>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"strings"
	"testing"
)

func TestBasicDecode(t *testing.T) {
	var b bytes.Buffer
	e := NewEncoder(1, &b)

	err := e.EncodeBOS(2, []byte("hello"))
	if err != nil {
		t.Fatal("unexpected EncodeBOS error:", err)
	}

	d := NewDecoder(&b)

	p, err := d.Decode()
	if err != nil {
		t.Fatal("unexpected Decode error:", err)
	}

	if p.Type != BOS {
		t.Fatal("expected BOS, got", p.Type)
	}

	if p.Serial != 1 {
		t.Fatal("expected serial 1, got", p.Serial)
	}

	if p.Granule != 2 {
		t.Fatal("expected granule 2, got", p.Granule)
	}

	expect := []byte{
		'h', 'e', 'l', 'l', 'o',
	}

	if !bytes.Equal(p.Packet, expect) {
		t.Fatalf("bytes != expected:\n%x\n%x", p.Packet, expect)
	}
}

func TestBadDecode(t *testing.T) {
	var b bytes.Buffer
	e := NewEncoder(1, &b)

	err := e.EncodeBOS(2, []byte("hello"))
	if err != nil {
		t.Fatalf("unexpected EncodeBOS error:", err)
	}

	b.Bytes()[22] = 0

	d := NewDecoder(&b)

	_, err = d.Decode()
	if err == nil {
		t.Fatal("unexpected lack of Decode error")
	}
	if bs, ok := err.(ErrBadCrc); !ok {
		t.Fatalf("exected ErrBadCrc, got: %v", err)
	} else if !strings.HasPrefix(bs.Error(), "invalid crc in packet") {
		t.Fatalf("the error message looks wrong: %q", err.Error())
	}
}

func TestSyncDecode(t *testing.T) {
	var b bytes.Buffer
	b.Write([]byte("junk, junk, and more junk"))

	e := NewEncoder(1, &b)

	err := e.EncodeBOS(2, []byte("hello"))
	if err != nil {
		t.Fatal("unexpected EncodeBOS error:", err)
	}

	d := NewDecoder(&b)

	p, err := d.Decode()
	if err != nil {
		t.Fatal("unexpected Decode error:", err)
	}

	if p.Type != BOS {
		t.Fatal("expected BOS, got", p.Type)
	}

	if p.Serial != 1 {
		t.Fatal("expected serial 1, got", p.Serial)
	}

	if p.Granule != 2 {
		t.Fatal("expected granule 2, got", p.Granule)
	}

	expect := []byte{
		'h', 'e', 'l', 'l', 'o',
	}

	if !bytes.Equal(p.Packet, expect) {
		t.Fatalf("bytes != expected:\n%x\n%x", p.Packet, expect)
	}
}
<|endoftext|>


<commit_before>package decor

import (
	"fmt"
	"io"
	"math"
	"time"

	"github.com/VividCortex/ewma"
)

// SpeedFormatter is wrapper for SizeB1024 and SizeB1000 to format value as speed/s.
type SpeedFormatter struct {
	fmt.Formatter
}

func (self *SpeedFormatter) Format(st fmt.State, verb rune) {
	self.Formatter.Format(st, verb)
	io.WriteString(st, "/s")
}

// EwmaSpeed exponential-weighted-moving-average based speed decorator.
// Note that it's necessary to supply bar.Incr* methods with incremental
// work duration as second argument, in order for this decorator to
// work correctly. This decorator is a wrapper of MovingAverageSpeed.
func EwmaSpeed(unit int, format string, age float64, wcc ...WC) Decorator {
	var average MovingAverage
	if age == 0 {
		average = ewma.NewMovingAverage()
	} else {
		average = ewma.NewMovingAverage(age)
	}
	return MovingAverageSpeed(unit, format, average, wcc...)
}

// MovingAverageSpeed decorator relies on MovingAverage implementation
// to calculate its average.
//
//	`unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
//	`format` printf compatible verb for value, like "%f" or "%d"
//
//	`average` MovingAverage implementation
//
//	`wcc` optional WC config
//
// format examples:
//
//	unit=UnitKiB, format="%.1f"  output: "1.0MiB/s"
//	unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
//	unit=UnitKB,  format="%.1f"  output: "1.0MB/s"
//	unit=UnitKB,  format="% .1f" output: "1.0 MB/s"
//
func MovingAverageSpeed(unit int, format string, average MovingAverage, wcc ...WC) Decorator {
	var wc WC
	for _, widthConf := range wcc {
		wc = widthConf
	}
	if format == "" {
		format = "%.0f"
	}
	d := &movingAverageSpeed{
		WC:       wc.Init(),
		average:  average,
		producer: chooseSpeedProducer(unit, format),
	}
	return d
}

type movingAverageSpeed struct {
	WC
	producer func(float64) string
	average  ewma.MovingAverage
	msg      string
}

func (d *movingAverageSpeed) Decor(st *Statistics) string {
	if !st.Completed {
		var speed float64
		if v := math.Round(d.average.Value()); v != 0 {
			speed = 1 / time.Duration(v).Seconds()
		}
		d.msg = d.producer(speed)
	}
	return d.FormatMsg(d.msg)
}

func (d *movingAverageSpeed) NextAmount(n int64, wdd ...time.Duration) {
	var workDuration time.Duration
	for _, wd := range wdd {
		workDuration = wd
	}
	durPerByte := float64(workDuration) / float64(n)
	if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) {
		return
	}
	d.average.Add(durPerByte)
}

// AverageSpeed decorator with dynamic unit measure adjustment. It's
// a wrapper of NewAverageSpeed.
func AverageSpeed(unit int, format string, wcc ...WC) Decorator {
	return NewAverageSpeed(unit, format, time.Now(), wcc...)
}

// NewAverageSpeed decorator with dynamic unit measure adjustment and
// user provided start time.
//
//	`unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
//	`format` printf compatible verb for value, like "%f" or "%d"
//
//	`startTime` start time
//
//	`wcc` optional WC config
//
// format examples:
//
//	unit=UnitKiB, format="%.1f"  output: "1.0MiB/s"
//	unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
//	unit=UnitKB,  format="%.1f"  output: "1.0MB/s"
//	unit=UnitKB,  format="% .1f" output: "1.0 MB/s"
//
func NewAverageSpeed(unit int, format string, startTime time.Time, wcc ...WC) Decorator {
	var wc WC
	for _, widthConf := range wcc {
		wc = widthConf
	}
	if format == "" {
		format = "%.0f"
	}
	d := &averageSpeed{
		WC:        wc.Init(),
		startTime: startTime,
		producer:  chooseSpeedProducer(unit, format),
	}
	return d
}

type averageSpeed struct {
	WC
	startTime time.Time
	producer  func(float64) string
	msg       string
}

func (d *averageSpeed) Decor(st *Statistics) string {
	if !st.Completed {
		speed := float64(st.Current) / time.Since(d.startTime).Seconds()
		d.msg = d.producer(speed)
	}

	return d.FormatMsg(d.msg)
}

func (d *averageSpeed) AverageAdjust(startTime time.Time) {
	d.startTime = startTime
}

func chooseSpeedProducer(unit int, format string) func(float64) string {
	switch unit {
	case UnitKiB:
		return func(speed float64) string {
			return fmt.Sprintf(format, &SpeedFormatter{SizeB1024(math.Round(speed))})
		}
	case UnitKB:
		return func(speed float64) string {
			return fmt.Sprintf(format, &SpeedFormatter{SizeB1000(math.Round(speed))})
		}
	default:
		return func(speed float64) string {
			return fmt.Sprintf(format, speed)
		}
	}
}
<commit_msg>one math.Round less<commit_after>package decor

import (
	"fmt"
	"io"
	"math"
	"time"

	"github.com/VividCortex/ewma"
)

// SpeedFormatter is wrapper for SizeB1024 and SizeB1000 to format value as speed/s.
type SpeedFormatter struct {
	fmt.Formatter
}

func (self *SpeedFormatter) Format(st fmt.State, verb rune) {
	self.Formatter.Format(st, verb)
	io.WriteString(st, "/s")
}

// EwmaSpeed exponential-weighted-moving-average based speed decorator.
// Note that it's necessary to supply bar.Incr* methods with incremental
// work duration as second argument, in order for this decorator to
// work correctly. This decorator is a wrapper of MovingAverageSpeed.
func EwmaSpeed(unit int, format string, age float64, wcc ...WC) Decorator {
	var average MovingAverage
	if age == 0 {
		average = ewma.NewMovingAverage()
	} else {
		average = ewma.NewMovingAverage(age)
	}
	return MovingAverageSpeed(unit, format, average, wcc...)
}

// MovingAverageSpeed decorator relies on MovingAverage implementation
// to calculate its average.
//
//	`unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
//	`format` printf compatible verb for value, like "%f" or "%d"
//
//	`average` MovingAverage implementation
//
//	`wcc` optional WC config
//
// format examples:
//
//	unit=UnitKiB, format="%.1f"  output: "1.0MiB/s"
//	unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
//	unit=UnitKB,  format="%.1f"  output: "1.0MB/s"
//	unit=UnitKB,  format="% .1f" output: "1.0 MB/s"
//
func MovingAverageSpeed(unit int, format string, average MovingAverage, wcc ...WC) Decorator {
	var wc WC
	for _, widthConf := range wcc {
		wc = widthConf
	}
	if format == "" {
		format = "%.0f"
	}
	d := &movingAverageSpeed{
		WC:       wc.Init(),
		average:  average,
		producer: chooseSpeedProducer(unit, format),
	}
	return d
}

type movingAverageSpeed struct {
	WC
	producer func(float64) string
	average  ewma.MovingAverage
	msg      string
}

func (d *movingAverageSpeed) Decor(st *Statistics) string {
	if !st.Completed {
		var speed float64
		if v := d.average.Value(); v < 0 {
			speed = 1 / v
		}
		d.msg = d.producer(speed * 1e9)
	}
	return d.FormatMsg(d.msg)
}

func (d *movingAverageSpeed) NextAmount(n int64, wdd ...time.Duration) {
	var workDuration time.Duration
	for _, wd := range wdd {
		workDuration = wd
	}
	durPerByte := float64(workDuration) / float64(n)
	if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) {
		return
	}
	d.average.Add(durPerByte)
}

// AverageSpeed decorator with dynamic unit measure adjustment. It's
// a wrapper of NewAverageSpeed.
func AverageSpeed(unit int, format string, wcc ...WC) Decorator {
	return NewAverageSpeed(unit, format, time.Now(), wcc...)
}

// NewAverageSpeed decorator with dynamic unit measure adjustment and
// user provided start time.
//
//	`unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
//	`format` printf compatible verb for value, like "%f" or "%d"
//
//	`startTime` start time
//
//	`wcc` optional WC config
//
// format examples:
//
//	unit=UnitKiB, format="%.1f"  output: "1.0MiB/s"
//	unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
//	unit=UnitKB,  format="%.1f"  output: "1.0MB/s"
//	unit=UnitKB,  format="% .1f" output: "1.0 MB/s"
//
func NewAverageSpeed(unit int, format string, startTime time.Time, wcc ...WC) Decorator {
	var wc WC
	for _, widthConf := range wcc {
		wc = widthConf
	}
	if format == "" {
		format = "%.0f"
	}
	d := &averageSpeed{
		WC:        wc.Init(),
		startTime: startTime,
		producer:  chooseSpeedProducer(unit, format),
	}
	return d
}

type averageSpeed struct {
	WC
	startTime time.Time
	producer  func(float64) string
	msg       string
}

func (d *averageSpeed) Decor(st *Statistics) string {
	if !st.Completed {
		speed := float64(st.Current) / float64(time.Since(d.startTime))
		d.msg = d.producer(speed * 1e9)
	}

	return d.FormatMsg(d.msg)
}

func (d *averageSpeed) AverageAdjust(startTime time.Time) {
	d.startTime = startTime
}

func chooseSpeedProducer(unit int, format string) func(float64) string {
	switch unit {
	case UnitKiB:
		return func(speed float64) string {
			return fmt.Sprintf(format, &SpeedFormatter{SizeB1024(math.Round(speed))})
		}
	case UnitKB:
		return func(speed float64) string {
			return fmt.Sprintf(format, &SpeedFormatter{SizeB1000(math.Round(speed))})
		}
	default:
		return func(speed float64) string {
			return fmt.Sprintf(format, speed)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>bcbatchfossilizer: Use a better logger (#20) * Add vendor dependencies<commit_after><|endoftext|>


<commit_before>package tmux

import (
	"testing"
)

func TestNodeAddType(t *testing.T) {

	pathTestCases := []struct {
		title   string
		path    string
		compare func(edge *Edge) bool
	}{
		{
			title:   "Static path",
			path:    "/echo",
			compare: func(edge *Edge) bool { return staticNode == edge.typ },
		},
		{
			title:   "Static path",
			path:    "/overview/",
			compare: func(edge *Edge) bool { return paramNode != edge.typ },
		},
		{
			title:   "Param path",
			path:    "/:string/:number/dummy",
			compare: func(edge *Edge) bool { return paramNode == edge.typ },
		},
		{
			title:   "Param path",
			path:    "/dummy/:number/dummy",
			compare: func(edge *Edge) bool { return staticNode != edge.typ },
		},
	}

	parentNode := &Node{}
	for _, pathTestCase := range pathTestCases {
		t.Run(pathTestCase.title, func(t *testing.T) {

			edge := &Edge{
				node: &Node{
					prefix: pathTestCase.path,
				},
			}

			parentNode.AddType(edge)

			if !pathTestCase.compare(edge) {
				t.Errorf("Unexpected type of node (type: %v)", edge.typ)
			}
		})
	}
}
<commit_msg>Added test cases for replace edge<commit_after>package tmux

import "testing"

func TestReplaceEdge(t *testing.T) {

	parentNode := &Node{
		edges: [edgeTypes]Edges{},
	}

	edges := []*Edge{
		&Edge{
			label: "a"[0],
			typ:   paramNode,
			node: &Node{
				prefix: "artcile/:number",
			},
		},
		&Edge{
			label: ":"[0],
			typ:   paramNode,
			node: &Node{
				prefix: ":number",
			},
		},
		&Edge{
			label: "u"[0],
			typ:   staticNode,
			node: &Node{
				prefix: "user",
			},
		},
	}

	for _, edge := range edges {
		parentNode.edges[edge.typ] = append(parentNode.edges[edge.typ], edge)
	}

	newEdge := &Edge{
		label: "a"[0],
		typ:   staticNode,
		node: &Node{
			prefix: "article/",
		},
	}

	if err := parentNode.ReplaceEdge(newEdge); err != nil {
		t.Errorf("Unexpected error while replaceing (%s)", err.Error())
	}
}

func TestReplaceEdgeFail(t *testing.T) {

	parentNode := &Node{
		edges: [edgeTypes]Edges{},
	}

	newEdge := &Edge{
		label: "a"[0],
		typ:   staticNode,
		node: &Node{
			prefix: "article/",
		},
	}

	if err := parentNode.ReplaceEdge(newEdge); err == nil {
		t.Errorf("Unexpected success while replaceing")
	}
}

func TestNodeAddType(t *testing.T) {

	pathTestCases := []struct {
		title   string
		path    string
		compare func(edge *Edge) bool
	}{
		{
			title:   "Static path",
			path:    "/echo",
			compare: func(edge *Edge) bool { return staticNode == edge.typ },
		},
		{
			title:   "Static path",
			path:    "/overview/",
			compare: func(edge *Edge) bool { return paramNode != edge.typ },
		},
		{
			title:   "Param path",
			path:    "/:string/:number/dummy",
			compare: func(edge *Edge) bool { return paramNode == edge.typ },
		},
		{
			title:   "Param path",
			path:    "/dummy/:number/dummy",
			compare: func(edge *Edge) bool { return staticNode != edge.typ },
		},
	}

	parentNode := &Node{}
	for _, pathTestCase := range pathTestCases {
		t.Run(pathTestCase.title, func(t *testing.T) {

			edge := &Edge{
				node: &Node{
					prefix: pathTestCase.path,
				},
			}

			parentNode.AddType(edge)

			if !pathTestCase.compare(edge) {
				t.Errorf("Unexpected type of node (type: %v)", edge.typ)
			}
		})
	}
}
<|endoftext|>


<commit_before>package pretty

import (
	"sort"
)

// Options is Pretty options
type Options struct {
	// Width is an max column width for single line arrays
	// Default is 80
	Width int
	// Prefix is a prefix for all lines
	// Default is an empty string
	Prefix string
	// Indent is the nested indentation
	// Default is two spaces
	Indent string
	// SortKeys will sort the keys alphabetically
	// Default is false
	SortKeys bool
}

// DefaultOptions is the default options for pretty formats.
var DefaultOptions = &Options{Width: 80, Prefix: "", Indent: "  ", SortKeys: false}

// Pretty converts the input json into a more human readable format where each
// element is on it's own line with clear indentation.
func Pretty(json []byte) []byte { return PrettyOptions(json, nil) }

// PrettyOptions is like Pretty but with customized options.
func PrettyOptions(json []byte, opts *Options) []byte {
	if opts == nil {
		opts = DefaultOptions
	}
	buf := make([]byte, 0, len(json))
	if len(opts.Prefix) != 0 {
		buf = append(buf, opts.Prefix...)
	}
	buf, _, _, _ = appendPrettyAny(buf, json, 0, true,
		opts.Width, opts.Prefix, opts.Indent, opts.SortKeys,
		0, 0, -1)
	return buf
}

// Ugly removes insignificant space characters from the input json byte slice
// and returns the compacted result.
func Ugly(json []byte) []byte {
	buf := make([]byte, 0, len(json))
	return ugly(buf, json)
}

// UglyInPlace removes insignificant space characters from the input json
// byte slice and returns the compacted result. This method reuses the
// input json buffer to avoid allocations. Do not use the original bytes
// slice upon return.
func UglyInPlace(json []byte) []byte { return ugly(json, json) }

func ugly(dst, src []byte) []byte {
	dst = dst[:0]
	for i := 0; i < len(src); i++ {
		if src[i] > ' ' {
			dst = append(dst, src[i])
			if src[i] == '"' {
				for i = i + 1; i < len(src); i++ {
					dst = append(dst, src[i])
					if src[i] == '"' {
						j := i - 1
						for ; ; j-- {
							if src[j] != '\\' {
								break
							}
						}
						if (j-i)%2 != 0 {
							break
						}
					}
				}
			}
		}
	}
	return dst
}

func appendPrettyAny(buf, json []byte, i int, pretty bool, width int, prefix, indent string, sortkeys bool, tabs, nl, max int) ([]byte, int, int, bool) {
	for ; i < len(json); i++ {
		if json[i] <= ' ' {
			continue
		}
		if json[i] == '"' {
			return appendPrettyString(buf, json, i, nl)
		}
		if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
			return appendPrettyNumber(buf, json, i, nl)
		}
		if json[i] == '{' {
			return appendPrettyObject(buf, json, i, '{', '}', pretty, width, prefix, indent, sortkeys, tabs, nl, max)
		}
		if json[i] == '[' {
			return appendPrettyObject(buf, json, i, '[', ']', pretty, width, prefix, indent, sortkeys, tabs, nl, max)
		}
		switch json[i] {
		case 't':
			return append(buf, 't', 'r', 'u', 'e'), i + 4, nl, true
		case 'f':
			return append(buf, 'f', 'a', 'l', 's', 'e'), i + 5, nl, true
		case 'n':
			return append(buf, 'n', 'u', 'l', 'l'), i + 4, nl, true
		}
	}
	return buf, i, nl, true
}

type pair struct {
	kstart, kend int
	vstart, vend int
}

type byKey struct {
	sorted bool
	json   []byte
	pairs  []pair
}

func (arr *byKey) Len() int {
	return len(arr.pairs)
}
func (arr *byKey) Less(i, j int) bool {
	key1 := arr.json[arr.pairs[i].kstart+1 : arr.pairs[i].kend-1]
	key2 := arr.json[arr.pairs[j].kstart+1 : arr.pairs[j].kend-1]
	return string(key1) < string(key2)
}
func (arr *byKey) Swap(i, j int) {
	arr.pairs[i], arr.pairs[j] = arr.pairs[j], arr.pairs[i]
	arr.sorted = true
}

func appendPrettyObject(buf, json []byte, i int, open, close byte, pretty bool, width int, prefix, indent string, sortkeys bool, tabs, nl, max int) ([]byte, int, int, bool) {
	var ok bool
	if width > 0 {
		if pretty && open == '[' && max == -1 {
			// here we try to create a single line array
			max := width - (len(buf) - nl)
			if max > 3 {
				s1, s2 := len(buf), i
				buf, i, _, ok = appendPrettyObject(buf, json, i, '[', ']', false, width, prefix, "", sortkeys, 0, 0, max)
				if ok && len(buf)-s1 <= max {
					return buf, i, nl, true
				}
				buf = buf[:s1]
				i = s2
			}
		} else if max != -1 && open == '{' {
			return buf, i, nl, false
		}
	}
	buf = append(buf, open)
	i++
	var pairs []pair
	if open == '{' && sortkeys {
		pairs = make([]pair, 0, 8)
	}
	var n int
	for ; i < len(json); i++ {
		if json[i] <= ' ' {
			continue
		}
		if json[i] == close {
			if pretty {
				if open == '{' && sortkeys {
					buf = sortPairs(json, buf, pairs)
				}
				if n > 0 {
					nl = len(buf)
					buf = append(buf, '\n')
				}
				if buf[len(buf)-1] != open {
					buf = appendTabs(buf, prefix, indent, tabs)
				}
			}
			buf = append(buf, close)
			return buf, i + 1, nl, open != '{'
		}
		if open == '[' || json[i] == '"' {
			if n > 0 {
				buf = append(buf, ',')
				if width != -1 {
					buf = append(buf, ' ')
				}
			}
			var p pair
			if pretty {
				nl = len(buf)
				buf = append(buf, '\n')
				if open == '{' && sortkeys {
					p.kstart = i
					p.vstart = len(buf)
				}
				buf = appendTabs(buf, prefix, indent, tabs+1)
			}
			if open == '{' {
				buf, i, nl, _ = appendPrettyString(buf, json, i, nl)
				if sortkeys {
					p.kend = i
				}
				buf = append(buf, ':')
				if pretty {
					buf = append(buf, ' ')
				}
			}
			buf, i, nl, ok = appendPrettyAny(buf, json, i, pretty, width, prefix, indent, sortkeys, tabs+1, nl, max)
			if max != -1 && !ok {
				return buf, i, nl, false
			}
			if pretty && open == '{' && sortkeys {
				p.vend = len(buf)
				if p.kstart > p.kend || p.vstart > p.vend {
					// bad data. disable sorting
					sortkeys = false
				} else {
					pairs = append(pairs, p)
				}
			}
			i--
			n++
		}
	}
	return buf, i, nl, open != '{'
}
func sortPairs(json, buf []byte, pairs []pair) []byte {
	if len(pairs) == 0 {
		return buf
	}
	vstart := pairs[0].vstart
	vend := pairs[len(pairs)-1].vend
	arr := byKey{false, json, pairs}
	sort.Sort(&arr)
	if !arr.sorted {
		return buf
	}
	nbuf := make([]byte, 0, vend-vstart)
	for i, p := range pairs {
		nbuf = append(nbuf, buf[p.vstart:p.vend]...)
		if i < len(pairs)-1 {
			nbuf = append(nbuf, ',')
			nbuf = append(nbuf, '\n')
		}
	}
	return append(buf[:vstart], nbuf...)
}

func appendPrettyString(buf, json []byte, i, nl int) ([]byte, int, int, bool) {
	s := i
	i++
	for ; i < len(json); i++ {
		if json[i] == '"' {
			var sc int
			for j := i - 1; j > s; j-- {
				if json[j] == '\\' {
					sc++
				} else {
					break
				}
			}
			if sc%2 == 1 {
				continue
			}
			i++
			break
		}
	}
	return append(buf, json[s:i]...), i, nl, true
}

func appendPrettyNumber(buf, json []byte, i, nl int) ([]byte, int, int, bool) {
	s := i
	i++
	for ; i < len(json); i++ {
		if json[i] <= ' ' || json[i] == ',' || json[i] == ':' || json[i] == ']' || json[i] == '}' {
			break
		}
	}
	return append(buf, json[s:i]...), i, nl, true
}

func appendTabs(buf []byte, prefix, indent string, tabs int) []byte {
	if len(prefix) != 0 {
		buf = append(buf, prefix...)
	}
	if len(indent) == 2 && indent[0] == ' ' && indent[1] == ' ' {
		for i := 0; i < tabs; i++ {
			buf = append(buf, ' ', ' ')
		}
	} else {
		for i := 0; i < tabs; i++ {
			buf = append(buf, indent...)
		}
	}
	return buf
}
<commit_msg>newline at end<commit_after>package pretty

import (
	"sort"
)

// Options is Pretty options
type Options struct {
	// Width is an max column width for single line arrays
	// Default is 80
	Width int
	// Prefix is a prefix for all lines
	// Default is an empty string
	Prefix string
	// Indent is the nested indentation
	// Default is two spaces
	Indent string
	// SortKeys will sort the keys alphabetically
	// Default is false
	SortKeys bool
}

// DefaultOptions is the default options for pretty formats.
var DefaultOptions = &Options{Width: 80, Prefix: "", Indent: "  ", SortKeys: false}

// Pretty converts the input json into a more human readable format where each
// element is on it's own line with clear indentation.
func Pretty(json []byte) []byte { return PrettyOptions(json, nil) }

// PrettyOptions is like Pretty but with customized options.
func PrettyOptions(json []byte, opts *Options) []byte {
	if opts == nil {
		opts = DefaultOptions
	}
	buf := make([]byte, 0, len(json))
	if len(opts.Prefix) != 0 {
		buf = append(buf, opts.Prefix...)
	}
	buf, _, _, _ = appendPrettyAny(buf, json, 0, true,
		opts.Width, opts.Prefix, opts.Indent, opts.SortKeys,
		0, 0, -1)
	buf = append(buf, '\n')
	return buf
}

// Ugly removes insignificant space characters from the input json byte slice
// and returns the compacted result.
func Ugly(json []byte) []byte {
	buf := make([]byte, 0, len(json))
	return ugly(buf, json)
}

// UglyInPlace removes insignificant space characters from the input json
// byte slice and returns the compacted result. This method reuses the
// input json buffer to avoid allocations. Do not use the original bytes
// slice upon return.
func UglyInPlace(json []byte) []byte { return ugly(json, json) }

func ugly(dst, src []byte) []byte {
	dst = dst[:0]
	for i := 0; i < len(src); i++ {
		if src[i] > ' ' {
			dst = append(dst, src[i])
			if src[i] == '"' {
				for i = i + 1; i < len(src); i++ {
					dst = append(dst, src[i])
					if src[i] == '"' {
						j := i - 1
						for ; ; j-- {
							if src[j] != '\\' {
								break
							}
						}
						if (j-i)%2 != 0 {
							break
						}
					}
				}
			}
		}
	}
	return dst
}

func appendPrettyAny(buf, json []byte, i int, pretty bool, width int, prefix, indent string, sortkeys bool, tabs, nl, max int) ([]byte, int, int, bool) {
	for ; i < len(json); i++ {
		if json[i] <= ' ' {
			continue
		}
		if json[i] == '"' {
			return appendPrettyString(buf, json, i, nl)
		}
		if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
			return appendPrettyNumber(buf, json, i, nl)
		}
		if json[i] == '{' {
			return appendPrettyObject(buf, json, i, '{', '}', pretty, width, prefix, indent, sortkeys, tabs, nl, max)
		}
		if json[i] == '[' {
			return appendPrettyObject(buf, json, i, '[', ']', pretty, width, prefix, indent, sortkeys, tabs, nl, max)
		}
		switch json[i] {
		case 't':
			return append(buf, 't', 'r', 'u', 'e'), i + 4, nl, true
		case 'f':
			return append(buf, 'f', 'a', 'l', 's', 'e'), i + 5, nl, true
		case 'n':
			return append(buf, 'n', 'u', 'l', 'l'), i + 4, nl, true
		}
	}
	return buf, i, nl, true
}

type pair struct {
	kstart, kend int
	vstart, vend int
}

type byKey struct {
	sorted bool
	json   []byte
	pairs  []pair
}

func (arr *byKey) Len() int {
	return len(arr.pairs)
}
func (arr *byKey) Less(i, j int) bool {
	key1 := arr.json[arr.pairs[i].kstart+1 : arr.pairs[i].kend-1]
	key2 := arr.json[arr.pairs[j].kstart+1 : arr.pairs[j].kend-1]
	return string(key1) < string(key2)
}
func (arr *byKey) Swap(i, j int) {
	arr.pairs[i], arr.pairs[j] = arr.pairs[j], arr.pairs[i]
	arr.sorted = true
}

func appendPrettyObject(buf, json []byte, i int, open, close byte, pretty bool, width int, prefix, indent string, sortkeys bool, tabs, nl, max int) ([]byte, int, int, bool) {
	var ok bool
	if width > 0 {
		if pretty && open == '[' && max == -1 {
			// here we try to create a single line array
			max := width - (len(buf) - nl)
			if max > 3 {
				s1, s2 := len(buf), i
				buf, i, _, ok = appendPrettyObject(buf, json, i, '[', ']', false, width, prefix, "", sortkeys, 0, 0, max)
				if ok && len(buf)-s1 <= max {
					return buf, i, nl, true
				}
				buf = buf[:s1]
				i = s2
			}
		} else if max != -1 && open == '{' {
			return buf, i, nl, false
		}
	}
	buf = append(buf, open)
	i++
	var pairs []pair
	if open == '{' && sortkeys {
		pairs = make([]pair, 0, 8)
	}
	var n int
	for ; i < len(json); i++ {
		if json[i] <= ' ' {
			continue
		}
		if json[i] == close {
			if pretty {
				if open == '{' && sortkeys {
					buf = sortPairs(json, buf, pairs)
				}
				if n > 0 {
					nl = len(buf)
					buf = append(buf, '\n')
				}
				if buf[len(buf)-1] != open {
					buf = appendTabs(buf, prefix, indent, tabs)
				}
			}
			buf = append(buf, close)
			return buf, i + 1, nl, open != '{'
		}
		if open == '[' || json[i] == '"' {
			if n > 0 {
				buf = append(buf, ',')
				if width != -1 {
					buf = append(buf, ' ')
				}
			}
			var p pair
			if pretty {
				nl = len(buf)
				buf = append(buf, '\n')
				if open == '{' && sortkeys {
					p.kstart = i
					p.vstart = len(buf)
				}
				buf = appendTabs(buf, prefix, indent, tabs+1)
			}
			if open == '{' {
				buf, i, nl, _ = appendPrettyString(buf, json, i, nl)
				if sortkeys {
					p.kend = i
				}
				buf = append(buf, ':')
				if pretty {
					buf = append(buf, ' ')
				}
			}
			buf, i, nl, ok = appendPrettyAny(buf, json, i, pretty, width, prefix, indent, sortkeys, tabs+1, nl, max)
			if max != -1 && !ok {
				return buf, i, nl, false
			}
			if pretty && open == '{' && sortkeys {
				p.vend = len(buf)
				if p.kstart > p.kend || p.vstart > p.vend {
					// bad data. disable sorting
					sortkeys = false
				} else {
					pairs = append(pairs, p)
				}
			}
			i--
			n++
		}
	}
	return buf, i, nl, open != '{'
}
func sortPairs(json, buf []byte, pairs []pair) []byte {
	if len(pairs) == 0 {
		return buf
	}
	vstart := pairs[0].vstart
	vend := pairs[len(pairs)-1].vend
	arr := byKey{false, json, pairs}
	sort.Sort(&arr)
	if !arr.sorted {
		return buf
	}
	nbuf := make([]byte, 0, vend-vstart)
	for i, p := range pairs {
		nbuf = append(nbuf, buf[p.vstart:p.vend]...)
		if i < len(pairs)-1 {
			nbuf = append(nbuf, ',')
			nbuf = append(nbuf, '\n')
		}
	}
	return append(buf[:vstart], nbuf...)
}

func appendPrettyString(buf, json []byte, i, nl int) ([]byte, int, int, bool) {
	s := i
	i++
	for ; i < len(json); i++ {
		if json[i] == '"' {
			var sc int
			for j := i - 1; j > s; j-- {
				if json[j] == '\\' {
					sc++
				} else {
					break
				}
			}
			if sc%2 == 1 {
				continue
			}
			i++
			break
		}
	}
	return append(buf, json[s:i]...), i, nl, true
}

func appendPrettyNumber(buf, json []byte, i, nl int) ([]byte, int, int, bool) {
	s := i
	i++
	for ; i < len(json); i++ {
		if json[i] <= ' ' || json[i] == ',' || json[i] == ':' || json[i] == ']' || json[i] == '}' {
			break
		}
	}
	return append(buf, json[s:i]...), i, nl, true
}

func appendTabs(buf []byte, prefix, indent string, tabs int) []byte {
	if len(prefix) != 0 {
		buf = append(buf, prefix...)
	}
	if len(indent) == 2 && indent[0] == ' ' && indent[1] == ' ' {
		for i := 0; i < tabs; i++ {
			buf = append(buf, ' ', ' ')
		}
	} else {
		for i := 0; i < tabs; i++ {
			buf = append(buf, indent...)
		}
	}
	return buf
}
<|endoftext|>


<commit_before>package shared

import (
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/sneakybeaky/aws-volumes/shared/log"
)

type AllocatedVolume struct {
	VolumeId   string
	DeviceName string
	InstanceId string
	svc        ec2iface.EC2API
}

// NewAllocatedVolume returns a new instance of AllocatedVolume
func NewAllocatedVolume(volumeId string, deviceName string, instanceId string, svc ec2iface.EC2API) *AllocatedVolume {

	return &AllocatedVolume{VolumeId: volumeId, DeviceName: deviceName, InstanceId: instanceId, svc: svc}
}

func (volume AllocatedVolume) String() string {
	return fmt.Sprintf("AllocatedVolume{ VolumeId : %s, DeviceName : %s, InstanceId : %s}", volume.VolumeId, volume.DeviceName, volume.InstanceId)
}

// Attach attempts to attach the volume
func (volume AllocatedVolume) Attach() error {

	log.Info.Printf("Attaching Volume (%s) at (%s)\n", volume.VolumeId, volume.DeviceName)

	if err := volume.waitUntilAvailable(); err != nil {
		return fmt.Errorf("Error waiting for Volume (%s) to become available, error: %s",
			volume.VolumeId, err)
	}

	opts := &ec2.AttachVolumeInput{
		Device:     aws.String(volume.DeviceName),
		InstanceId: aws.String(volume.InstanceId),
		VolumeId:   aws.String(volume.VolumeId),
	}

	if _, err := volume.svc.AttachVolume(opts); err != nil {

		return fmt.Errorf("Error attaching volume (%s) to instance (%s), cause: \"%s\"",
			volume.VolumeId, volume.InstanceId, err.Error())

	} else {

		err := volume.waitUntilAttached()

		if err != nil {
			return fmt.Errorf("Error waiting for Volume (%s) to attach at (%s), error: %s",
				volume.VolumeId, volume.DeviceName, err)
		}

		log.Info.Printf("Attached Volume (%s) at (%s)\n", volume.VolumeId, volume.DeviceName)

	}

	return nil

}

// Detach attempts to detach the volume
func (volume AllocatedVolume) Detach() error {

	log.Info.Printf("Detaching Volume (%s) from (%s)\n", volume.VolumeId, volume.DeviceName)

	opts := &ec2.DetachVolumeInput{
		Device:     aws.String(volume.DeviceName),
		InstanceId: aws.String(volume.InstanceId),
		VolumeId:   aws.String(volume.VolumeId),
	}

	if _, err := volume.svc.DetachVolume(opts); err != nil {

		return fmt.Errorf("Error Detaching volume (%s) to instance (%s), cause : \"%s\"",
			volume.VolumeId, volume.InstanceId, err.Error())

	} else {

		err := volume.waitUntilAvailable()

		if err != nil {
			return fmt.Errorf("Error waiting for Volume (%s) to detach at (%s), cause: %s",
				volume.VolumeId, volume.DeviceName, err.Error())
		} else {
			log.Info.Printf("Detached Volume (%s) from (%s)\n", volume.VolumeId, volume.DeviceName)
		}
	}

	return nil

}

func (volume AllocatedVolume) Info(w io.Writer) error {

	if status, err := volume.svc.DescribeVolumes(volume.describeVolumesInputWhenDetached()); err != nil {

		return fmt.Errorf("Error getting volume status for Volume (%s), cause: \"%s\"",
			volume.VolumeId, err.Error())

	} else {
		volumeStatus := status.Volumes[0]
		fmt.Fprintf(w, "Volume ID (%s), Device Name (%s), Status is %s\n",
			volume.VolumeId, volume.DeviceName, *volumeStatus.State)
	}

	return nil
}

func (volume AllocatedVolume) describeVolumesInputWhenAttached() *ec2.DescribeVolumesInput {
	return &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volume.VolumeId)},
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name:   aws.String("attachment.instance-id"),
				Values: []*string{aws.String(volume.InstanceId)},
			},
			&ec2.Filter{
				Name:   aws.String("attachment.status"),
				Values: []*string{aws.String(ec2.AttachmentStatusAttached)},
			},
		},
	}
}

func (volume AllocatedVolume) describeVolumesInputWhenDetached() *ec2.DescribeVolumesInput {
	return &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volume.VolumeId)},
	}
}

func (volume AllocatedVolume) waitUntilAvailable() error {

	log.Debug.Printf("Waiting for volume (%s) to become available\n", volume.VolumeId)
	return volume.svc.WaitUntilVolumeAvailable(volume.describeVolumesInputWhenDetached())
}

// waitUntilVolumeAttached uses the Amazon EC2 API operation
// DescribeVolumes to wait for a condition to be met before returning.
// If the condition is not meet within the max attempt window an error will
// be returned.
func (volume AllocatedVolume) waitUntilAttached() error {

	input := volume.describeVolumesInputWhenAttached()

	log.Debug.Printf("Waiting for volume (%s) to be attached at (%s)\n", volume.VolumeId, volume.DeviceName)

	return volume.svc.WaitUntilVolumeInUse(input)

}
<commit_msg>Renamed method to describe volume<commit_after>package shared

import (
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/sneakybeaky/aws-volumes/shared/log"
)

type AllocatedVolume struct {
	VolumeId   string
	DeviceName string
	InstanceId string
	svc        ec2iface.EC2API
}

// NewAllocatedVolume returns a new instance of AllocatedVolume
func NewAllocatedVolume(volumeId string, deviceName string, instanceId string, svc ec2iface.EC2API) *AllocatedVolume {

	return &AllocatedVolume{VolumeId: volumeId, DeviceName: deviceName, InstanceId: instanceId, svc: svc}
}

func (volume AllocatedVolume) String() string {
	return fmt.Sprintf("AllocatedVolume{ VolumeId : %s, DeviceName : %s, InstanceId : %s}", volume.VolumeId, volume.DeviceName, volume.InstanceId)
}

// Attach attempts to attach the volume
func (volume AllocatedVolume) Attach() error {

	log.Info.Printf("Attaching Volume (%s) at (%s)\n", volume.VolumeId, volume.DeviceName)

	if err := volume.waitUntilAvailable(); err != nil {
		return fmt.Errorf("Error waiting for Volume (%s) to become available, error: %s",
			volume.VolumeId, err)
	}

	opts := &ec2.AttachVolumeInput{
		Device:     aws.String(volume.DeviceName),
		InstanceId: aws.String(volume.InstanceId),
		VolumeId:   aws.String(volume.VolumeId),
	}

	if _, err := volume.svc.AttachVolume(opts); err != nil {

		return fmt.Errorf("Error attaching volume (%s) to instance (%s), cause: \"%s\"",
			volume.VolumeId, volume.InstanceId, err.Error())

	} else {

		err := volume.waitUntilAttached()

		if err != nil {
			return fmt.Errorf("Error waiting for Volume (%s) to attach at (%s), error: %s",
				volume.VolumeId, volume.DeviceName, err)
		}

		log.Info.Printf("Attached Volume (%s) at (%s)\n", volume.VolumeId, volume.DeviceName)

	}

	return nil

}

// Detach attempts to detach the volume
func (volume AllocatedVolume) Detach() error {

	log.Info.Printf("Detaching Volume (%s) from (%s)\n", volume.VolumeId, volume.DeviceName)

	opts := &ec2.DetachVolumeInput{
		Device:     aws.String(volume.DeviceName),
		InstanceId: aws.String(volume.InstanceId),
		VolumeId:   aws.String(volume.VolumeId),
	}

	if _, err := volume.svc.DetachVolume(opts); err != nil {

		return fmt.Errorf("Error Detaching volume (%s) to instance (%s), cause : \"%s\"",
			volume.VolumeId, volume.InstanceId, err.Error())

	} else {

		err := volume.waitUntilAvailable()

		if err != nil {
			return fmt.Errorf("Error waiting for Volume (%s) to detach at (%s), cause: %s",
				volume.VolumeId, volume.DeviceName, err.Error())
		} else {
			log.Info.Printf("Detached Volume (%s) from (%s)\n", volume.VolumeId, volume.DeviceName)
		}
	}

	return nil

}

func (volume AllocatedVolume) Info(w io.Writer) error {

	if status, err := volume.svc.DescribeVolumes(volume.describeVolumesInput()); err != nil {

		return fmt.Errorf("Error getting volume status for Volume (%s), cause: \"%s\"",
			volume.VolumeId, err.Error())

	} else {
		volumeStatus := status.Volumes[0]
		fmt.Fprintf(w, "Volume ID (%s), Device Name (%s), Status is %s\n",
			volume.VolumeId, volume.DeviceName, *volumeStatus.State)
	}

	return nil
}

// describeVolumesInput provides the structure to describe this volume when attached to the designated EC2 instance
func (volume AllocatedVolume) describeVolumesInputWhenAttached() *ec2.DescribeVolumesInput {
	return &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volume.VolumeId)},
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name:   aws.String("attachment.instance-id"),
				Values: []*string{aws.String(volume.InstanceId)},
			},
			&ec2.Filter{
				Name:   aws.String("attachment.status"),
				Values: []*string{aws.String(ec2.AttachmentStatusAttached)},
			},
		},
	}
}

// describeVolumesInput provides the structure to describe this volume
func (volume AllocatedVolume) describeVolumesInput() *ec2.DescribeVolumesInput {
	return &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volume.VolumeId)},
	}
}

func (volume AllocatedVolume) waitUntilAvailable() error {

	log.Debug.Printf("Waiting for volume (%s) to become available\n", volume.VolumeId)
	return volume.svc.WaitUntilVolumeAvailable(volume.describeVolumesInput())
}

// waitUntilVolumeAttached uses the Amazon EC2 API operation
// DescribeVolumes to wait for a condition to be met before returning.
// If the condition is not meet within the max attempt window an error will
// be returned.
func (volume AllocatedVolume) waitUntilAttached() error {

	input := volume.describeVolumesInputWhenAttached()

	log.Debug.Printf("Waiting for volume (%s) to be attached at (%s)\n", volume.VolumeId, volume.DeviceName)

	return volume.svc.WaitUntilVolumeInUse(input)

}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced Authors.
// 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 master

import (
	"fmt"
	"time"

	"github.com/control-center/serviced/auth"
	"github.com/control-center/serviced/domain/host"
	"github.com/control-center/serviced/facade"

	"errors"
)

var (
	ErrRequestExpired = errors.New("Authentication request expired")
)

// GetHost gets the host
func (s *Server) GetHost(hostID string, reply *host.Host) error {
	response, err := s.f.GetHost(s.context(), hostID)
	if err != nil {
		return err
	}
	if response == nil {
		return facade.ErrHostDoesNotExist
	}
	*reply = *response
	return nil
}

// GetHosts returns all Hosts
func (s *Server) GetHosts(empty struct{}, hostReply *[]host.Host) error {
	hosts, err := s.f.GetHosts(s.context())
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

// GetActiveHosts returns all active host ids
func (s *Server) GetActiveHostIDs(empty struct{}, hostReply *[]string) error {
	hosts, err := s.f.GetActiveHostIDs(s.context())
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

// AddHost adds the host
func (s *Server) AddHost(host host.Host, hostReply *[]byte) error {
	privateKey, err := s.f.AddHost(s.context(), &host)
	if err != nil {
		return err
	}
	*hostReply = privateKey
	return nil
}

// UpdateHost updates the host
func (s *Server) UpdateHost(host host.Host, _ *struct{}) error {
	return s.f.UpdateHost(s.context(), &host)
}

// RemoveHost removes the host
func (s *Server) RemoveHost(hostID string, _ *struct{}) error {
	return s.f.RemoveHost(s.context(), hostID)
}

// FindHostsInPool  Returns all Hosts in a pool
func (s *Server) FindHostsInPool(poolID string, hostReply *[]host.Host) error {
	hosts, err := s.f.FindHostsInPool(s.context(), poolID)
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

type HostAuthenticationRequest struct {
	HostID    string
	Expires   int64
	Signature []byte
}

type HostAuthenticationResponse struct {
	Token   string
	Expires int64
}

func (req HostAuthenticationRequest) toMessage() []byte {
	return []byte(fmt.Sprintf("%s:%d", req.HostID, req.Expires))
}

func (req HostAuthenticationRequest) valid(publicKeyPEM []byte) error {
	verifier, err := auth.RSAVerifierFromPEM(publicKeyPEM)
	if err != nil {
		return err
	}
	if err := verifier.Verify(req.toMessage(), req.Signature); err != nil {
		return err
	}
	if time.Now().UTC().Unix() >= req.Expires {
		return ErrRequestExpired
	}
	return nil
}

func (s *Server) AuthenticateHost(req HostAuthenticationRequest, resp *HostAuthenticationResponse) error {
	keypem, err := s.f.GetHostKey(s.context(), req.HostID)
	if err != nil {
		return err
	}
	if err := req.valid(keypem); err != nil {
		return err
	}
	host, err := s.f.GetHost(s.context(), req.HostID)
	if err != nil {
		return err
	}
	if host == nil {
		return facade.ErrHostDoesNotExist
	}
	signed, expires, err := auth.CreateJWTIdentity(host.ID, host.PoolID, true, true, keypem, s.expiration)
	if err != nil {
		return err
	}
	*resp = HostAuthenticationResponse{signed, expires}
	return nil
}

// Return host's public key
func (s *Server) GetHostPublicKey(hostID string, key *[]byte) error {
	publicKey, err := s.f.GetHostKey(s.context(), hostID)
	*key = publicKey
	return err
}

// Reset and return host's private key
func (s *Server) ResetHostKey(hostID string, key *[]byte) error {
	publicKey, err := s.f.ResetHostKey(s.context(), hostID)
	*key = publicKey
	return err
}
<commit_msg>Set correct access flags in auth token<commit_after>// Copyright 2014 The Serviced Authors.
// 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 master

import (
	"fmt"
	"time"

	"github.com/control-center/serviced/auth"
	"github.com/control-center/serviced/domain/host"
	"github.com/control-center/serviced/domain/pool"
	"github.com/control-center/serviced/facade"

	"errors"
)

var (
	ErrRequestExpired = errors.New("Authentication request expired")
)

// GetHost gets the host
func (s *Server) GetHost(hostID string, reply *host.Host) error {
	response, err := s.f.GetHost(s.context(), hostID)
	if err != nil {
		return err
	}
	if response == nil {
		return facade.ErrHostDoesNotExist
	}
	*reply = *response
	return nil
}

// GetHosts returns all Hosts
func (s *Server) GetHosts(empty struct{}, hostReply *[]host.Host) error {
	hosts, err := s.f.GetHosts(s.context())
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

// GetActiveHosts returns all active host ids
func (s *Server) GetActiveHostIDs(empty struct{}, hostReply *[]string) error {
	hosts, err := s.f.GetActiveHostIDs(s.context())
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

// AddHost adds the host
func (s *Server) AddHost(host host.Host, hostReply *[]byte) error {
	privateKey, err := s.f.AddHost(s.context(), &host)
	if err != nil {
		return err
	}
	*hostReply = privateKey
	return nil
}

// UpdateHost updates the host
func (s *Server) UpdateHost(host host.Host, _ *struct{}) error {
	return s.f.UpdateHost(s.context(), &host)
}

// RemoveHost removes the host
func (s *Server) RemoveHost(hostID string, _ *struct{}) error {
	return s.f.RemoveHost(s.context(), hostID)
}

// FindHostsInPool  Returns all Hosts in a pool
func (s *Server) FindHostsInPool(poolID string, hostReply *[]host.Host) error {
	hosts, err := s.f.FindHostsInPool(s.context(), poolID)
	if err != nil {
		return err
	}
	*hostReply = hosts
	return nil
}

type HostAuthenticationRequest struct {
	HostID    string
	Expires   int64
	Signature []byte
}

type HostAuthenticationResponse struct {
	Token   string
	Expires int64
}

func (req HostAuthenticationRequest) toMessage() []byte {
	return []byte(fmt.Sprintf("%s:%d", req.HostID, req.Expires))
}

func (req HostAuthenticationRequest) valid(publicKeyPEM []byte) error {
	verifier, err := auth.RSAVerifierFromPEM(publicKeyPEM)
	if err != nil {
		return err
	}
	if err := verifier.Verify(req.toMessage(), req.Signature); err != nil {
		return err
	}
	if time.Now().UTC().Unix() >= req.Expires {
		return ErrRequestExpired
	}
	return nil
}

func (s *Server) AuthenticateHost(req HostAuthenticationRequest, resp *HostAuthenticationResponse) error {
	keypem, err := s.f.GetHostKey(s.context(), req.HostID)
	if err != nil {
		return err
	}
	if err := req.valid(keypem); err != nil {
		return err
	}
	host, err := s.f.GetHost(s.context(), req.HostID)
	if err != nil {
		return err
	}
	if host == nil {
		return facade.ErrHostDoesNotExist
	}
	p, err := s.f.GetResourcePool(s.context(), host.PoolID)
	if err != nil {
		return err
	}
	if p == nil {
		return facade.ErrPoolNotExists
	}
	adminAccess := p.Permissions&pool.AdminAccess != 0
	dfsAccess := p.Permissions&pool.DFSAccess != 0
	signed, expires, err := auth.CreateJWTIdentity(host.ID, host.PoolID, adminAccess, dfsAccess, keypem, s.expiration)
	if err != nil {
		return err
	}
	*resp = HostAuthenticationResponse{signed, expires}
	return nil
}

// Return host's public key
func (s *Server) GetHostPublicKey(hostID string, key *[]byte) error {
	publicKey, err := s.f.GetHostKey(s.context(), hostID)
	*key = publicKey
	return err
}

// Reset and return host's private key
func (s *Server) ResetHostKey(hostID string, key *[]byte) error {
	publicKey, err := s.f.ResetHostKey(s.context(), hostID)
	*key = publicKey
	return err
}
<|endoftext|>


<commit_before>package class

import (
    //"fmt"
    //. "jvmgo/any"
    "jvmgo/classfile"
    //"jvmgo/rtda"
)

func cf2class(cf *classfile.ClassFile) (*Class) {
    class := &Class{obj:&Obj{}}
    class.copyConstantPool(cf)
    class.name = cf.ClassName()
    class.superClassName = cf.SuperClassName()
    class.interfaceNames = cf.InterfaceNames()
    class.copyFields(cf)
    class.copyMethods(cf)
    return class
}

func (self *Class) copyConstantPool(cf *classfile.ClassFile) {
    self.constantPool = newConstantPool(self, cf.ConstantPool())
}

func (self *Class) copyFields(cf *classfile.ClassFile) {
    self.fields = make([]*Field, len(cf.Fields()))
    for i, fieldInfo := range cf.Fields() {
        self.fields[i] = newField(self, fieldInfo)
    }
}

func (self *Class) copyMethods(cf *classfile.ClassFile) {
    self.methods = make([]*Method, len(cf.Methods()))
    for i, methodInfo := range cf.Methods() {
        self.methods[i] = newMethod(self, methodInfo)
    }
}
<commit_msg>code refactor<commit_after>package class

import (
    //"fmt"
    //. "jvmgo/any"
    "jvmgo/classfile"
    //"jvmgo/rtda"
)

func cf2class(cf *classfile.ClassFile) (*Class) {
    class := &Class{obj:&Obj{}}
    class.copyConstantPool(cf)
    class.copyClassNames(cf)
    class.copyFields(cf)
    class.copyMethods(cf)
    return class
}

func (self *Class) copyConstantPool(cf *classfile.ClassFile) {
    self.constantPool = newConstantPool(self, cf.ConstantPool())
}

func (self *Class) copyClassNames(cf *classfile.ClassFile) {
    self.name = cf.ClassName()
    self.superClassName = cf.SuperClassName()
    self.interfaceNames = cf.InterfaceNames()
}

func (self *Class) copyFields(cf *classfile.ClassFile) {
    self.fields = make([]*Field, len(cf.Fields()))
    for i, fieldInfo := range cf.Fields() {
        self.fields[i] = newField(self, fieldInfo)
    }
}

func (self *Class) copyMethods(cf *classfile.ClassFile) {
    self.methods = make([]*Method, len(cf.Methods()))
    for i, methodInfo := range cf.Methods() {
        self.methods[i] = newMethod(self, methodInfo)
    }
}
<|endoftext|>


<commit_before>package cluster // import "github.com/docker/docker/daemon/cluster"

import (
	"context"

	apitypes "github.com/docker/docker/api/types"
	types "github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/daemon/cluster/convert"
	swarmapi "github.com/docker/swarmkit/api"
)

// GetConfig returns a config from a managed swarm cluster
func (c *Cluster) GetConfig(input string) (types.Config, error) {
	var config *swarmapi.Config

	if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		s, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}
		config = s
		return nil
	}); err != nil {
		return types.Config{}, err
	}
	return convert.ConfigFromGRPC(config), nil
}

// GetConfigs returns all configs of a managed swarm cluster.
func (c *Cluster) GetConfigs(options apitypes.ConfigListOptions) ([]types.Config, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	state := c.currentNodeState()
	if !state.IsActiveManager() {
		return nil, c.errNoManager(state)
	}

	filters, err := newListConfigsFilters(options.Filters)
	if err != nil {
		return nil, err
	}
	ctx, cancel := c.getRequestContext()
	defer cancel()

	r, err := state.controlClient.ListConfigs(ctx,
		&swarmapi.ListConfigsRequest{Filters: filters})
	if err != nil {
		return nil, err
	}

	configs := []types.Config{}

	for _, config := range r.Configs {
		configs = append(configs, convert.ConfigFromGRPC(config))
	}

	return configs, nil
}

// CreateConfig creates a new config in a managed swarm cluster.
func (c *Cluster) CreateConfig(s types.ConfigSpec) (string, error) {
	var resp *swarmapi.CreateConfigResponse
	if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		configSpec := convert.ConfigSpecToGRPC(s)

		r, err := state.controlClient.CreateConfig(ctx,
			&swarmapi.CreateConfigRequest{Spec: &configSpec})
		if err != nil {
			return err
		}
		resp = r
		return nil
	}); err != nil {
		return "", err
	}
	return resp.Config.ID, nil
}

// RemoveConfig removes a config from a managed swarm cluster.
func (c *Cluster) RemoveConfig(input string) error {
	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		config, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}

		req := &swarmapi.RemoveConfigRequest{
			ConfigID: config.ID,
		}

		_, err = state.controlClient.RemoveConfig(ctx, req)
		return err
	})
}

// UpdateConfig updates a config in a managed swarm cluster.
// Note: this is not exposed to the CLI but is available from the API only
func (c *Cluster) UpdateConfig(input string, version uint64, spec types.ConfigSpec) error {
	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		config, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}

		configSpec := convert.ConfigSpecToGRPC(spec)

		_, err = state.controlClient.UpdateConfig(ctx,
			&swarmapi.UpdateConfigRequest{
				ConfigID: config.ID,
				ConfigVersion: &swarmapi.Version{
					Index: version,
				},
				Spec: &configSpec,
			})
		return err
	})
}
<commit_msg>set bigger grpc limit for GetConfigs api<commit_after>package cluster // import "github.com/docker/docker/daemon/cluster"

import (
	"context"

	apitypes "github.com/docker/docker/api/types"
	types "github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/daemon/cluster/convert"
	swarmapi "github.com/docker/swarmkit/api"
	"google.golang.org/grpc"
)

// GetConfig returns a config from a managed swarm cluster
func (c *Cluster) GetConfig(input string) (types.Config, error) {
	var config *swarmapi.Config

	if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		s, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}
		config = s
		return nil
	}); err != nil {
		return types.Config{}, err
	}
	return convert.ConfigFromGRPC(config), nil
}

// GetConfigs returns all configs of a managed swarm cluster.
func (c *Cluster) GetConfigs(options apitypes.ConfigListOptions) ([]types.Config, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	state := c.currentNodeState()
	if !state.IsActiveManager() {
		return nil, c.errNoManager(state)
	}

	filters, err := newListConfigsFilters(options.Filters)
	if err != nil {
		return nil, err
	}
	ctx, cancel := c.getRequestContext()
	defer cancel()

	r, err := state.controlClient.ListConfigs(ctx,
		&swarmapi.ListConfigsRequest{Filters: filters},
		grpc.MaxCallRecvMsgSize(defaultRecvSizeForListResponse))
	if err != nil {
		return nil, err
	}

	configs := []types.Config{}

	for _, config := range r.Configs {
		configs = append(configs, convert.ConfigFromGRPC(config))
	}

	return configs, nil
}

// CreateConfig creates a new config in a managed swarm cluster.
func (c *Cluster) CreateConfig(s types.ConfigSpec) (string, error) {
	var resp *swarmapi.CreateConfigResponse
	if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		configSpec := convert.ConfigSpecToGRPC(s)

		r, err := state.controlClient.CreateConfig(ctx,
			&swarmapi.CreateConfigRequest{Spec: &configSpec})
		if err != nil {
			return err
		}
		resp = r
		return nil
	}); err != nil {
		return "", err
	}
	return resp.Config.ID, nil
}

// RemoveConfig removes a config from a managed swarm cluster.
func (c *Cluster) RemoveConfig(input string) error {
	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		config, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}

		req := &swarmapi.RemoveConfigRequest{
			ConfigID: config.ID,
		}

		_, err = state.controlClient.RemoveConfig(ctx, req)
		return err
	})
}

// UpdateConfig updates a config in a managed swarm cluster.
// Note: this is not exposed to the CLI but is available from the API only
func (c *Cluster) UpdateConfig(input string, version uint64, spec types.ConfigSpec) error {
	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
		config, err := getConfig(ctx, state.controlClient, input)
		if err != nil {
			return err
		}

		configSpec := convert.ConfigSpecToGRPC(spec)

		_, err = state.controlClient.UpdateConfig(ctx,
			&swarmapi.UpdateConfigRequest{
				ConfigID: config.ID,
				ConfigVersion: &swarmapi.Version{
					Index: version,
				},
				Spec: &configSpec,
			})
		return err
	})
}
<|endoftext|>


<commit_before>package prompt

import (
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
)

const (
	logfile      = "/tmp/go-prompt-debug.log"
	envEnableLog = "GO_PROMPT_ENABLE_LOG"
)

type Executor func(string)
type Completer func(string) []Suggest

type Prompt struct {
	in         ConsoleParser
	buf        *Buffer
	renderer   *Render
	executor   Executor
	history    *History
	completion *CompletionManager
}

type Exec struct {
	input string
}

func (p *Prompt) Run() {
	p.setUp()
	defer p.tearDown()

	p.renderer.Render(p.buf, p.completion)

	bufCh := make(chan []byte, 128)
	stopReadBufCh := make(chan struct{})
	go readBuffer(bufCh, stopReadBufCh)

	exitCh := make(chan int)
	winSizeCh := make(chan *WinSize)
	go handleSignals(p.in, exitCh, winSizeCh)

	for {
		select {
		case b := <-bufCh:
			if shouldExit, e := p.feed(b); shouldExit {
				p.renderer.BreakLine(p.buf)
				return
			} else if e != nil {
				// Stop goroutine to run readBuffer function
				stopReadBufCh <- struct{}{}

				// Unset raw mode
				// Reset to Blocking mode because returned EAGAIN when still set non-blocking mode.
				p.in.TearDown()
				p.executor(e.input)

				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)

				// Set raw mode
				p.in.Setup()
				go readBuffer(bufCh, stopReadBufCh)
			} else {
				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)
			}
		case w := <-winSizeCh:
			p.renderer.UpdateWinSize(w)
			p.renderer.Render(p.buf, p.completion)
		case code := <-exitCh:
			p.renderer.BreakLine(p.buf)
			p.tearDown()
			os.Exit(code)
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func (p *Prompt) feed(b []byte) (shouldExit bool, exec *Exec) {
	key := p.in.GetKey(b)

	switch key {
	case ControlJ, Enter:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
		}
		p.renderer.BreakLine(p.buf)

		exec = &Exec{input: p.buf.Text()}
		log.Printf("[History] %s", p.buf.Text())
		p.buf = NewBuffer()
		p.completion.Reset()
		if exec.input != "" {
			p.history.Add(exec.input)
		}
	case ControlC:
		p.renderer.BreakLine(p.buf)
		p.buf = NewBuffer()
		p.completion.Reset()
		p.history.Clear()
	case ControlD:
		shouldExit = true
	case Up:
		if !p.completion.Completing() {
			if newBuf, changed := p.history.Older(p.buf); changed {
				p.buf = newBuf
			}
			return
		}
		fallthrough
	case BackTab:
		p.completion.Previous()
	case Down:
		if !p.completion.Completing() {
			if newBuf, changed := p.history.Newer(p.buf); changed {
				p.buf = newBuf
			}
			return
		}
		fallthrough
	case Tab, ControlI:
		p.completion.Next()
	case Left:
		p.buf.CursorLeft(1)
	case Right:
		p.buf.CursorRight(1)
	case Backspace:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
			p.completion.Reset()
		}
		p.buf.DeleteBeforeCursor(1)
	case NotDefined:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
		}
		p.completion.Reset()
		p.buf.InsertText(string(b), false, true)
	default:
		p.completion.Reset()
	}
	return
}

func (p *Prompt) Input() string {
	p.setUp()
	defer p.tearDown()

	p.renderer.Render(p.buf, p.completion)
	bufCh := make(chan []byte, 128)
	stopReadBufCh := make(chan struct{})
	go readBuffer(bufCh, stopReadBufCh)

	for {
		select {
		case b := <-bufCh:
			if shouldExit, e := p.feed(b); shouldExit {
				p.renderer.BreakLine(p.buf)
				return ""
			} else if e != nil {
				// Stop goroutine to run readBuffer function
				stopReadBufCh <- struct{}{}
				return e.input
			} else {
				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)
			}
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func (p *Prompt) setUp() {
	// Logging
	if os.Getenv(envEnableLog) != "true" {
		log.SetOutput(ioutil.Discard)
	} else if f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err != nil {
		log.SetOutput(ioutil.Discard)
	} else {
		defer f.Close()
		log.SetOutput(f)
		log.Println("[INFO] Logging is enabled.")
	}

	p.in.Setup()
	p.renderer.Setup()
	p.renderer.UpdateWinSize(p.in.GetWinSize())
}

func (p *Prompt) tearDown() {
	p.in.TearDown()
	p.renderer.TearDown()
}

func readBuffer(bufCh chan []byte, stopCh chan struct{}) {
	buf := make([]byte, 1024)

	log.Printf("[INFO] readBuffer start")
	for {
		time.Sleep(10 * time.Millisecond)
		select {
		case <-stopCh:
			log.Print("[INFO] stop readBuffer")
			return
		default:
			if n, err := syscall.Read(syscall.Stdin, buf); err == nil {
				bufCh <- buf[:n]
			}
		}
	}
}

func handleSignals(in ConsoleParser, exitCh chan int, winSizeCh chan *WinSize) {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(
		sigCh,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT,
		syscall.SIGWINCH,
	)

	for {
		s := <-sigCh
		switch s {
		case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c
			log.Println("[SIGNAL] Catch SIGINT")
			exitCh <- 0

		case syscall.SIGTERM: // kill -SIGTERM XXXX
			log.Println("[SIGNAL] Catch SIGTERM")
			exitCh <- 1

		case syscall.SIGQUIT: // kill -SIGQUIT XXXX
			log.Println("[SIGNAL] Catch SIGQUIT")
			exitCh <- 0

		case syscall.SIGWINCH:
			log.Println("[SIGNAL] Catch SIGWINCH")
			winSizeCh <- in.GetWinSize()
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}
<commit_msg>Add some keybind<commit_after>package prompt

import (
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
)

const (
	logfile      = "/tmp/go-prompt-debug.log"
	envEnableLog = "GO_PROMPT_ENABLE_LOG"
)

type Executor func(string)
type Completer func(string) []Suggest

type Prompt struct {
	in         ConsoleParser
	buf        *Buffer
	renderer   *Render
	executor   Executor
	history    *History
	completion *CompletionManager
}

type Exec struct {
	input string
}

func (p *Prompt) Run() {
	p.setUp()
	defer p.tearDown()

	p.renderer.Render(p.buf, p.completion)

	bufCh := make(chan []byte, 128)
	stopReadBufCh := make(chan struct{})
	go readBuffer(bufCh, stopReadBufCh)

	exitCh := make(chan int)
	winSizeCh := make(chan *WinSize)
	go handleSignals(p.in, exitCh, winSizeCh)

	for {
		select {
		case b := <-bufCh:
			if shouldExit, e := p.feed(b); shouldExit {
				p.renderer.BreakLine(p.buf)
				return
			} else if e != nil {
				// Stop goroutine to run readBuffer function
				stopReadBufCh <- struct{}{}

				// Unset raw mode
				// Reset to Blocking mode because returned EAGAIN when still set non-blocking mode.
				p.in.TearDown()
				p.executor(e.input)

				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)

				// Set raw mode
				p.in.Setup()
				go readBuffer(bufCh, stopReadBufCh)
			} else {
				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)
			}
		case w := <-winSizeCh:
			p.renderer.UpdateWinSize(w)
			p.renderer.Render(p.buf, p.completion)
		case code := <-exitCh:
			p.renderer.BreakLine(p.buf)
			p.tearDown()
			os.Exit(code)
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func (p *Prompt) feed(b []byte) (shouldExit bool, exec *Exec) {
	key := p.in.GetKey(b)

	switch key {
	case ControlJ, Enter:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
		}
		p.renderer.BreakLine(p.buf)

		exec = &Exec{input: p.buf.Text()}
		log.Printf("[History] %s", p.buf.Text())
		p.buf = NewBuffer()
		p.completion.Reset()
		if exec.input != "" {
			p.history.Add(exec.input)
		}
	case ControlA:
		x := []rune(p.buf.Document().TextBeforeCursor())
		p.buf.CursorLeft(len(x))
	case ControlE:
		x := []rune(p.buf.Document().TextAfterCursor())
		p.buf.CursorRight(len(x))
	case ControlK:
		x := []rune(p.buf.Document().TextAfterCursor())
		p.buf.Delete(len(x))
	case ControlU:
		x := []rune(p.buf.Document().TextBeforeCursor())
		p.buf.DeleteBeforeCursor(len(x))
	case ControlC:
		p.renderer.BreakLine(p.buf)
		p.buf = NewBuffer()
		p.completion.Reset()
		p.history.Clear()
	case ControlD:
		if p.buf.Text() == "" {
			shouldExit = true
		} else {
			p.buf.Delete(1)
		}
	case Up:
		if !p.completion.Completing() {
			if newBuf, changed := p.history.Older(p.buf); changed {
				p.buf = newBuf
			}
			return
		}
		fallthrough
	case BackTab:
		p.completion.Previous()
	case Down:
		if !p.completion.Completing() {
			if newBuf, changed := p.history.Newer(p.buf); changed {
				p.buf = newBuf
			}
			return
		}
		fallthrough
	case Tab, ControlI:
		p.completion.Next()
	case Left:
		p.buf.CursorLeft(1)
	case Right:
		p.buf.CursorRight(1)
	case Backspace:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
			p.completion.Reset()
		}
		p.buf.DeleteBeforeCursor(1)
	case NotDefined:
		if s, ok := p.completion.GetSelectedSuggestion(); ok {
			w := p.buf.Document().GetWordBeforeCursor()
			if w != "" {
				p.buf.DeleteBeforeCursor(len([]rune(w)))
			}
			p.buf.InsertText(s.Text, false, true)
		}
		p.completion.Reset()
		p.buf.InsertText(string(b), false, true)
	default:
		p.completion.Reset()
	}
	return
}

func (p *Prompt) Input() string {
	p.setUp()
	defer p.tearDown()

	p.renderer.Render(p.buf, p.completion)
	bufCh := make(chan []byte, 128)
	stopReadBufCh := make(chan struct{})
	go readBuffer(bufCh, stopReadBufCh)

	for {
		select {
		case b := <-bufCh:
			if shouldExit, e := p.feed(b); shouldExit {
				p.renderer.BreakLine(p.buf)
				return ""
			} else if e != nil {
				// Stop goroutine to run readBuffer function
				stopReadBufCh <- struct{}{}
				return e.input
			} else {
				p.completion.Update(p.buf.Text())
				p.renderer.Render(p.buf, p.completion)
			}
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func (p *Prompt) setUp() {
	// Logging
	if os.Getenv(envEnableLog) != "true" {
		log.SetOutput(ioutil.Discard)
	} else if f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err != nil {
		log.SetOutput(ioutil.Discard)
	} else {
		defer f.Close()
		log.SetOutput(f)
		log.Println("[INFO] Logging is enabled.")
	}

	p.in.Setup()
	p.renderer.Setup()
	p.renderer.UpdateWinSize(p.in.GetWinSize())
}

func (p *Prompt) tearDown() {
	p.in.TearDown()
	p.renderer.TearDown()
}

func readBuffer(bufCh chan []byte, stopCh chan struct{}) {
	buf := make([]byte, 1024)

	log.Printf("[INFO] readBuffer start")
	for {
		time.Sleep(10 * time.Millisecond)
		select {
		case <-stopCh:
			log.Print("[INFO] stop readBuffer")
			return
		default:
			if n, err := syscall.Read(syscall.Stdin, buf); err == nil {
				bufCh <- buf[:n]
			}
		}
	}
}

func handleSignals(in ConsoleParser, exitCh chan int, winSizeCh chan *WinSize) {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(
		sigCh,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT,
		syscall.SIGWINCH,
	)

	for {
		s := <-sigCh
		switch s {
		case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c
			log.Println("[SIGNAL] Catch SIGINT")
			exitCh <- 0

		case syscall.SIGTERM: // kill -SIGTERM XXXX
			log.Println("[SIGNAL] Catch SIGTERM")
			exitCh <- 1

		case syscall.SIGQUIT: // kill -SIGQUIT XXXX
			log.Println("[SIGNAL] Catch SIGQUIT")
			exitCh <- 0

		case syscall.SIGWINCH:
			log.Println("[SIGNAL] Catch SIGWINCH")
			winSizeCh <- in.GetWinSize()
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}
<|endoftext|>


<commit_before>// Main package wraps sprite_sass tool for use with the command line
// See -h for list of available options
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"strings"

	"github.com/drewwells/sprite_sass/context"
	"github.com/drewwells/spritewell"

	sprite "github.com/drewwells/sprite_sass"
)

const version = `v0.2.1`

var (
	Dir, Gen, Input, Includes string
	MainFile, Style           string
	Comments                  bool
	cpuprofile                string
	Help, ShowVersion         bool
	BuildDir                  string
)

func init() {
	flag.StringVar(&BuildDir, "b", "", "Build Directory")
	flag.StringVar(&Includes, "p", "", "SASS import path")
	flag.BoolVar(&Help, "help", false, "this help")
	flag.BoolVar(&Help, "h", false, "this help")
	flag.StringVar(&Dir, "dir", "", "Image directory")
	flag.StringVar(&Dir, "d", "", "Image directory")
	flag.StringVar(&Gen, "gen", ".", "Directory for generated images")
	flag.StringVar(&Style, "style", "nested", "CSS nested style")
	flag.StringVar(&Style, "s", "nested", "CSS nested style")
	flag.BoolVar(&Comments, "comment", true, "Turn on source comments")
	flag.BoolVar(&Comments, "c", true, "Turn on source comments")
	flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
	flag.BoolVar(&ShowVersion, "version", false, "Show the app version")
}

func main() {
	flag.Parse()

	if ShowVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	// Profiling code
	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		log.Println("Starting profiler")
		pprof.StartCPUProfile(f)
		defer func() {
			pprof.StopCPUProfile()
			err := f.Close()
			if err != nil {
				log.Fatal(err)
			}
			log.Println("Stopping Profiller")
		}()
	}

	for _, v := range flag.Args() {
		if strings.HasPrefix(v, "-") {
			log.Fatalf("Please specify flags before other arguments: %s", v)
		}
	}

	if Help {
		fmt.Println("Please specify input filepath.")
		fmt.Println("\nAvailable options:")
		flag.PrintDefaults()
		return
	}

	style, ok := context.Style[Style]

	if !ok {
		style = context.NESTED_STYLE
	}

	if len(flag.Args()) == 0 {
		// Read from stdin
		log.Print("Reading from stdin, -h for help")
		out := os.Stdout
		in := os.Stdin

		var pout bytes.Buffer
		ctx := context.Context{}
		err := startParser(ctx, in, &pout, "")
		if err != nil {
			log.Println(err)
		}
		err = ctx.Compile(&pout, out)

		if err != nil {
			log.Println(err)
		}
	}
	sharedSprites := make(map[string]spritewell.ImageList, 100)
	sharedImgs := make(map[string]spritewell.ImageList, 100)
	for _, f := range flag.Args() {
		// Remove partials
		if strings.HasPrefix(filepath.Base(f), "_") {
			continue
		}
		log.Println("Open:", f)

		// If no imagedir specified, assume relative to the input file
		if Dir == "" {
			Dir = filepath.Dir(f)
		}
		var (
			out  io.WriteCloser
			fout string
		)
		if BuildDir != "" {
			// Build output file based off build directory and input filename
			rel, _ := filepath.Rel(Includes, filepath.Dir(f))
			filename := strings.Replace(filepath.Base(f), ".scss", ".css", 1)
			fout = filepath.Join(BuildDir, rel, filename)
		} else {
			out = os.Stdout
		}

		ctx := context.Context{
			// TODO: Most of these fields are no longer used
			Sprites:     sharedSprites,
			Imgs:        sharedImgs,
			OutputStyle: style,
			ImageDir:    Dir,
			// Assumption that output is a file
			BuildDir:     BuildDir,
			GenImgDir:    Gen,
			MainFile:     f,
			Comments:     Comments,
			IncludePaths: []string{filepath.Dir(f)},
		}
		if Includes != "" {
			ctx.IncludePaths = append(ctx.IncludePaths,
				strings.Split(Includes, ",")...)
		}
		fRead, err := os.Open(f)
		if err != nil {
			log.Fatal(err)
		}
		if fout != "" {
			dir := filepath.Dir(fout)
			err := os.MkdirAll(dir, 0755)
			if err != nil {
				log.Fatalf("Failed to create directory: %s", dir)
			}

			out, err = os.Create(fout)
			if err != nil {
				log.Fatalf("Failed to create file: %s", f)
			}
			log.Println("Created:", fout)
		}

		var pout bytes.Buffer
		err = startParser(ctx, fRead, &pout, filepath.Dir(Input))
		if err != nil {
			log.Println(err)
			continue
		}
		err = ctx.Compile(&pout, out)

		if err != nil {
			log.Println(err)
		}
	}
}

func startParser(ctx context.Context, in io.Reader, out io.Writer, pkgdir string) error {
	// Run the sprite_sass parser prior to passing to libsass
	parser := sprite.Parser{
		ImageDir:  ctx.ImageDir,
		Includes:  ctx.IncludePaths,
		BuildDir:  ctx.BuildDir,
		GenImgDir: ctx.GenImgDir,
	}
	// Save reference to parser in context
	bs, err := parser.Start(in, pkgdir)
	if err != nil {
		return err
	}
	out.Write(bs)
	return err
}
<commit_msg>Close files and ignore open/creation statements<commit_after>// Main package wraps sprite_sass tool for use with the command line
// See -h for list of available options
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"strings"

	"github.com/drewwells/sprite_sass/context"
	"github.com/drewwells/spritewell"

	sprite "github.com/drewwells/sprite_sass"
)

const version = `v0.2.1`

var (
	Dir, Gen, Input, Includes string
	MainFile, Style           string
	Comments                  bool
	cpuprofile                string
	Help, ShowVersion         bool
	BuildDir                  string
)

func init() {
	flag.StringVar(&BuildDir, "b", "", "Build Directory")
	flag.StringVar(&Includes, "p", "", "SASS import path")
	flag.BoolVar(&Help, "help", false, "this help")
	flag.BoolVar(&Help, "h", false, "this help")
	flag.StringVar(&Dir, "dir", "", "Image directory")
	flag.StringVar(&Dir, "d", "", "Image directory")
	flag.StringVar(&Gen, "gen", ".", "Directory for generated images")
	flag.StringVar(&Style, "style", "nested", "CSS nested style")
	flag.StringVar(&Style, "s", "nested", "CSS nested style")
	flag.BoolVar(&Comments, "comment", true, "Turn on source comments")
	flag.BoolVar(&Comments, "c", true, "Turn on source comments")
	flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
	flag.BoolVar(&ShowVersion, "version", false, "Show the app version")
}

func main() {
	flag.Parse()

	if ShowVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	// Profiling code
	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		log.Println("Starting profiler")
		pprof.StartCPUProfile(f)
		defer func() {
			pprof.StopCPUProfile()
			err := f.Close()
			if err != nil {
				log.Fatal(err)
			}
			log.Println("Stopping Profiller")
		}()
	}

	for _, v := range flag.Args() {
		if strings.HasPrefix(v, "-") {
			log.Fatalf("Please specify flags before other arguments: %s", v)
		}
	}

	if Help {
		fmt.Println("Please specify input filepath.")
		fmt.Println("\nAvailable options:")
		flag.PrintDefaults()
		return
	}

	style, ok := context.Style[Style]

	if !ok {
		style = context.NESTED_STYLE
	}

	if len(flag.Args()) == 0 {
		// Read from stdin
		log.Print("Reading from stdin, -h for help")
		out := os.Stdout
		in := os.Stdin

		var pout bytes.Buffer
		ctx := context.Context{}
		err := startParser(ctx, in, &pout, "")
		if err != nil {
			log.Println(err)
		}
		err = ctx.Compile(&pout, out)

		if err != nil {
			log.Println(err)
		}
	}
	sharedSprites := make(map[string]spritewell.ImageList, 100)
	sharedImgs := make(map[string]spritewell.ImageList, 100)
	for _, f := range flag.Args() {
		// Remove partials
		if strings.HasPrefix(filepath.Base(f), "_") {
			continue
		}
		// log.Println("Open:", f)

		// If no imagedir specified, assume relative to the input file
		if Dir == "" {
			Dir = filepath.Dir(f)
		}
		var (
			out  io.WriteCloser
			fout string
		)
		if BuildDir != "" {
			// Build output file based off build directory and input filename
			rel, _ := filepath.Rel(Includes, filepath.Dir(f))
			filename := strings.Replace(filepath.Base(f), ".scss", ".css", 1)
			fout = filepath.Join(BuildDir, rel, filename)
		} else {
			out = os.Stdout
		}

		ctx := context.Context{
			// TODO: Most of these fields are no longer used
			Sprites:     sharedSprites,
			Imgs:        sharedImgs,
			OutputStyle: style,
			ImageDir:    Dir,
			// Assumption that output is a file
			BuildDir:     BuildDir,
			GenImgDir:    Gen,
			MainFile:     f,
			Comments:     Comments,
			IncludePaths: []string{filepath.Dir(f)},
		}
		if Includes != "" {
			ctx.IncludePaths = append(ctx.IncludePaths,
				strings.Split(Includes, ",")...)
		}
		fRead, err := os.Open(f)
		defer fRead.Close()
		if err != nil {
			log.Fatal(err)
		}
		if fout != "" {
			dir := filepath.Dir(fout)
			err := os.MkdirAll(dir, 0755)
			if err != nil {
				log.Fatalf("Failed to create directory: %s", dir)
			}

			out, err = os.Create(fout)
			defer out.Close()
			if err != nil {
				log.Fatalf("Failed to create file: %s", f)
			}
			// log.Println("Created:", fout)
		}

		var pout bytes.Buffer
		err = startParser(ctx, fRead, &pout, filepath.Dir(Input))
		if err != nil {
			log.Println(err)
			continue
		}
		err = ctx.Compile(&pout, out)

		if err != nil {
			log.Println(err)
		}
	}
}

func startParser(ctx context.Context, in io.Reader, out io.Writer, pkgdir string) error {
	// Run the sprite_sass parser prior to passing to libsass
	parser := sprite.Parser{
		ImageDir:  ctx.ImageDir,
		Includes:  ctx.IncludePaths,
		BuildDir:  ctx.BuildDir,
		GenImgDir: ctx.GenImgDir,
	}
	// Save reference to parser in context
	bs, err := parser.Start(in, pkgdir)
	if err != nil {
		return err
	}
	out.Write(bs)
	return err
}
<|endoftext|>


<commit_before>package httpd

import (
	"bufio"
	"fmt"
	"github.com/Symantec/Dominator/lib/filesystem"
	"io"
	"net/http"
	"path"
)

func (s state) listComputedInodesHandler(w http.ResponseWriter,
	req *http.Request) {
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	imageName := req.URL.RawQuery
	fmt.Fprintf(writer, "<title>image %s computed inodes</title>\n", imageName)
	fmt.Fprintln(writer, ``)
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "
")
	if image := s.imageDataBase.GetImage(imageName); image == nil {
		fmt.Fprintf(writer, "Image: %s UNKNOWN!\n", imageName)
	} else {
		fmt.Fprintf(writer, "Computed files for image: %s\n", imageName)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, `<table border="1" style="width:100%">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Filename	")
		fmt.Fprintln(writer, "    Data Source	")
		fmt.Fprintln(writer, "
")
		// Walk the file-system to leverage stable and friendly sort order.
		listComputedInodes(writer, &image.FileSystem.DirectoryInode, "/")
		fmt.Fprintln(writer, "
")
	}
	fmt.Fprintln(writer, "")
}

func listComputedInodes(writer io.Writer,
	directoryInode *filesystem.DirectoryInode, name string) {
	for _, dirent := range directoryInode.EntryList {
		fmt.Fprintln(writer, "
")
		if inode, ok := dirent.Inode().(*filesystem.ComputedRegularInode); ok {
			fmt.Fprintf(writer, "    %s	\n",
				path.Join(name, dirent.Name))
			fmt.Fprintf(writer, "    %s	\n", inode.Source)
		} else if inode, ok := dirent.Inode().(*filesystem.DirectoryInode); ok {
			listComputedInodes(writer, inode, path.Join(name, dirent.Name))
		}
		fmt.Fprintln(writer, "
")
	}
}
<commit_msg>Do not show empty rows in display of computed files in imageserver.<commit_after>package httpd

import (
	"bufio"
	"fmt"
	"github.com/Symantec/Dominator/lib/filesystem"
	"io"
	"net/http"
	"path"
)

func (s state) listComputedInodesHandler(w http.ResponseWriter,
	req *http.Request) {
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	imageName := req.URL.RawQuery
	fmt.Fprintf(writer, "<title>image %s computed inodes</title>\n", imageName)
	fmt.Fprintln(writer, ``)
	fmt.Fprintln(writer, "")
	fmt.Fprintln(writer, "
")
	if image := s.imageDataBase.GetImage(imageName); image == nil {
		fmt.Fprintf(writer, "Image: %s UNKNOWN!\n", imageName)
	} else {
		fmt.Fprintf(writer, "Computed files for image: %s\n", imageName)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, `<table border="1" style="width:100%">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Filename	")
		fmt.Fprintln(writer, "    Data Source	")
		fmt.Fprintln(writer, "
")
		// Walk the file-system to leverage stable and friendly sort order.
		listComputedInodes(writer, &image.FileSystem.DirectoryInode, "/")
		fmt.Fprintln(writer, "
")
	}
	fmt.Fprintln(writer, "")
}

func listComputedInodes(writer io.Writer,
	directoryInode *filesystem.DirectoryInode, name string) {
	for _, dirent := range directoryInode.EntryList {
		if inode, ok := dirent.Inode().(*filesystem.ComputedRegularInode); ok {
			fmt.Fprintln(writer, "
")
			fmt.Fprintf(writer, "    %s	\n",
				path.Join(name, dirent.Name))
			fmt.Fprintf(writer, "    %s	\n", inode.Source)
			fmt.Fprintln(writer, "
")
		} else if inode, ok := dirent.Inode().(*filesystem.DirectoryInode); ok {
			listComputedInodes(writer, inode, path.Join(name, dirent.Name))
		}
	}
}
<|endoftext|>


<commit_before>package spipe

import (
	"testing"

	ci "github.com/jbenet/go-ipfs/crypto"
	"github.com/jbenet/go-ipfs/peer"
)

func TestHandshake(t *testing.T) {
	ska, pka, err := ci.GenerateKeyPair(ci.RSA, 512)
	if err != nil {
		t.Fatal(err)
	}
	skb, pkb, err := ci.GenerateKeyPair(ci.RSA, 512)
	if err != nil {
		t.Fatal(err)
	}

	cha := make(chan []byte, 5)
	chb := make(chan []byte, 5)

	ida, err := IDFromPubKey(pka)
	if err != nil {
		t.Fatal(err)
	}
	pa := &peer.Peer{
		ID:      ida,
		PubKey:  pka,
		PrivKey: ska,
	}

	idb, err := IDFromPubKey(pkb)
	if err != nil {
		t.Fatal(err)
	}
	pb := &peer.Peer{
		ID:      idb,
		PubKey:  pkb,
		PrivKey: skb,
	}

	go func() {
		_, _, err := Handshake(pa, pb, cha, chb)
		if err != nil {
			t.Fatal(err)
		}
	}()

	_, _, err = Handshake(pb, pa, chb, cha)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>misc(crypto) remove stale test<commit_after><|endoftext|>