<commit_before>package core

import (
	"errors"
	"fmt"
	"sync"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/logger"
)

var (
	txplogger = logger.NewLogger("TXP")

	ErrInvalidSender = errors.New("Invalid sender")
)

const txPoolQueueSize = 50

type TxPoolHook chan *types.Transaction
type TxMsg struct {
	Tx *types.Transaction
}

const (
	minGasPrice = 1000000
)

type TxProcessor interface {
	ProcessTransaction(tx *types.Transaction)
}

// The tx pool a thread safe transaction pool handler. In order to
// guarantee a non blocking pool we use a queue channel which can be
// independently read without needing access to the actual pool.
type TxPool struct {
	mu sync.RWMutex
	// Queueing channel for reading and writing incoming
	// transactions to
	queueChan chan *types.Transaction
	// Quiting channel
	quit chan bool
	// The actual pool
	//pool *list.List
	txs map[string]*types.Transaction

	SecondaryProcessor TxProcessor

	subscribers []chan TxMsg

	eventMux *event.TypeMux
}

func NewTxPool(eventMux *event.TypeMux) *TxPool {
	return &TxPool{
		txs:       make(map[string]*types.Transaction),
		queueChan: make(chan *types.Transaction, txPoolQueueSize),
		quit:      make(chan bool),
		eventMux:  eventMux,
	}
}

func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
	if len(tx.To()) != 0 && len(tx.To()) != 20 {
		return fmt.Errorf("Invalid recipient. len = %d", len(tx.To()))
	}

	// Validate curve param
	v, _, _ := tx.Curve()
	if v > 28 || v < 27 {
		return fmt.Errorf("tx.v != (28 || 27) => %v", v)
	}

	// Validate sender address
	senderAddr := tx.From()
	if senderAddr == nil || len(senderAddr) != 20 {
		return ErrInvalidSender
	}

	/* XXX this kind of validation needs to happen elsewhere in the gui when sending txs.
	   Other clients should do their own validation. Value transfer could throw error
	   but doesn't necessarily invalidate the tx. Gas can still be payed for and miner
	   can still be rewarded for their inclusion and processing.
	sender := pool.stateQuery.GetAccount(senderAddr)
	totAmount := new(big.Int).Set(tx.Value())
	// Make sure there's enough in the sender's account. Having insufficient
	// funds won't invalidate this transaction but simple ignores it.
	if sender.Balance().Cmp(totAmount) < 0 {
		return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From())
	}
	*/

	return nil
}

func (self *TxPool) addTx(tx *types.Transaction) {
	self.txs[string(tx.Hash())] = tx
}

func (self *TxPool) add(tx *types.Transaction) error {
	if self.txs[string(tx.Hash())] != nil {
		return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
	}

	err := self.ValidateTransaction(tx)
	if err != nil {
		return err
	}

	self.addTx(tx)

	var to string
	if len(tx.To()) > 0 {
		to = common.Bytes2Hex(tx.To()[:4])
	} else {
		to = "[NEW_CONTRACT]"
	}
	var from string
	if len(tx.From()) > 0 {
		from = common.Bytes2Hex(tx.From()[:4])
	} else {
		return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From()))
	}
	txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())

	// Notify the subscribers
	go self.eventMux.Post(TxPreEvent{tx})

	return nil
}

func (self *TxPool) Size() int {
	return len(self.txs)
}

func (self *TxPool) Add(tx *types.Transaction) error {
	self.mu.Lock()
	defer self.mu.Unlock()
	return self.add(tx)
}
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
	self.mu.Lock()
	defer self.mu.Unlock()

	for _, tx := range txs {
		if err := self.add(tx); err != nil {
			txplogger.Debugln(err)
		} else {
			txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
		}
	}
}

func (self *TxPool) GetTransactions() (txs types.Transactions) {
	self.mu.RLock()
	defer self.mu.RUnlock()

	txs = make(types.Transactions, self.Size())
	i := 0
	for _, tx := range self.txs {
		txs[i] = tx
		i++
	}

	return
}

func (pool *TxPool) RemoveInvalid(query StateQuery) {
	pool.mu.Lock()

	var removedTxs types.Transactions
	for _, tx := range pool.txs {
		sender := query.GetAccount(tx.From())
		err := pool.ValidateTransaction(tx)
		if err != nil || sender.Nonce() >= tx.Nonce() {
			removedTxs = append(removedTxs, tx)
		}
	}
	pool.mu.Unlock()

	pool.RemoveSet(removedTxs)
}

func (self *TxPool) RemoveSet(txs types.Transactions) {
	self.mu.Lock()
	defer self.mu.Unlock()

	for _, tx := range txs {
		delete(self.txs, string(tx.Hash()))
	}
}

func (pool *TxPool) Flush() {
	pool.txs = make(map[string]*types.Transaction)
}

func (pool *TxPool) Start() {
}

func (pool *TxPool) Stop() {
	pool.Flush()

	txplogger.Infoln("Stopped")
}
<commit_msg>core: convert transaction pool to common.{Address,Hash}<commit_after>package core

import (
	"errors"
	"fmt"
	"sync"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/logger"
)

var (
	txplogger = logger.NewLogger("TXP")

	ErrInvalidSender = errors.New("Invalid sender")
)

const txPoolQueueSize = 50

type TxPoolHook chan *types.Transaction
type TxMsg struct{ Tx *types.Transaction }

const (
	minGasPrice = 1000000
)

type TxProcessor interface {
	ProcessTransaction(tx *types.Transaction)
}

// The tx pool a thread safe transaction pool handler. In order to
// guarantee a non blocking pool we use a queue channel which can be
// independently read without needing access to the actual pool.
type TxPool struct {
	mu sync.RWMutex
	// Queueing channel for reading and writing incoming
	// transactions to
	queueChan chan *types.Transaction
	// Quiting channel
	quit chan bool
	// The actual pool
	//pool *list.List
	txs map[common.Hash]*types.Transaction

	SecondaryProcessor TxProcessor

	subscribers []chan TxMsg

	eventMux *event.TypeMux
}

func NewTxPool(eventMux *event.TypeMux) *TxPool {
	return &TxPool{
		txs:       make(map[common.Hash]*types.Transaction),
		queueChan: make(chan *types.Transaction, txPoolQueueSize),
		quit:      make(chan bool),
		eventMux:  eventMux,
	}
}

func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
	// Validate sender
	if _, err := tx.From(); err != nil {
		return err
	}
	// Validate curve param
	v, _, _ := tx.Curve()
	if v > 28 || v < 27 {
		return fmt.Errorf("tx.v != (28 || 27) => %v", v)
	}
	return nil

	/* XXX this kind of validation needs to happen elsewhere in the gui when sending txs.
	   Other clients should do their own validation. Value transfer could throw error
	   but doesn't necessarily invalidate the tx. Gas can still be payed for and miner
	   can still be rewarded for their inclusion and processing.
	sender := pool.stateQuery.GetAccount(senderAddr)
	totAmount := new(big.Int).Set(tx.Value())
	// Make sure there's enough in the sender's account. Having insufficient
	// funds won't invalidate this transaction but simple ignores it.
	if sender.Balance().Cmp(totAmount) < 0 {
		return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From())
	}
	*/
}

func (self *TxPool) addTx(tx *types.Transaction) {
	self.txs[tx.Hash()] = tx
}

func (self *TxPool) add(tx *types.Transaction) error {
	if self.txs[tx.Hash()] != nil {
		return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
	}
	err := self.ValidateTransaction(tx)
	if err != nil {
		return err
	}

	self.addTx(tx)

	var toname string
	if to, valid := tx.To(); valid {
		toname = common.Bytes2Hex(to[:4])
	} else {
		toname = "[NEW_CONTRACT]"
	}
	// we can ignore the error here because From is
	// verified in ValidateTransaction.
	f, _ := tx.From()
	from := common.Bytes2Hex(f[:4])
	txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())

	// Notify the subscribers
	go self.eventMux.Post(TxPreEvent{tx})

	return nil
}

func (self *TxPool) Size() int {
	return len(self.txs)
}

func (self *TxPool) Add(tx *types.Transaction) error {
	self.mu.Lock()
	defer self.mu.Unlock()
	return self.add(tx)
}

func (self *TxPool) AddTransactions(txs []*types.Transaction) {
	self.mu.Lock()
	defer self.mu.Unlock()

	for _, tx := range txs {
		if err := self.add(tx); err != nil {
			txplogger.Debugln(err)
		} else {
			txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
		}
	}
}

func (self *TxPool) GetTransactions() (txs types.Transactions) {
	self.mu.RLock()
	defer self.mu.RUnlock()

	txs = make(types.Transactions, self.Size())
	i := 0
	for _, tx := range self.txs {
		txs[i] = tx
		i++
	}

	return
}

func (pool *TxPool) RemoveInvalid(query StateQuery) {
	pool.mu.Lock()

	var removedTxs types.Transactions
	for _, tx := range pool.txs {
		sender := query.GetAccount(tx.From())
		err := pool.ValidateTransaction(tx)
		if err != nil || sender.Nonce() >= tx.Nonce() {
			removedTxs = append(removedTxs, tx)
		}
	}
	pool.mu.Unlock()

	pool.RemoveSet(removedTxs)
}

func (self *TxPool) RemoveSet(txs types.Transactions) {
	self.mu.Lock()
	defer self.mu.Unlock()
	for _, tx := range txs {
		delete(self.txs, tx.Hash())
	}
}

func (pool *TxPool) Flush() {
	pool.txs = make(map[common.Hash]*types.Transaction)
}

func (pool *TxPool) Start() {
}

func (pool *TxPool) Stop() {
	pool.Flush()

	txplogger.Infoln("Stopped")
}
<|endoftext|>


<commit_before>package boardgame

import (
	"container/heap"
	"time"
)

type Timer struct {
	//Id will be an opaque identifier that is used to keep track of the
	//corresponding underlying Timer object in the game engine. It is not
	//meaningful to inspect yourself and should not be modified.
	Id       int
	statePtr *state
}

func NewTimer() *Timer {
	return &Timer{}
}

func (t *Timer) Copy() *Timer {
	var result Timer
	result = *t
	return &result
}

func (t *Timer) MarshalJSON() ([]byte, error) {
	obj := map[string]interface{}{
		"Id":       t.Id,
		"TimeLeft": t.TimeLeft(),
	}

	return DefaultMarshalJSON(obj)
}

//Active returns true if the timer is active and counting down.
func (t *Timer) Active() bool {
	return t.Id == 0
}

//TimeLeft returns the number of nanoseconds left until this timer fires.
func (t *Timer) TimeLeft() int {
	if !t.Active() {
		return 0
	}

	return t.statePtr.game.manager.timers.GetTimerRemaining(t.Id)
}

//Start starts the timer. After nanoseconds nanoseconds have passed, the Move
//will be proposed via proposeMove.
func (t *Timer) Start(nanoseconds int, move Move) {
	game := t.statePtr.game
	manager := game.manager

	t.Id = manager.timers.RegisterTimer(nanoseconds, game, move)
}

//Cancel cancels an active timer. If the timer is not active, it has no
//effect. Returns true if the timer was active and canceled, false if the
//timer was not active.
func (t *Timer) Cancel() bool {
	if !t.Active() {
		return false
	}
	manager := t.statePtr.game.manager

	manager.timers.CancelTimer(t.Id)

	t.Id = 0

	return true
}

type timerRecord struct {
	id       int
	index    int
	fireTime time.Time
	game     *Game
	move     Move
}

func (t *timerRecord) TimeRemaining() int {
	duration := t.fireTime.Sub(time.Now())

	if duration < 0 {
		duration = 0
	}

	return int(duration)
}

type timerQueue []*timerRecord

type timerManager struct {
	nextId      int
	records     timerQueue
	recordsById map[int]*timerRecord
}

func newTimerManager() *timerManager {
	return &timerManager{
		nextId:      0,
		records:     make(timerQueue, 0),
		recordsById: make(map[int]*timerRecord),
	}
}

func (t *timerManager) RegisterTimer(nanoseconds int, game *Game, move Move) int {
	record := &timerRecord{
		id:       t.nextId,
		index:    -1,
		fireTime: time.Now().Add(time.Duration(nanoseconds)),
		game:     game,
		move:     move,
	}
	t.nextId++

	t.recordsById[record.id] = record

	heap.Push(&t.records, record)

	return record.id
}

func (t *timerManager) GetTimerRemaining(id int) int {
	record := t.recordsById[id]

	if record == nil {
		return 0
	}

	return record.TimeRemaining()
}

func (t *timerManager) CancelTimer(id int) {
	record := t.recordsById[id]

	if record == nil {
		return
	}

	heap.Remove(&t.records, record.index)

	record.index = -1

	delete(t.recordsById, record.id)

}

//Should be called regularly by the manager to tell this to check and see if
//any timers have fired, and execute them if so.
func (t *timerManager) Tick() {
	for t.nextTimerFired() {
		record := t.popNext()
		if record == nil {
			continue
		}
		if err := <-record.game.ProposeMove(record.move); err != nil {
			//TODO: log the error or something
			panic(err)
		}
	}
}

//Whether the next timer in the queue is already fired
func (t *timerManager) nextTimerFired() bool {
	if len(t.records) == 0 {
		return false
	}

	record := t.records[0]

	return record.TimeRemaining() <= 0
}

func (t *timerManager) popNext() *timerRecord {
	if !t.nextTimerFired() {
		return nil
	}

	x := heap.Pop(&t.records)

	record := x.(*timerRecord)

	delete(t.recordsById, record.id)

	return record
}

func (t timerQueue) Len() int {
	return len(t)
}

func (t timerQueue) Less(i, j int) bool {
	return t[i].fireTime.Sub(t[j].fireTime) < 0
}

func (t timerQueue) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
	t[i].index = i
	t[j].index = j
}

//DO NOT USE THIS DIRECTLY. Use heap.Push(t)
func (t *timerQueue) Push(x interface{}) {
	n := len(*t)
	item := x.(*timerRecord)
	item.index = n
	*t = append(*t, item)
}

//DO NOT USE THIS DIRECTLY. Use heap.Pop()
func (t *timerQueue) Pop() interface{} {
	old := *t
	n := len(old)
	item := old[n-1]
	item.index = -1
	*t = old[0 : n-1]
	return item
}
<commit_msg>Timers instead of using int number of nanoseconds, uses time.Duration, which is more precise and more clear. Part of #178.<commit_after>package boardgame

import (
	"container/heap"
	"time"
)

type Timer struct {
	//Id will be an opaque identifier that is used to keep track of the
	//corresponding underlying Timer object in the game engine. It is not
	//meaningful to inspect yourself and should not be modified.
	Id       int
	statePtr *state
}

func NewTimer() *Timer {
	return &Timer{}
}

func (t *Timer) Copy() *Timer {
	var result Timer
	result = *t
	return &result
}

func (t *Timer) MarshalJSON() ([]byte, error) {
	obj := map[string]interface{}{
		"Id":       t.Id,
		"TimeLeft": t.TimeLeft(),
	}

	return DefaultMarshalJSON(obj)
}

//Active returns true if the timer is active and counting down.
func (t *Timer) Active() bool {
	return t.Id == 0
}

//TimeLeft returns the number of nanoseconds left until this timer fires.
func (t *Timer) TimeLeft() time.Duration {
	if !t.Active() {
		return 0
	}

	return t.statePtr.game.manager.timers.GetTimerRemaining(t.Id)
}

//Start starts the timer. After duration has passed, the Move
//will be proposed via proposeMove.
func (t *Timer) Start(duration time.Duration, move Move) {
	game := t.statePtr.game
	manager := game.manager

	t.Id = manager.timers.RegisterTimer(duration, game, move)
}

//Cancel cancels an active timer. If the timer is not active, it has no
//effect. Returns true if the timer was active and canceled, false if the
//timer was not active.
func (t *Timer) Cancel() bool {
	if !t.Active() {
		return false
	}
	manager := t.statePtr.game.manager

	manager.timers.CancelTimer(t.Id)

	t.Id = 0

	return true
}

type timerRecord struct {
	id       int
	index    int
	fireTime time.Time
	game     *Game
	move     Move
}

func (t *timerRecord) TimeRemaining() time.Duration {
	duration := t.fireTime.Sub(time.Now())

	if duration < 0 {
		duration = 0
	}

	return duration
}

type timerQueue []*timerRecord

type timerManager struct {
	nextId      int
	records     timerQueue
	recordsById map[int]*timerRecord
}

func newTimerManager() *timerManager {
	return &timerManager{
		nextId:      0,
		records:     make(timerQueue, 0),
		recordsById: make(map[int]*timerRecord),
	}
}

func (t *timerManager) RegisterTimer(duration time.Duration, game *Game, move Move) int {
	record := &timerRecord{
		id:       t.nextId,
		index:    -1,
		fireTime: time.Now().Add(duration),
		game:     game,
		move:     move,
	}
	t.nextId++

	t.recordsById[record.id] = record

	heap.Push(&t.records, record)

	return record.id
}

func (t *timerManager) GetTimerRemaining(id int) time.Duration {
	record := t.recordsById[id]

	if record == nil {
		return 0
	}

	return record.TimeRemaining()
}

func (t *timerManager) CancelTimer(id int) {
	record := t.recordsById[id]

	if record == nil {
		return
	}

	heap.Remove(&t.records, record.index)

	record.index = -1

	delete(t.recordsById, record.id)

}

//Should be called regularly by the manager to tell this to check and see if
//any timers have fired, and execute them if so.
func (t *timerManager) Tick() {
	for t.nextTimerFired() {
		record := t.popNext()
		if record == nil {
			continue
		}
		if err := <-record.game.ProposeMove(record.move); err != nil {
			//TODO: log the error or something
			panic(err)
		}
	}
}

//Whether the next timer in the queue is already fired
func (t *timerManager) nextTimerFired() bool {
	if len(t.records) == 0 {
		return false
	}

	record := t.records[0]

	return record.TimeRemaining() <= 0
}

func (t *timerManager) popNext() *timerRecord {
	if !t.nextTimerFired() {
		return nil
	}

	x := heap.Pop(&t.records)

	record := x.(*timerRecord)

	delete(t.recordsById, record.id)

	return record
}

func (t timerQueue) Len() int {
	return len(t)
}

func (t timerQueue) Less(i, j int) bool {
	return t[i].fireTime.Sub(t[j].fireTime) < 0
}

func (t timerQueue) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
	t[i].index = i
	t[j].index = j
}

//DO NOT USE THIS DIRECTLY. Use heap.Push(t)
func (t *timerQueue) Push(x interface{}) {
	n := len(*t)
	item := x.(*timerRecord)
	item.index = n
	*t = append(*t, item)
}

//DO NOT USE THIS DIRECTLY. Use heap.Pop()
func (t *timerQueue) Pop() interface{} {
	old := *t
	n := len(old)
	item := old[n-1]
	item.index = -1
	*t = old[0 : n-1]
	return item
}
<|endoftext|>


<commit_before>package times

import (
	"errors"
	"time"
)

type Times struct {
	time.Time
	timezone string
	location *time.Location
}

// This will return an instance of Times the current time localized to UTC
func Now() Times {
	timezone := "UTC"
	location, _ := time.LoadLocation(timezone)
	time := time.Now().UTC()
	return Times{time, timezone, location}
}

// This will localixe
func (t Times) Localize(timezone string) (Times, error) {
	location, err := time.LoadLocation(timezone)

	if err != nil {
		return nil, errors.New("The provided timezone isn't a valid time.Location", timezone)
	}
	time := t.In(location)
	return Times(time, timezone, location), err

}
<commit_msg>switching function name to a more sane number<commit_after>package times

import (
	"errors"
	"time"
)

type Times struct {
	time.Time
	timezone string
	location *time.Location
}

// This will return an instance of Times the current time localized to UTC
func Now() Times {
	timezone := "UTC"
	location, _ := time.LoadLocation(timezone)
	time := time.Now().UTC()
	return Times{time, timezone, location}
}

// This will localixe
func (t Times) Normalize(timezone string) (Times, error) {
	location, err := time.LoadLocation(timezone)

	if err != nil {
		return nil, errors.New("The provided timezone isn't a valid time.Location", timezone)
	}
	time := t.In(location)
	return Times(time, timezone, location), err

}
<|endoftext|>


<commit_before>package jira

// Issue Types -----------------------------------------------------------------

const (
	issueTypeIdBug              = "1"
	issueTypeIdTechnicalTask    = "10401"
	issueTypeIdTechnicalSubTask = "10002"
	issueTypeIdUserStory        = "10500"
)

var codingIssueTypeIds = []string{
	issueTypeIdBug,
	issueTypeIdTechnicalTask,
	issueTypeIdTechnicalSubTask,
	issueTypeIdUserStory,
}

// States --------------------------------------------------------------------

const (
	stateIdApproved         = "10000"
	stateIdBeingImplemented = "10400"
	stateIdImplemented      = "10401"
)

var startableStateIds = []string{
	stateIdApproved,
}

var inDevelopmentStateIds = []string{
	stateIdBeingImplemented,
	stateIdImplemented,
}

// Transitions -----------------------------------------------------------------

const (
	transitionIdStartImplementing = "321"
)
<commit_msg>modules/jira: Update workflow IDs, again<commit_after>package jira

// Issue Types -----------------------------------------------------------------

const (
	issueTypeIdBug           = "1"
	issueTypeIdCodingTask    = "10508"
	issueTypeIdCodingSubTask = "10501"
	issueTypeIdUserStory     = "10500"
)

var codingIssueTypeIds = []string{
	issueTypeIdBug,
	issueTypeIdCodingTask,
	issueTypeIdCodingSubTask,
	issueTypeIdUserStory,
}

// States --------------------------------------------------------------------

const (
	stateIdApproved         = "10000"
	stateIdBeingImplemented = "10400"
	stateIdImplemented      = "10401"
)

var startableStateIds = []string{
	stateIdApproved,
}

var inDevelopmentStateIds = []string{
	stateIdBeingImplemented,
	stateIdImplemented,
}

// Transitions -----------------------------------------------------------------

const (
	transitionIdStartImplementing = "321"
)
<|endoftext|>


<commit_before>package openstack

import (
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
)

// NetworkCreateOpts represents the attributes used when creating a new network.
type NetworkCreateOpts struct {
	networks.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToNetworkCreateMap casts a CreateOpts struct to a map.
// It overrides networks.ToNetworkCreateMap to add the ValueSpecs field.
func (opts NetworkCreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
	return BuildRequest(opts, "network")
}

// RouterCreateOpts represents the attributes used when creating a new router.
type RouterCreateOpts struct {
	routers.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToRouterCreateMap casts a CreateOpts struct to a map.
// It overrides routers.ToRouterCreateMap to add the ValueSpecs field.
func (opts RouterCreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
	return BuildRequest(opts, "router")
}

// SubnetCreateOpts represents the attributes used when creating a new subnet.
type SubnetCreateOpts struct {
	subnets.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToSubnetCreateMap casts a CreateOpts struct to a map.
// It overrides subnets.ToSubnetCreateMap to add the ValueSpecs field.
func (opts SubnetCreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
	return BuildRequest(opts, "subnet")
}
<commit_msg>provider/openstack: gophercloud migration: Update openstack_networking_subnet_v2 to correctly handle Gateway IP<commit_after>package openstack

import (
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
)

// NetworkCreateOpts represents the attributes used when creating a new network.
type NetworkCreateOpts struct {
	networks.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToNetworkCreateMap casts a CreateOpts struct to a map.
// It overrides networks.ToNetworkCreateMap to add the ValueSpecs field.
func (opts NetworkCreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
	return BuildRequest(opts, "network")
}

// RouterCreateOpts represents the attributes used when creating a new router.
type RouterCreateOpts struct {
	routers.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToRouterCreateMap casts a CreateOpts struct to a map.
// It overrides routers.ToRouterCreateMap to add the ValueSpecs field.
func (opts RouterCreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
	return BuildRequest(opts, "router")
}

// SubnetCreateOpts represents the attributes used when creating a new subnet.
type SubnetCreateOpts struct {
	subnets.CreateOpts
	ValueSpecs map[string]string `json:"value_specs,omitempty"`
}

// ToSubnetCreateMap casts a CreateOpts struct to a map.
// It overrides subnets.ToSubnetCreateMap to add the ValueSpecs field.
func (opts SubnetCreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
	b, err := BuildRequest(opts, "subnet")
	if err != nil {
		return nil, err
	}

	if m := b["subnet"].(map[string]interface{}); m["gateway_ip"] == "" {
		m["gateway_ip"] = nil
	}

	return b, nil
}
<|endoftext|>


<commit_before>package gocsv

import (
	"encoding"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// --------------------------------------------------------------------------
// Conversion interfaces

// TypeMarshaller is implemented by any value that has a MarshalCSV method
// This converter is used to convert the value to it string representation
type TypeMarshaller interface {
	MarshalCSV() (string, error)
}

// Stringer is implemented by any value that has a String method
// This converter is used to convert the value to it string representation
// This converter will be used if your value does not implement TypeMarshaller
type Stringer interface {
	String() string
}

// TypeUnmarshaller is implemented by any value that has an UnmarshalCSV method
// This converter is used to convert a string to your value representation of that string
type TypeUnmarshaller interface {
	UnmarshalCSV(string) error
}

var (
	stringerType        = reflect.TypeOf((*Stringer)(nil)).Elem()
	marshallerType      = reflect.TypeOf((*TypeMarshaller)(nil)).Elem()
	unMarshallerType    = reflect.TypeOf((*TypeUnmarshaller)(nil)).Elem()
	textMarshalerType   = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
	textUnMarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)

// --------------------------------------------------------------------------
// Conversion helpers

func toString(in interface{}) (string, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		return inValue.String(), nil
	case reflect.Bool:
		b := inValue.Bool()
		if b {
			return "true", nil
		}
		return "false", nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return fmt.Sprintf("%v", inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return fmt.Sprintf("%v", inValue.Uint()), nil
	case reflect.Float32:
		return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 32), nil
	case reflect.Float64:
		return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 64), nil
	}
	return "", fmt.Errorf("No known conversion from " + inValue.Type().String() + " to string")
}

func toBool(in interface{}) (bool, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := inValue.String()
		switch s {
		case "yes":
			return true, nil
		case "no", "":
			return false, nil
		default:
			return strconv.ParseBool(s)
		}
	case reflect.Bool:
		return inValue.Bool(), nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i := inValue.Int()
		if i != 0 {
			return true, nil
		}
		return false, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		i := inValue.Uint()
		if i != 0 {
			return true, nil
		}
		return false, nil
	case reflect.Float32, reflect.Float64:
		f := inValue.Float()
		if f != 0 {
			return true, nil
		}
		return false, nil
	}
	return false, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to bool")
}

func toInt(in interface{}) (int64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}
		return strconv.ParseInt(s, 0, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return inValue.Int(), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int64(inValue.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return int64(inValue.Float()), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to int")
}

func toUint(in interface{}) (uint64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}

		// support the float input
		if strings.Contains(s, ".") {
			f, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return 0, err
			}
			return uint64(f), nil
		}
		return strconv.ParseUint(s, 0, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return uint64(inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return inValue.Uint(), nil
	case reflect.Float32, reflect.Float64:
		return uint64(inValue.Float()), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to uint")
}

func toFloat(in interface{}) (float64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}
		return strconv.ParseFloat(s, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return float64(inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return float64(inValue.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return inValue.Float(), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to float")
}

func setField(field reflect.Value, value string) error {
	switch field.Kind() {
	case reflect.String:
		s, err := toString(value)
		if err != nil {
			return err
		}
		field.SetString(s)
	case reflect.Bool:
		b, err := toBool(value)
		if err != nil {
			return err
		}
		field.SetBool(b)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i, err := toInt(value)
		if err != nil {
			return err
		}
		field.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		ui, err := toUint(value)
		if err != nil {
			return err
		}
		field.SetUint(ui)
	case reflect.Float32, reflect.Float64:
		f, err := toFloat(value)
		if err != nil {
			return err
		}
		field.SetFloat(f)
	default:
		return unmarshall(field, value)
	}
	return nil
}

func getFieldAsString(field reflect.Value) (str string, err error) {
	switch field.Kind() {
	case reflect.Interface:
	case reflect.Ptr:
		if field.IsNil() {
			return "", nil
		}
		return getFieldAsString(field.Elem())
	case reflect.String:
		return field.String(), nil
	case reflect.Bool:
		str, err = toString(field.Bool())
		if err != nil {
			return str, err
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		str, err = toString(field.Int())
		if err != nil {
			return str, err
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		str, err = toString(field.Uint())
		if err != nil {
			return str, err
		}
	case reflect.Float32:
		str, err = toString(float32(field.Float()))
		if err != nil {
			return str, err
		}
	case reflect.Float64:
		str, err = toString(field.Float())
		if err != nil {
			return str, err
		}
	default:
		return marshall(field)
	}
	return str, nil
}

// --------------------------------------------------------------------------
// Un/serializations helpers

func unmarshall(field reflect.Value, value string) error {
	dupField := field
	unMarshallIt := func(finalField reflect.Value) error {
		if finalField.CanInterface() && finalField.Type().Implements(unMarshallerType) {
			if err := finalField.Interface().(TypeUnmarshaller).UnmarshalCSV(value); err != nil {
				return err
			}
			return nil
		} else if finalField.CanInterface() && finalField.Type().Implements(textUnMarshalerType) { // Otherwise try to use TextMarshaller
			if err := finalField.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(value)); err != nil {
				return err
			}
		}

		return fmt.Errorf("No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implements TypeUnmarshaller")
	}
	for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
		if dupField.IsNil() {
			dupField = reflect.New(field.Type().Elem())
			field.Set(dupField)
			return unMarshallIt(dupField)
			break
		}
		dupField = dupField.Elem()
	}
	if dupField.CanAddr() {
		return unMarshallIt(dupField.Addr())
	}
	return fmt.Errorf("No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implements TypeUnmarshaller")
}

func marshall(field reflect.Value) (value string, err error) {
	dupField := field
	marshallIt := func(finalField reflect.Value) (string, error) {
		if finalField.CanInterface() && finalField.Type().Implements(marshallerType) { // Use TypeMarshaller when possible
			return finalField.Interface().(TypeMarshaller).MarshalCSV()
		} else if finalField.CanInterface() && finalField.Type().Implements(stringerType) { // Otherwise try to use Stringer
			return finalField.Interface().(Stringer).String(), nil
		} else if finalField.CanInterface() && finalField.Type().Implements(textMarshalerType) { // Otherwise try to use TextMarshaller
			text, err := finalField.Interface().(encoding.TextMarshaler).MarshalText()
			return string(text), err
		}

		return value, fmt.Errorf("No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implements TypeMarshaller nor Stringer")
	}
	for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
		if dupField.IsNil() {
			return value, nil
		}
		dupField = dupField.Elem()
	}
	if dupField.CanAddr() {
		return marshallIt(dupField.Addr())
	}
	return value, fmt.Errorf("No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implements TypeMarshaller nor Stringer")
}
<commit_msg>Type switch using reflection for real type instead of basic type (Kind) for marshaling<commit_after>package gocsv

import (
	"encoding"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// --------------------------------------------------------------------------
// Conversion interfaces

// TypeMarshaller is implemented by any value that has a MarshalCSV method
// This converter is used to convert the value to it string representation
type TypeMarshaller interface {
	MarshalCSV() (string, error)
}

// Stringer is implemented by any value that has a String method
// This converter is used to convert the value to it string representation
// This converter will be used if your value does not implement TypeMarshaller
type Stringer interface {
	String() string
}

// TypeUnmarshaller is implemented by any value that has an UnmarshalCSV method
// This converter is used to convert a string to your value representation of that string
type TypeUnmarshaller interface {
	UnmarshalCSV(string) error
}

var (
	stringerType        = reflect.TypeOf((*Stringer)(nil)).Elem()
	marshallerType      = reflect.TypeOf((*TypeMarshaller)(nil)).Elem()
	unMarshallerType    = reflect.TypeOf((*TypeUnmarshaller)(nil)).Elem()
	textMarshalerType   = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
	textUnMarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)

// --------------------------------------------------------------------------
// Conversion helpers

func toString(in interface{}) (string, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		return inValue.String(), nil
	case reflect.Bool:
		b := inValue.Bool()
		if b {
			return "true", nil
		}
		return "false", nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return fmt.Sprintf("%v", inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return fmt.Sprintf("%v", inValue.Uint()), nil
	case reflect.Float32:
		return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 32), nil
	case reflect.Float64:
		return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 64), nil
	}
	return "", fmt.Errorf("No known conversion from " + inValue.Type().String() + " to string")
}

func toBool(in interface{}) (bool, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := inValue.String()
		switch s {
		case "yes":
			return true, nil
		case "no", "":
			return false, nil
		default:
			return strconv.ParseBool(s)
		}
	case reflect.Bool:
		return inValue.Bool(), nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i := inValue.Int()
		if i != 0 {
			return true, nil
		}
		return false, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		i := inValue.Uint()
		if i != 0 {
			return true, nil
		}
		return false, nil
	case reflect.Float32, reflect.Float64:
		f := inValue.Float()
		if f != 0 {
			return true, nil
		}
		return false, nil
	}
	return false, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to bool")
}

func toInt(in interface{}) (int64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}
		return strconv.ParseInt(s, 0, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return inValue.Int(), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int64(inValue.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return int64(inValue.Float()), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to int")
}

func toUint(in interface{}) (uint64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}

		// support the float input
		if strings.Contains(s, ".") {
			f, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return 0, err
			}
			return uint64(f), nil
		}
		return strconv.ParseUint(s, 0, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return uint64(inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return inValue.Uint(), nil
	case reflect.Float32, reflect.Float64:
		return uint64(inValue.Float()), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to uint")
}

func toFloat(in interface{}) (float64, error) {
	inValue := reflect.ValueOf(in)

	switch inValue.Kind() {
	case reflect.String:
		s := strings.TrimSpace(inValue.String())
		if s == "" {
			return 0, nil
		}
		return strconv.ParseFloat(s, 64)
	case reflect.Bool:
		if inValue.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return float64(inValue.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return float64(inValue.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return inValue.Float(), nil
	}
	return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to float")
}

func setField(field reflect.Value, value string) error {
	// TODO: Same method for type switching in other functions
	switch field.Interface().(type) {
	case string:
		s, err := toString(value)
		if err != nil {
			return err
		}
		field.SetString(s)
	case bool:
		b, err := toBool(value)
		if err != nil {
			return err
		}
		field.SetBool(b)
	case int, int8, int16, int32, int64:
		i, err := toInt(value)
		if err != nil {
			return err
		}
		field.SetInt(i)
	case uint, uint8, uint16, uint32, uint64:
		ui, err := toUint(value)
		if err != nil {
			return err
		}
		field.SetUint(ui)
	case float32, float64:
		f, err := toFloat(value)
		if err != nil {
			return err
		}
		field.SetFloat(f)
	default:
		return unmarshall(field, value)
	}
	return nil
}

func getFieldAsString(field reflect.Value) (str string, err error) {
	switch field.Kind() {
	case reflect.Interface:
	case reflect.Ptr:
		if field.IsNil() {
			return "", nil
		}
		return getFieldAsString(field.Elem())
	case reflect.String:
		return field.String(), nil
	case reflect.Bool:
		str, err = toString(field.Bool())
		if err != nil {
			return str, err
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		str, err = toString(field.Int())
		if err != nil {
			return str, err
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		str, err = toString(field.Uint())
		if err != nil {
			return str, err
		}
	case reflect.Float32:
		str, err = toString(float32(field.Float()))
		if err != nil {
			return str, err
		}
	case reflect.Float64:
		str, err = toString(field.Float())
		if err != nil {
			return str, err
		}
	default:
		return marshall(field)
	}
	return str, nil
}

// --------------------------------------------------------------------------
// Un/serializations helpers

func unmarshall(field reflect.Value, value string) error {
	dupField := field
	unMarshallIt := func(finalField reflect.Value) error {
		if finalField.CanInterface() && finalField.Type().Implements(unMarshallerType) {
			if err := finalField.Interface().(TypeUnmarshaller).UnmarshalCSV(value); err != nil {
				return err
			}
			return nil
		} else if finalField.CanInterface() && finalField.Type().Implements(textUnMarshalerType) { // Otherwise try to use TextMarshaller
			if err := finalField.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(value)); err != nil {
				return err
			}
		}

		return fmt.Errorf("No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implements TypeUnmarshaller")
	}
	for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
		if dupField.IsNil() {
			dupField = reflect.New(field.Type().Elem())
			field.Set(dupField)
			return unMarshallIt(dupField)
			break
		}
		dupField = dupField.Elem()
	}
	if dupField.CanAddr() {
		return unMarshallIt(dupField.Addr())
	}
	return fmt.Errorf("No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implements TypeUnmarshaller")
}

func marshall(field reflect.Value) (value string, err error) {
	dupField := field
	marshallIt := func(finalField reflect.Value) (string, error) {
		if finalField.CanInterface() && finalField.Type().Implements(marshallerType) { // Use TypeMarshaller when possible
			return finalField.Interface().(TypeMarshaller).MarshalCSV()
		} else if finalField.CanInterface() && finalField.Type().Implements(stringerType) { // Otherwise try to use Stringer
			return finalField.Interface().(Stringer).String(), nil
		} else if finalField.CanInterface() && finalField.Type().Implements(textMarshalerType) { // Otherwise try to use TextMarshaller
			text, err := finalField.Interface().(encoding.TextMarshaler).MarshalText()
			return string(text), err
		}

		return value, fmt.Errorf("No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implements TypeMarshaller nor Stringer")
	}
	for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
		if dupField.IsNil() {
			return value, nil
		}
		dupField = dupField.Elem()
	}
	if dupField.CanAddr() {
		return marshallIt(dupField.Addr())
	}
	return value, fmt.Errorf("No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implements TypeMarshaller nor Stringer")
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd 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 typeurl

import (
	"encoding/json"
	"errors"
	"fmt"
	"path"
	"reflect"
	"sync"

	gogoproto "github.com/gogo/protobuf/proto"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoregistry"
)

var (
	mu       sync.RWMutex
	registry = make(map[reflect.Type]string)
)

// Definitions of common error types used throughout typeurl.
//
// These error types are used with errors.Wrap and errors.Wrapf to add context
// to an error.
//
// To detect an error class, use errors.Is() functions to tell whether an
// error is of this type.

var (
	ErrNotFound = errors.New("not found")
)

type Any interface {
	GetTypeUrl() string
	GetValue() []byte
}

type anyType struct {
	typeURL string
	value   []byte
}

func (a *anyType) GetTypeUrl() string {
	if a == nil {
		return ""
	}
	return a.typeURL
}

func (a *anyType) GetValue() []byte {
	if a == nil {
		return nil
	}
	return a.value
}

// Register a type with a base URL for JSON marshaling. When the MarshalAny and
// UnmarshalAny functions are called they will treat the Any type value as JSON.
// To use protocol buffers for handling the Any value the proto.Register
// function should be used instead of this function.
func Register(v interface{}, args ...string) {
	var (
		t = tryDereference(v)
		p = path.Join(args...)
	)
	mu.Lock()
	defer mu.Unlock()
	if et, ok := registry[t]; ok {
		if et != p {
			panic(fmt.Errorf("type registered with alternate path %q != %q", et, p))
		}
		return
	}
	registry[t] = p
}

// TypeURL returns the type url for a registered type.
func TypeURL(v interface{}) (string, error) {
	mu.RLock()
	u, ok := registry[tryDereference(v)]
	mu.RUnlock()
	if !ok {
		switch t := v.(type) {
		case proto.Message:
			return string(t.ProtoReflect().Descriptor().FullName()), nil
		case gogoproto.Message:
			return gogoproto.MessageName(t), nil
		default:
			return "", fmt.Errorf("type %s: %w", reflect.TypeOf(v), ErrNotFound)
		}
	}
	return u, nil
}

// Is returns true if the type of the Any is the same as v.
func Is(any Any, v interface{}) bool {
	// call to check that v is a pointer
	tryDereference(v)
	url, err := TypeURL(v)
	if err != nil {
		return false
	}
	return any.GetTypeUrl() == url
}

// MarshalAny marshals the value v into an any with the correct TypeUrl.
// If the provided object is already a proto.Any message, then it will be
// returned verbatim. If it is of type proto.Message, it will be marshaled as a
// protocol buffer. Otherwise, the object will be marshaled to json.
func MarshalAny(v interface{}) (Any, error) {
	var marshal func(v interface{}) ([]byte, error)
	switch t := v.(type) {
	case Any:
		// avoid reserializing the type if we have an any.
		return t, nil
	case proto.Message:
		marshal = func(v interface{}) ([]byte, error) {
			return proto.Marshal(t)
		}
	case gogoproto.Message:
		marshal = func(v interface{}) ([]byte, error) {
			return gogoproto.Marshal(t)
		}
	default:
		marshal = json.Marshal
	}

	url, err := TypeURL(v)
	if err != nil {
		return nil, err
	}

	data, err := marshal(v)
	if err != nil {
		return nil, err
	}
	return &anyType{
		typeURL: url,
		value:   data,
	}, nil
}

// UnmarshalAny unmarshals the any type into a concrete type.
func UnmarshalAny(any Any) (interface{}, error) {
	return UnmarshalByTypeURL(any.GetTypeUrl(), any.GetValue())
}

// UnmarshalByTypeURL unmarshals the given type and value to into a concrete type.
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
	return unmarshal(typeURL, value, nil)
}

// UnmarshalTo unmarshals the any type into a concrete type passed in the out
// argument. It is identical to UnmarshalAny, but lets clients provide a
// destination type through the out argument.
func UnmarshalTo(any Any, out interface{}) error {
	return UnmarshalToByTypeURL(any.GetTypeUrl(), any.GetValue(), out)
}

// UnmarshalToByTypeURL unmarshals the given type and value into a concrete type passed
// in the out argument. It is identical to UnmarshalByTypeURL, but lets clients
// provide a destination type through the out argument.
func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
	_, err := unmarshal(typeURL, value, out)
	return err
}

func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
	if value == nil {
		return nil, nil
	}

	t, err := getTypeByUrl(typeURL)
	if err != nil {
		return nil, err
	}

	if v == nil {
		v = reflect.New(t.t).Interface()
	} else {
		// Validate interface type provided by client
		vURL, err := TypeURL(v)
		if err != nil {
			return nil, err
		}
		if typeURL != vURL {
			return nil, fmt.Errorf("can't unmarshal type %q to output %q", typeURL, vURL)
		}
	}

	if t.isProto {
		switch t := v.(type) {
		case proto.Message:
			err = proto.Unmarshal(value, t)
		case gogoproto.Message:
			err = gogoproto.Unmarshal(value, t)
		}
	} else {
		err = json.Unmarshal(value, v)
	}

	return v, err
}

type urlType struct {
	t       reflect.Type
	isProto bool
}

func getTypeByUrl(url string) (urlType, error) {
	mu.RLock()
	for t, u := range registry {
		if u == url {
			mu.RUnlock()
			return urlType{
				t: t,
			}, nil
		}
	}
	mu.RUnlock()
	// fallback to proto registry
	t := gogoproto.MessageType(url)
	if t != nil {
		return urlType{
			// get the underlying Elem because proto returns a pointer to the type
			t:       t.Elem(),
			isProto: true,
		}, nil
	}
	mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
	if err != nil {
		return urlType{}, fmt.Errorf("type with url %s: %w", url, ErrNotFound)
	}
	empty := mt.New().Interface()
	return urlType{t: reflect.TypeOf(empty).Elem(), isProto: true}, nil
}

func tryDereference(v interface{}) reflect.Type {
	t := reflect.TypeOf(v)
	if t.Kind() == reflect.Ptr {
		// require check of pointer but dereference to register
		return t.Elem()
	}
	panic("v is not a pointer to a type")
}
<commit_msg>Document exported types<commit_after>/*
   Copyright The containerd 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 typeurl

import (
	"encoding/json"
	"errors"
	"fmt"
	"path"
	"reflect"
	"sync"

	gogoproto "github.com/gogo/protobuf/proto"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoregistry"
)

var (
	mu       sync.RWMutex
	registry = make(map[reflect.Type]string)
)

// Definitions of common error types used throughout typeurl.
//
// These error types are used with errors.Wrap and errors.Wrapf to add context
// to an error.
//
// To detect an error class, use errors.Is() functions to tell whether an
// error is of this type.

var (
	ErrNotFound = errors.New("not found")
)

// Any contains an arbitrary protcol buffer message along with its type.
//
// While there is google.golang.org/protobuf/types/known/anypb.Any,
// we'd like to have our own to hide the underlying protocol buffer
// implementations from containerd clients.
//
// https://developers.google.com/protocol-buffers/docs/proto3#any
type Any interface {
	// GetTypeUrl returns a URL/resource name that uniquely identifies
	// the type of the serialized protocol buffer message.
	GetTypeUrl() string

	// GetValue returns a valid serialized protocol buffer of the type that
	// GetTypeUrl() indicates.
	GetValue() []byte
}

type anyType struct {
	typeURL string
	value   []byte
}

func (a *anyType) GetTypeUrl() string {
	if a == nil {
		return ""
	}
	return a.typeURL
}

func (a *anyType) GetValue() []byte {
	if a == nil {
		return nil
	}
	return a.value
}

// Register a type with a base URL for JSON marshaling. When the MarshalAny and
// UnmarshalAny functions are called they will treat the Any type value as JSON.
// To use protocol buffers for handling the Any value the proto.Register
// function should be used instead of this function.
func Register(v interface{}, args ...string) {
	var (
		t = tryDereference(v)
		p = path.Join(args...)
	)
	mu.Lock()
	defer mu.Unlock()
	if et, ok := registry[t]; ok {
		if et != p {
			panic(fmt.Errorf("type registered with alternate path %q != %q", et, p))
		}
		return
	}
	registry[t] = p
}

// TypeURL returns the type url for a registered type.
func TypeURL(v interface{}) (string, error) {
	mu.RLock()
	u, ok := registry[tryDereference(v)]
	mu.RUnlock()
	if !ok {
		switch t := v.(type) {
		case proto.Message:
			return string(t.ProtoReflect().Descriptor().FullName()), nil
		case gogoproto.Message:
			return gogoproto.MessageName(t), nil
		default:
			return "", fmt.Errorf("type %s: %w", reflect.TypeOf(v), ErrNotFound)
		}
	}
	return u, nil
}

// Is returns true if the type of the Any is the same as v.
func Is(any Any, v interface{}) bool {
	// call to check that v is a pointer
	tryDereference(v)
	url, err := TypeURL(v)
	if err != nil {
		return false
	}
	return any.GetTypeUrl() == url
}

// MarshalAny marshals the value v into an any with the correct TypeUrl.
// If the provided object is already a proto.Any message, then it will be
// returned verbatim. If it is of type proto.Message, it will be marshaled as a
// protocol buffer. Otherwise, the object will be marshaled to json.
func MarshalAny(v interface{}) (Any, error) {
	var marshal func(v interface{}) ([]byte, error)
	switch t := v.(type) {
	case Any:
		// avoid reserializing the type if we have an any.
		return t, nil
	case proto.Message:
		marshal = func(v interface{}) ([]byte, error) {
			return proto.Marshal(t)
		}
	case gogoproto.Message:
		marshal = func(v interface{}) ([]byte, error) {
			return gogoproto.Marshal(t)
		}
	default:
		marshal = json.Marshal
	}

	url, err := TypeURL(v)
	if err != nil {
		return nil, err
	}

	data, err := marshal(v)
	if err != nil {
		return nil, err
	}
	return &anyType{
		typeURL: url,
		value:   data,
	}, nil
}

// UnmarshalAny unmarshals the any type into a concrete type.
func UnmarshalAny(any Any) (interface{}, error) {
	return UnmarshalByTypeURL(any.GetTypeUrl(), any.GetValue())
}

// UnmarshalByTypeURL unmarshals the given type and value to into a concrete type.
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
	return unmarshal(typeURL, value, nil)
}

// UnmarshalTo unmarshals the any type into a concrete type passed in the out
// argument. It is identical to UnmarshalAny, but lets clients provide a
// destination type through the out argument.
func UnmarshalTo(any Any, out interface{}) error {
	return UnmarshalToByTypeURL(any.GetTypeUrl(), any.GetValue(), out)
}

// UnmarshalToByTypeURL unmarshals the given type and value into a concrete type passed
// in the out argument. It is identical to UnmarshalByTypeURL, but lets clients
// provide a destination type through the out argument.
func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
	_, err := unmarshal(typeURL, value, out)
	return err
}

func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
	if value == nil {
		return nil, nil
	}

	t, err := getTypeByUrl(typeURL)
	if err != nil {
		return nil, err
	}

	if v == nil {
		v = reflect.New(t.t).Interface()
	} else {
		// Validate interface type provided by client
		vURL, err := TypeURL(v)
		if err != nil {
			return nil, err
		}
		if typeURL != vURL {
			return nil, fmt.Errorf("can't unmarshal type %q to output %q", typeURL, vURL)
		}
	}

	if t.isProto {
		switch t := v.(type) {
		case proto.Message:
			err = proto.Unmarshal(value, t)
		case gogoproto.Message:
			err = gogoproto.Unmarshal(value, t)
		}
	} else {
		err = json.Unmarshal(value, v)
	}

	return v, err
}

type urlType struct {
	t       reflect.Type
	isProto bool
}

func getTypeByUrl(url string) (urlType, error) {
	mu.RLock()
	for t, u := range registry {
		if u == url {
			mu.RUnlock()
			return urlType{
				t: t,
			}, nil
		}
	}
	mu.RUnlock()
	// fallback to proto registry
	t := gogoproto.MessageType(url)
	if t != nil {
		return urlType{
			// get the underlying Elem because proto returns a pointer to the type
			t:       t.Elem(),
			isProto: true,
		}, nil
	}
	mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
	if err != nil {
		return urlType{}, fmt.Errorf("type with url %s: %w", url, ErrNotFound)
	}
	empty := mt.New().Interface()
	return urlType{t: reflect.TypeOf(empty).Elem(), isProto: true}, nil
}

func tryDereference(v interface{}) reflect.Type {
	t := reflect.TypeOf(v)
	if t.Kind() == reflect.Ptr {
		// require check of pointer but dereference to register
		return t.Elem()
	}
	panic("v is not a pointer to a type")
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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.

// This package is a CLI tool for generating test exposure key data.
package main

import (
	"encoding/base64"
	"encoding/json"
	"flag"
	"io/ioutil"
	"log"
	"strings"
	"time"

	"github.com/google/exposure-notifications-server/internal/util"
	verifyapi "github.com/google/exposure-notifications-server/pkg/api/v1alpha1"
	"github.com/google/exposure-notifications-server/testing/enclient"
)

var (
	url                  = flag.String("url", "http://localhost:8080", "http(s) destination to send test record")
	numKeys              = flag.Int("num", 1, "number of keys to generate -num=1")
	twice                = flag.Bool("twice", false, "send the same request twice w/ delay")
	appPackage           = flag.String("app", "com.example.android.app", "AppPackageName to use in request")
	regions              = flag.String("regions", "", "Comma separated region names")
	authorityName        = flag.String("authority", "", "Verification Authority Name")
	transmissionRiskFlag = flag.Int("transmissionRisk", -1, "Transmission risk")
	// region settings for a key are assigned randomly
	defaultRegions = [][]string{
		{"US"},
		{"US", "CA"},
		{"US", "CA", "MX"},
		{"CA"},
		{"CA", "MX"},
	}

	// verificationAuth for a key are assigned randomly
	verificationAuthorityNames = []string{
		"",
		"AAA Health",
		"BBB Labs",
	}
)

func main() {
	flag.Parse()

	exposureKeys := util.GenerateExposureKeys(*numKeys, *transmissionRiskFlag, false)
	regionIdx, err := util.RandomInt(len(defaultRegions))
	if err != nil {
		log.Printf("error getting random region: %v", err)
	}
	region := defaultRegions[regionIdx]
	if *regions != "" {
		region = strings.Split(*regions, ",")
	}

	verificationAuthorityName := *authorityName
	if verificationAuthorityName == "" {
		verificationAuthorityName, err = util.RandomArrValue(verificationAuthorityNames)
		if err != nil {
			log.Printf("could not get random verification authority: %v", err)
		}
	}

	i, err := util.RandomInt(1000)
	if err != nil {
		log.Printf("error getting random int: %v", err)
	}
	padding, err := util.RandomBytes(i + 1000)
	if err != nil {
		log.Printf("could not get random padding: %v", err)
	}

	data := verifyapi.Publish{
		Keys:                exposureKeys,
		Regions:             region,
		AppPackageName:      *appPackage,
		VerificationPayload: verificationAuthorityName,
		Padding:             base64.RawStdEncoding.EncodeToString(padding),
	}

	prettyJSON, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		log.Printf("Can't display JSON that was sent, error: %v", err)
	} else {
		log.Printf("SENDING: \n%v", string(prettyJSON))
	}

	sendRequest(data)

	if *twice {
		time.Sleep(1 * time.Second)
		log.Printf("sending the request again...")
		sendRequest(data)
	}
}

func sendRequest(data interface{}) {
	resp, err := enclient.PostRequest(*url, data)
	if err != nil {
		log.Fatalf("request failed: %v, %v", err, resp)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("unable to read http response: %v", err)
	} else {
		log.Printf("response: %v", string(body))
	}
}
<commit_msg>Fix exposure-client tool (#752)<commit_after>// Copyright 2020 Google LLC
//
// 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.

// This package is a CLI tool for generating test exposure key data.
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/google/exposure-notifications-server/internal/util"
	verifyapi "github.com/google/exposure-notifications-server/pkg/api/v1alpha1"
)

var (
	url                  = flag.String("url", "http://localhost:8080", "http(s) destination to send test record")
	numKeys              = flag.Int("num", 1, "number of keys to generate -num=1")
	twice                = flag.Bool("twice", false, "send the same request twice w/ delay")
	appPackage           = flag.String("app", "com.example.android.app", "AppPackageName to use in request")
	regions              = flag.String("regions", "", "Comma separated region names")
	authorityName        = flag.String("authority", "", "Verification Authority Name")
	transmissionRiskFlag = flag.Int("transmissionRisk", -1, "Transmission risk")
	// region settings for a key are assigned randomly
	defaultRegions = [][]string{
		{"US"},
		{"US", "CA"},
		{"US", "CA", "MX"},
		{"CA"},
		{"CA", "MX"},
	}

	// verificationAuth for a key are assigned randomly
	verificationAuthorityNames = []string{
		"",
		"AAA Health",
		"BBB Labs",
	}
)

func main() {
	if err := realMain(); err != nil {
		fmt.Printf("failed to create exposures: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("success!\n")
}

func realMain() error {
	flag.Parse()

	exposureKeys := util.GenerateExposureKeys(*numKeys, *transmissionRiskFlag, false)
	regionIdx, err := util.RandomInt(len(defaultRegions))
	if err != nil {
		return fmt.Errorf("failed to get random region: %w", err)
	}
	region := defaultRegions[regionIdx]
	if *regions != "" {
		region = strings.Split(*regions, ",")
	}

	verificationAuthorityName := *authorityName
	if verificationAuthorityName == "" {
		verificationAuthorityName, err = util.RandomArrValue(verificationAuthorityNames)
		if err != nil {
			return fmt.Errorf("failed to get random verification authority: %w", err)
		}
	}

	i, err := util.RandomInt(1000)
	if err != nil {
		return fmt.Errorf("failed to get random int: %w", err)
	}

	padding, err := util.RandomBytes(i + 1000)
	if err != nil {
		return fmt.Errorf("failed to get random padding: %w", err)
	}

	data := verifyapi.Publish{
		Keys:                exposureKeys,
		Regions:             region,
		AppPackageName:      *appPackage,
		VerificationPayload: verificationAuthorityName,
		Padding:             base64.RawStdEncoding.EncodeToString(padding),
	}

	body, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to generate JSON: %w", err)
	}
	fmt.Printf("generated json: \n%s\n", body)

	if _, err := sendRequest(bytes.NewReader(body)); err != nil {
		return fmt.Errorf("failed to send first request: %w", err)
	}

	if *twice {
		time.Sleep(1 * time.Second)
		if _, err := sendRequest(bytes.NewReader(body)); err != nil {
			return fmt.Errorf("failed to send second request: %w", err)
		}
	}

	return nil
}

func sendRequest(data io.Reader) ([]byte, error) {
	req, err := http.NewRequest("POST", *url, data)
	if err != nil {
		return nil, fmt.Errorf("failed to build request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to make request: %w", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read body: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("post request failed with status %v, body: %s", resp.StatusCode, body)
	}

	return body, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Kelsey Hightower and others. All rights reserved.
// Use of this source code is governed by the MIT License that can be found in
// the LICENSE file.

package envconfig

import (
	"encoding"
	"fmt"
	"io"
	"os"
	"reflect"
	"strconv"
	"strings"
	"text/tabwriter"
	"text/template"
)

const (
	// DefaultListFormat constant to use to display usage in a list format
	DefaultListFormat = `This application is configured via the environment. The following environment
variables can be used:
{{range .}}
{{usage_key .}}
  [description] {{usage_description .}}
  [type]        {{usage_type .}}
  [default]     {{usage_default .}}
  [required]    {{usage_required .}}{{end}}
`
	// DefaultTableFormat constant to use to display usage in a tabluar format
	DefaultTableFormat = `This application is configured via the environment. The following environment
variables can be used:

KEY	TYPE	DEFAULT	REQUIRED	DESCRIPTION
{{range .}}{{usage_key .}}	{{usage_type .}}	{{usage_default .}}	{{usage_required .}}	{{usage_description .}}
{{end}}`
)

var (
	decoderType     = reflect.TypeOf((*Decoder)(nil)).Elem()
	setterType      = reflect.TypeOf((*Setter)(nil)).Elem()
	unmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)

func implementsInterface(t reflect.Type) bool {
	return t.Implements(decoderType) ||
		reflect.PtrTo(t).Implements(decoderType) ||
		t.Implements(setterType) ||
		reflect.PtrTo(t).Implements(setterType) ||
		t.Implements(unmarshalerType) ||
		reflect.PtrTo(t).Implements(unmarshalerType)
}

// toTypeDescription converts Go types into a human readable description
func toTypeDescription(t reflect.Type) string {
	switch t.Kind() {
	case reflect.Array, reflect.Slice:
		return fmt.Sprintf("Comma-separated list of %s", toTypeDescription(t.Elem()))
	case reflect.Map:
		return fmt.Sprintf(
			"Comma-separated list of %s:%s pairs",
			toTypeDescription(t.Key()),
			toTypeDescription(t.Elem()),
		)
	case reflect.Ptr:
		return toTypeDescription(t.Elem())
	case reflect.Struct:
		if implementsInterface(t) && t.Name() != "" {
			return t.Name()
		}
		return ""
	case reflect.String:
		name := t.Name()
		if name != "" && name != "string" {
			return name
		}
		return "String"
	case reflect.Bool:
		name := t.Name()
		if name != "" && name != "bool" {
			return name
		}
		return "True or False"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "int") {
			return name
		}
		return "Integer"
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "uint") {
			return name
		}
		return "Unsigned Integer"
	case reflect.Float32, reflect.Float64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "float") {
			return name
		}
		return "Float"
	}
	return fmt.Sprintf("%+v", t)
}

// Usage writes usage information to stderr using the default header and table format
func Usage(prefix string, spec interface{}) error {
	// The default is to output the usage information as a table
	// Create tabwriter instance to support table output
	tabs := tabwriter.NewWriter(os.Stdout, 1, 0, 4, ' ', 0)

	err := Usagef(prefix, spec, tabs, DefaultTableFormat)
	tabs.Flush()
	return err
}

// Usagef writes usage information to the specified io.Writer using the specifed template specification
func Usagef(prefix string, spec interface{}, out io.Writer, format string) error {

	// Specify the default usage template functions
	functions := template.FuncMap{
		"usage_key":         func(v varInfo) string { return v.Key },
		"usage_description": func(v varInfo) string { return v.Tags.Get("desc") },
		"usage_type":        func(v varInfo) string { return toTypeDescription(v.Field.Type()) },
		"usage_default":     func(v varInfo) string { return v.Tags.Get("default") },
		"usage_required": func(v varInfo) (string, error) {
			req := v.Tags.Get("required")
			if req != "" {
				reqB, err := strconv.ParseBool(req)
				if err != nil {
					return "", err
				}
				if reqB {
					req = "true"
				}
			}
			return req, nil
		},
	}

	tmpl, err := template.New("envconfig").Funcs(functions).Parse(format)
	if err != nil {
		return err
	}

	return Usaget(prefix, spec, out, tmpl)
}

// Usaget writes usage information to the specified io.Writer using the specified template
func Usaget(prefix string, spec interface{}, out io.Writer, tmpl *template.Template) error {
	// gather first
	infos, err := gatherInfo(prefix, spec)
	if err != nil {
		return err
	}

	return tmpl.Execute(out, infos)
}
<commit_msg>Fix typo (#87)<commit_after>// Copyright (c) 2016 Kelsey Hightower and others. All rights reserved.
// Use of this source code is governed by the MIT License that can be found in
// the LICENSE file.

package envconfig

import (
	"encoding"
	"fmt"
	"io"
	"os"
	"reflect"
	"strconv"
	"strings"
	"text/tabwriter"
	"text/template"
)

const (
	// DefaultListFormat constant to use to display usage in a list format
	DefaultListFormat = `This application is configured via the environment. The following environment
variables can be used:
{{range .}}
{{usage_key .}}
  [description] {{usage_description .}}
  [type]        {{usage_type .}}
  [default]     {{usage_default .}}
  [required]    {{usage_required .}}{{end}}
`
	// DefaultTableFormat constant to use to display usage in a tabular format
	DefaultTableFormat = `This application is configured via the environment. The following environment
variables can be used:

KEY	TYPE	DEFAULT	REQUIRED	DESCRIPTION
{{range .}}{{usage_key .}}	{{usage_type .}}	{{usage_default .}}	{{usage_required .}}	{{usage_description .}}
{{end}}`
)

var (
	decoderType     = reflect.TypeOf((*Decoder)(nil)).Elem()
	setterType      = reflect.TypeOf((*Setter)(nil)).Elem()
	unmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)

func implementsInterface(t reflect.Type) bool {
	return t.Implements(decoderType) ||
		reflect.PtrTo(t).Implements(decoderType) ||
		t.Implements(setterType) ||
		reflect.PtrTo(t).Implements(setterType) ||
		t.Implements(unmarshalerType) ||
		reflect.PtrTo(t).Implements(unmarshalerType)
}

// toTypeDescription converts Go types into a human readable description
func toTypeDescription(t reflect.Type) string {
	switch t.Kind() {
	case reflect.Array, reflect.Slice:
		return fmt.Sprintf("Comma-separated list of %s", toTypeDescription(t.Elem()))
	case reflect.Map:
		return fmt.Sprintf(
			"Comma-separated list of %s:%s pairs",
			toTypeDescription(t.Key()),
			toTypeDescription(t.Elem()),
		)
	case reflect.Ptr:
		return toTypeDescription(t.Elem())
	case reflect.Struct:
		if implementsInterface(t) && t.Name() != "" {
			return t.Name()
		}
		return ""
	case reflect.String:
		name := t.Name()
		if name != "" && name != "string" {
			return name
		}
		return "String"
	case reflect.Bool:
		name := t.Name()
		if name != "" && name != "bool" {
			return name
		}
		return "True or False"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "int") {
			return name
		}
		return "Integer"
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "uint") {
			return name
		}
		return "Unsigned Integer"
	case reflect.Float32, reflect.Float64:
		name := t.Name()
		if name != "" && !strings.HasPrefix(name, "float") {
			return name
		}
		return "Float"
	}
	return fmt.Sprintf("%+v", t)
}

// Usage writes usage information to stderr using the default header and table format
func Usage(prefix string, spec interface{}) error {
	// The default is to output the usage information as a table
	// Create tabwriter instance to support table output
	tabs := tabwriter.NewWriter(os.Stdout, 1, 0, 4, ' ', 0)

	err := Usagef(prefix, spec, tabs, DefaultTableFormat)
	tabs.Flush()
	return err
}

// Usagef writes usage information to the specified io.Writer using the specifed template specification
func Usagef(prefix string, spec interface{}, out io.Writer, format string) error {

	// Specify the default usage template functions
	functions := template.FuncMap{
		"usage_key":         func(v varInfo) string { return v.Key },
		"usage_description": func(v varInfo) string { return v.Tags.Get("desc") },
		"usage_type":        func(v varInfo) string { return toTypeDescription(v.Field.Type()) },
		"usage_default":     func(v varInfo) string { return v.Tags.Get("default") },
		"usage_required": func(v varInfo) (string, error) {
			req := v.Tags.Get("required")
			if req != "" {
				reqB, err := strconv.ParseBool(req)
				if err != nil {
					return "", err
				}
				if reqB {
					req = "true"
				}
			}
			return req, nil
		},
	}

	tmpl, err := template.New("envconfig").Funcs(functions).Parse(format)
	if err != nil {
		return err
	}

	return Usaget(prefix, spec, out, tmpl)
}

// Usaget writes usage information to the specified io.Writer using the specified template
func Usaget(prefix string, spec interface{}, out io.Writer, tmpl *template.Template) error {
	// gather first
	infos, err := gatherInfo(prefix, spec)
	if err != nil {
		return err
	}

	return tmpl.Execute(out, infos)
}
<|endoftext|>


<commit_before>package goinsta

import (
	"encoding/json"
	"errors"
	"fmt"
)

type Users struct {
	inst *Instagram

	// It's a bit confusing have the same structure
	// in the Instagram strucure and in the multiple users
	// calls

	err      error
	endpoint string

	Status   string `json:"status"`
	BigList  bool   `json:"big_list"`
	Users    []User `json:"users"`
	PageSize int    `json:"page_size"`
	NextID   string `json:"next_max_id"`
}

func newUsers(inst *Instagram) *Users {
	users := &Users{inst: inst}

	return users
}

// SetInstagram sets new instagram to user structure
func (users *Users) SetInstagram(inst *Instagram) {
	users.inst = inst
}

var ErrNoMore = errors.New("User list end reached")

// Next allows to paginate after calling:
// Account.Follow* and User.Follow*
//
// New user list is stored inside Users
//
// returns false when list reach the end.
func (users *Users) Next() bool {
	if users.err != nil {
		return false
	}

	insta := users.inst
	endpoint := users.endpoint

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query: map[string]string{
				"max_id":             users.NextID,
				"ig_sig_key_version": goInstaSigKeyVersion,
				"rank_token":         insta.rankToken,
			},
		},
	)
	if err == nil {
		usrs := Users{}
		err = json.Unmarshal(body, &usrs)
		if err == nil {
			*users = usrs
			if !usrs.BigList || usrs.NextID == "" {
				users.err = ErrNoMore
			}
			users.inst = insta
			users.endpoint = endpoint
			return true
		}
	}
	users.err = err
	return false
}

type userResp struct {
	Status string `json:"status"`
	User   User   `json:"user"`
}

// User is the representation of instagram's user profile
type User struct {
	inst *Instagram

	ID                         int64        `json:"pk"`
	Username                   string       `json:"username"`
	FullName                   string       `json:"full_name"`
	Biography                  string       `json:"biography"`
	ProfilePicURL              string       `json:"profile_pic_url"`
	Email                      string       `json:"email"`
	PhoneNumber                string       `json:"phone_number"`
	IsBusiness                 bool         `json:"is_business"`
	Gender                     int          `json:"gender"`
	ProfilePicID               string       `json:"profile_pic_id"`
	HasAnonymousProfilePicture bool         `json:"has_anonymous_profile_picture"`
	IsPrivate                  bool         `json:"is_private"`
	IsUnpublished              bool         `json:"is_unpublished"`
	AllowedCommenterType       string       `json:"allowed_commenter_type"`
	IsVerified                 bool         `json:"is_verified"`
	MediaCount                 int          `json:"media_count"`
	FollowerCount              int          `json:"follower_count"`
	FollowingCount             int          `json:"following_count"`
	GeoMediaCount              int          `json:"geo_media_count"`
	ExternalURL                string       `json:"external_url"`
	HasBiographyTranslation    bool         `json:"has_biography_translation"`
	ExternalLynxURL            string       `json:"external_lynx_url"`
	HdProfilePicURLInfo        PicURLInfo   `json:"hd_profile_pic_url_info"`
	HdProfilePicVersions       []PicURLInfo `json:"hd_profile_pic_versions"`
	UsertagsCount              int          `json:"usertags_count"`
	HasChaining                bool         `json:"has_chaining"`
	IsFavorite                 bool         `json:"is_favorite"`
	ReelAutoArchive            string       `json:"reel_auto_archive"`
	School                     School       `json:"school"`
	PublicEmail                string       `json:"public_email"`
	PublicPhoneNumber          string       `json:"public_phone_number"`
	PublicPhoneCountryCode     string       `json:"public_phone_country_code"`
	ContactPhoneNumber         string       `json:"contact_phone_number"`
	Byline                     string       `json:"byline"`
	SocialContext              string       `json:"social_context,omitempty"`
	SearchSocialContext        string       `json:"search_social_context,omitempty"`
	MutualFollowersCount       float64      `json:"mutual_followers_count"`
	LatestReelMedia            int          `json:"latest_reel_media,omitempty"`
	CityID                     int64        `json:"city_id"`
	CityName                   string       `json:"city_name"`
	AddressStreet              string       `json:"address_street"`
	DirectMessaging            string       `json:"direct_messaging"`
	Latitude                   float64      `json:"latitude"`
	Longitude                  float64      `json:"longitude"`
	Category                   string       `json:"category"`
	BusinessContactMethod      string       `json:"business_contact_method"`
	IsCallToActionEnabled      bool         `json:"is_call_to_action_enabled"`
	FbPageCallToActionID       string       `json:"fb_page_call_to_action_id"`
	Zip                        string       `json:"zip"`
	Friendship                 Friendship   `json:"friendship_status"`
}

// Following returns a list of user following.
//
// Users.Next can be used to paginate
//
// See example: examples/user/following.go
func (user *User) Following() *Users {
	users := &Users{}
	users.inst = user.inst
	users.endpoint = fmt.Sprintf(urlFollowing, user.ID)
	return users
}

// Followers returns a list of user followers.
//
// Users.Next can be used to paginate
//
// See example: examples/user/followers.go
func (user *User) Followers() *Users {
	users := &Users{}
	users.inst = user.inst
	users.endpoint = fmt.Sprintf(urlFollowers, user.ID)
	return users
}

// Block blocks user
//
// This function updates current User.Friendship structure.
//
// See example: examples/user/block.go
func (user *User) Block() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserBlock, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Unblock unblocks user
//
// This function updates current User.Friendship structure.
//
// See example: examples/user/unblock.go
func (user *User) Unblock() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserUnblock, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Follow started following some user
//
// This function performs a follow call. If user is private
// you have to wait until he/she accepts you.
//
// If the account is public User.Friendship will be updated
//
// See example: examples/user/follow.go
func (user *User) Follow() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserFollow, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Unfollow unfollows user
//
// User.Friendship will be updated
//
// See example: examples/user/unfollow.go
func (user *User) Unfollow() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserUnfollow, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// FriendShip allows user to get friend relationship.
//
// The result is stored in user.Friendship
func (user *User) FriendShip() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err != nil {
		return err
	}

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlFriendship, user.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	if err == nil {
		err = json.Unmarshal(body, &user.Friendship)
	}
	return err
}

// Feed returns user feeds (media)
//
// minTime is the minimum timestamp of media.
//
// For pagination use FeedMedia.Next()
//
// See example: examples/user/feed.go
func (user *User) Feed(minTime []byte) *FeedMedia {
	insta := user.inst
	timestamp := b2s(minTime)

	media := &FeedMedia{}
	media.timestamp = timestamp
	media.inst = insta
	media.endpoint = urlUserFeed
	media.uid = user.ID
	return media
}

// Stories returns user stories
//
// Use StoryMedia.Next for pagination.
//
// See example: examples/user/stories.go
func (user *User) Stories() *StoryMedia {
	media := &StoryMedia{}
	media.uid = user.ID
	media.inst = user.inst
	media.endpoint = urlUserStories
	return media
}

// Tags returns media where user is tagged in
//
// For pagination use FeedMedia.Next()
//
// See example: examples/user/tags.go
func (user *User) Tags(minTimestamp []byte) (*FeedMedia, error) {
	timestamp := b2s(minTimestamp)
	body, err := user.inst.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlUserTags, user.ID),
			Query: map[string]string{
				"max_id":         "",
				"rank_token":     user.inst.rankToken,
				"min_timestamp":  timestamp,
				"ranked_content": "true",
			},
		},
	)
	if err != nil {
		return nil, err
	}

	media := &FeedMedia{}
	err = json.Unmarshal(body, media)
	media.inst = user.inst
	media.endpoint = urlUserTags
	media.uid = user.ID
	return media, err
}
<commit_msg>Added setValues function to users<commit_after>package goinsta

import (
	"encoding/json"
	"errors"
	"fmt"
)

type Users struct {
	inst *Instagram

	// It's a bit confusing have the same structure
	// in the Instagram strucure and in the multiple users
	// calls

	err      error
	endpoint string

	Status   string `json:"status"`
	BigList  bool   `json:"big_list"`
	Users    []User `json:"users"`
	PageSize int    `json:"page_size"`
	NextID   string `json:"next_max_id"`
}

func newUsers(inst *Instagram) *Users {
	users := &Users{inst: inst}

	return users
}

// SetInstagram sets new instagram to user structure
func (users *Users) SetInstagram(inst *Instagram) {
	users.inst = inst
}

var ErrNoMore = errors.New("User list end reached")

// Next allows to paginate after calling:
// Account.Follow* and User.Follow*
//
// New user list is stored inside Users
//
// returns false when list reach the end.
func (users *Users) Next() bool {
	if users.err != nil {
		return false
	}

	insta := users.inst
	endpoint := users.endpoint

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query: map[string]string{
				"max_id":             users.NextID,
				"ig_sig_key_version": goInstaSigKeyVersion,
				"rank_token":         insta.rankToken,
			},
		},
	)
	if err == nil {
		usrs := Users{}
		err = json.Unmarshal(body, &usrs)
		if err == nil {
			*users = usrs
			if !usrs.BigList || usrs.NextID == "" {
				users.err = ErrNoMore
			}
			users.inst = insta
			users.endpoint = endpoint
			users.setValues()
			return true
		}
	}
	users.err = err
	return false
}

func (users *Users) setValues() {
	for i := range users.Users {
		users.Users[i].inst = users.inst
	}
}

type userResp struct {
	Status string `json:"status"`
	User   User   `json:"user"`
}

// User is the representation of instagram's user profile
type User struct {
	inst *Instagram

	ID                         int64        `json:"pk"`
	Username                   string       `json:"username"`
	FullName                   string       `json:"full_name"`
	Biography                  string       `json:"biography"`
	ProfilePicURL              string       `json:"profile_pic_url"`
	Email                      string       `json:"email"`
	PhoneNumber                string       `json:"phone_number"`
	IsBusiness                 bool         `json:"is_business"`
	Gender                     int          `json:"gender"`
	ProfilePicID               string       `json:"profile_pic_id"`
	HasAnonymousProfilePicture bool         `json:"has_anonymous_profile_picture"`
	IsPrivate                  bool         `json:"is_private"`
	IsUnpublished              bool         `json:"is_unpublished"`
	AllowedCommenterType       string       `json:"allowed_commenter_type"`
	IsVerified                 bool         `json:"is_verified"`
	MediaCount                 int          `json:"media_count"`
	FollowerCount              int          `json:"follower_count"`
	FollowingCount             int          `json:"following_count"`
	GeoMediaCount              int          `json:"geo_media_count"`
	ExternalURL                string       `json:"external_url"`
	HasBiographyTranslation    bool         `json:"has_biography_translation"`
	ExternalLynxURL            string       `json:"external_lynx_url"`
	HdProfilePicURLInfo        PicURLInfo   `json:"hd_profile_pic_url_info"`
	HdProfilePicVersions       []PicURLInfo `json:"hd_profile_pic_versions"`
	UsertagsCount              int          `json:"usertags_count"`
	HasChaining                bool         `json:"has_chaining"`
	IsFavorite                 bool         `json:"is_favorite"`
	ReelAutoArchive            string       `json:"reel_auto_archive"`
	School                     School       `json:"school"`
	PublicEmail                string       `json:"public_email"`
	PublicPhoneNumber          string       `json:"public_phone_number"`
	PublicPhoneCountryCode     string       `json:"public_phone_country_code"`
	ContactPhoneNumber         string       `json:"contact_phone_number"`
	Byline                     string       `json:"byline"`
	SocialContext              string       `json:"social_context,omitempty"`
	SearchSocialContext        string       `json:"search_social_context,omitempty"`
	MutualFollowersCount       float64      `json:"mutual_followers_count"`
	LatestReelMedia            int          `json:"latest_reel_media,omitempty"`
	CityID                     int64        `json:"city_id"`
	CityName                   string       `json:"city_name"`
	AddressStreet              string       `json:"address_street"`
	DirectMessaging            string       `json:"direct_messaging"`
	Latitude                   float64      `json:"latitude"`
	Longitude                  float64      `json:"longitude"`
	Category                   string       `json:"category"`
	BusinessContactMethod      string       `json:"business_contact_method"`
	IsCallToActionEnabled      bool         `json:"is_call_to_action_enabled"`
	FbPageCallToActionID       string       `json:"fb_page_call_to_action_id"`
	Zip                        string       `json:"zip"`
	Friendship                 Friendship   `json:"friendship_status"`
}

// Following returns a list of user following.
//
// Users.Next can be used to paginate
//
// See example: examples/user/following.go
func (user *User) Following() *Users {
	users := &Users{}
	users.inst = user.inst
	users.endpoint = fmt.Sprintf(urlFollowing, user.ID)
	return users
}

// Followers returns a list of user followers.
//
// Users.Next can be used to paginate
//
// See example: examples/user/followers.go
func (user *User) Followers() *Users {
	users := &Users{}
	users.inst = user.inst
	users.endpoint = fmt.Sprintf(urlFollowers, user.ID)
	return users
}

// Block blocks user
//
// This function updates current User.Friendship structure.
//
// See example: examples/user/block.go
func (user *User) Block() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserBlock, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Unblock unblocks user
//
// This function updates current User.Friendship structure.
//
// See example: examples/user/unblock.go
func (user *User) Unblock() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserUnblock, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Follow started following some user
//
// This function performs a follow call. If user is private
// you have to wait until he/she accepts you.
//
// If the account is public User.Friendship will be updated
//
// See example: examples/user/follow.go
func (user *User) Follow() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserFollow, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// Unfollow unfollows user
//
// User.Friendship will be updated
//
// See example: examples/user/unfollow.go
func (user *User) Unfollow() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err == nil {
		body, err := insta.sendRequest(
			&reqOptions{
				Endpoint: fmt.Sprintf(urlUserUnfollow, user.ID),
				Query:    generateSignature(data),
				IsPost:   true,
			},
		)
		if err == nil {
			resp := friendResp{}
			err = json.Unmarshal(body, &resp)
			user.Friendship = resp.Friendship
		}
	}
	return err
}

// FriendShip allows user to get friend relationship.
//
// The result is stored in user.Friendship
func (user *User) FriendShip() error {
	insta := user.inst
	data, err := insta.prepareData(
		map[string]interface{}{
			"user_id": user.ID,
		},
	)
	if err != nil {
		return err
	}

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlFriendship, user.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	if err == nil {
		err = json.Unmarshal(body, &user.Friendship)
	}
	return err
}

// Feed returns user feeds (media)
//
// minTime is the minimum timestamp of media.
//
// For pagination use FeedMedia.Next()
//
// See example: examples/user/feed.go
func (user *User) Feed(minTime []byte) *FeedMedia {
	insta := user.inst
	timestamp := b2s(minTime)

	media := &FeedMedia{}
	media.timestamp = timestamp
	media.inst = insta
	media.endpoint = urlUserFeed
	media.uid = user.ID
	return media
}

// Stories returns user stories
//
// Use StoryMedia.Next for pagination.
//
// See example: examples/user/stories.go
func (user *User) Stories() *StoryMedia {
	media := &StoryMedia{}
	media.uid = user.ID
	media.inst = user.inst
	media.endpoint = urlUserStories
	return media
}

// Tags returns media where user is tagged in
//
// For pagination use FeedMedia.Next()
//
// See example: examples/user/tags.go
func (user *User) Tags(minTimestamp []byte) (*FeedMedia, error) {
	timestamp := b2s(minTimestamp)
	body, err := user.inst.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlUserTags, user.ID),
			Query: map[string]string{
				"max_id":         "",
				"rank_token":     user.inst.rankToken,
				"min_timestamp":  timestamp,
				"ranked_content": "true",
			},
		},
	)
	if err != nil {
		return nil, err
	}

	media := &FeedMedia{}
	err = json.Unmarshal(body, media)
	media.inst = user.inst
	media.endpoint = urlUserTags
	media.uid = user.ID
	return media, err
}
<|endoftext|>