<commit_before>package parse

import (
	"encoding/json"
	"fmt"
	"net/url"
	"path"
	"reflect"
	"time"
)

// An interface for custom Parse types. Contains a single method:
//
// ClassName() - returns a string containing the class name as it appears in your
// Parse database.
//
// Implement this interface if your class name does not match your struct
// name. If this class is not implemented, the name of the struct will
// be used when interacting with the Parse API
type iClassName interface {
	ClassName() string
}

// An interface for custom Parse types to override the endpoint used for querying.
//
// Contains a single method:
//
// Endpoint() - returns the endpoint to use when querying the Parse REST API.
//
// If this method is not implented, the endpoint is constructed as follows:
//
// /classes/{ClassName} - where {ClassName} is the name of the struct or the value returned by the ClassName
// method if implemented
type iParseEp interface {
	Endpoint() string
}

// A base type containing fields common to all Parse types
//
// Embed this struct in custom types to avoid having to declare
// these fields everywhere.
type Base struct {
	Id        string                 `parse:"objectId"`
	CreatedAt time.Time              `parse:"-"`
	UpdatedAt time.Time              `parse:"-"`
	ACL       ACL                    `parse:"ACL"`
	Extra     map[string]interface{} `parse:"-"`
}

// Represents the built-in Parse "User" class. Embed this type in a custom
// type containing any custom fields. When fetching user objects, any retrieved
// fields with no matching struct field will be stored in User.Extra (map[string]interface{})
type User struct {
	Base
	Username      string
	Email         string
	EmailVerified bool
}

func (u *User) ClassName() string {
	return "_User"
}

func (u *User) Endpoint() string {
	return "users"
}

// Represents the built-in Parse "Installation" class. Embed this type in a custom
// type containing any custom fields. When fetching user objects, any retrieved
// fields with no matching struct field will be stored in User.Extra (map[string]interface{})
type Installation struct {
	Base
}

func (i *Installation) ClassName() string {
	return "_Installation"
}

func (i *Installation) Endpoint() string {
	return "installations"
}

type ACL interface {
	PublicReadAccess() bool
	PublicWriteAccess() bool
	RoleReadAccess(role string) bool
	RoleWriteAccess(role string) bool
	ReadAccess(userId string) bool
	WriteAccess(userId string) bool

	SetPublicReadAccess(allowed bool) ACL
	SetPublicWriteAccess(allowed bool) ACL
	SetRoleReadAccess(role string, allowed bool) ACL
	SetRoleWriteAccess(role string, allowed bool) ACL
	SetReadAccess(userId string, allowed bool) ACL
	SetWriteAccess(userId string, allowed bool) ACL
}

type aclT struct {
	publicReadAccess  bool
	publicWriteAccess bool

	write map[string]bool
	read  map[string]bool
}

func NewACL() ACL {
	return &aclT{
		write: map[string]bool{},
		read:  map[string]bool{},
	}
}

func (a *aclT) PublicReadAccess() bool {
	return a.publicReadAccess
}

func (a *aclT) PublicWriteAccess() bool {
	return a.publicWriteAccess
}

func (a *aclT) RoleReadAccess(role string) bool {
	if tmp, ok := a.read["role:"+role]; ok {
		return tmp
	}
	return false
}

func (a *aclT) RoleWriteAccess(role string) bool {
	if tmp, ok := a.write["role:"+role]; ok {
		return tmp
	}
	return false
}

func (a *aclT) ReadAccess(userId string) bool {
	if tmp, ok := a.read[userId]; ok {
		return tmp
	}
	return false
}

func (a *aclT) WriteAccess(userId string) bool {
	if tmp, ok := a.write[userId]; ok {
		return tmp
	}
	return false
}

func (a *aclT) SetPublicReadAccess(allowed bool) ACL {
	a.publicReadAccess = allowed
	return a
}

func (a *aclT) SetPublicWriteAccess(allowed bool) ACL {
	a.publicWriteAccess = allowed
	return a
}

func (a *aclT) SetReadAccess(userId string, allowed bool) ACL {
	a.read[userId] = allowed
	return a
}

func (a *aclT) SetWriteAccess(userId string, allowed bool) ACL {
	a.write[userId] = allowed
	return a
}

func (a *aclT) SetRoleReadAccess(role string, allowed bool) ACL {
	a.read["role:"+role] = allowed
	return a
}

func (a *aclT) SetRoleWriteAccess(role string, allowed bool) ACL {
	a.write["role:"+role] = allowed
	return a
}

func (a *aclT) MarshalJSON() ([]byte, error) {
	m := map[string]map[string]bool{}

	for k, v := range a.read {
		if v {
			m[k] = map[string]bool{
				"read": v,
			}
		}
	}

	for k, v := range a.write {
		if v {
			if p, ok := m[k]; ok {
				p["write"] = v
			} else {
				m[k] = map[string]bool{
					"write": v,
				}
			}
		}
	}

	if a.publicReadAccess {
		m["*"] = map[string]bool{
			"read": true,
		}
	}

	if a.publicWriteAccess {
		if p, ok := m["*"]; !ok {
			m["*"] = map[string]bool{
				"write": true,
			}
		} else {
			p["write"] = true
		}
	}

	return json.Marshal(m)
}

func (a *aclT) UnmarshalJSON(b []byte) error {
	m := map[string]map[string]bool{}

	if err := json.Unmarshal(b, &m); err != nil {
		return err
	}

	if a.read == nil {
		a.read = map[string]bool{}
	}

	if a.write == nil {
		a.write = map[string]bool{}
	}

	for k, v := range m {
		if k == "*" {
			if w, ok := v["write"]; w && ok {
				a.publicWriteAccess = true
			}
			if r, ok := v["read"]; r && ok {
				a.publicReadAccess = true
			}
		} else {
			if w, ok := v["write"]; w && ok {
				a.write[k] = true
			}
			if r, ok := v["read"]; r && ok {
				a.read[k] = true
			}
		}
	}
	return nil
}

// Represents the Parse GeoPoint type
type GeoPoint struct {
	Latitude  float64
	Longitude float64
}

func (g GeoPoint) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type      string  `json:"__type"`
		Latitude  float64 `json:"latitude"`
		Longitude float64 `json:"longitude"`
	}{
		"GeoPoint",
		g.Latitude,
		g.Longitude,
	})
}

func (g *GeoPoint) UnmarshalJSON(b []byte) error {
	s := struct {
		Type      string  `json:"__type"`
		Latitude  float64 `json:"latitude"`
		Longitude float64 `json:"longitude"`
	}{}
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}
	if s.Type != "GeoPoint" {
		return fmt.Errorf("cannot unmarshal type %s to type GeoPoint", s.Type)
	}

	g.Latitude = s.Latitude
	g.Longitude = s.Longitude
	return nil
}

// Represents the Parse File type
type File struct {
}

// Represents a Parse Pointer type. When querying, creating, or updating
// objects, any struct types will be automatically converted to and from Pointer
// types as required. Direct use of this type should not be necessary
type Pointer struct {
	Id        string
	ClassName string
}

func (p Pointer) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type      string `json:"__type"`
		ClassName string `json:"className"`
		Id        string `json:"objectId"`
	}{
		"Pointer",
		p.ClassName,
		p.Id,
	})
}

// Represents the Parse Date type. Values of type time.Time will
// automatically converted to a Date type when constructing queries
// or creating objects. The inverse is true for retrieving objects.
// Direct use of this type should not be necessary
type Date time.Time

func (d Date) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type string `json:"__type"`
		Iso  string `json:"iso"`
	}{
		"Date",
		time.Time(d).In(time.UTC).Format("2006-01-02T15:04:05.000Z"),
	})
}

func (d *Date) UnmarshalJSON(b []byte) error {
	s := struct {
		Type string `json:"__type"`
		Iso  string `json:"iso"`
	}{}
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}
	if s.Type != "Date" {
		return fmt.Errorf("cannot unmarshal type %s to type Date", s.Type)
	}

	t, err := time.Parse(s.Iso, "2006-01-02T15:04:05.000Z")
	if err != nil {
		return err
	}

	*d = Date(t)
	return nil
}

func getClassName(v interface{}) string {
	if tmp, ok := v.(iClassName); ok {
		return tmp.ClassName()
	} else {
		t := reflect.TypeOf(v)
		return t.Elem().Name()
	}
}

func getEndpointBase(v interface{}) string {
	var p string
	var inst interface{}

	rt := reflect.TypeOf(v)
	rt = rt.Elem()
	if rt.Kind() == reflect.Slice || rt.Kind() == reflect.Array {
		rte := rt.Elem()
		var rv reflect.Value
		if rte.Kind() == reflect.Ptr {
			rv = reflect.New(rte.Elem())
		} else {
			rv = reflect.New(rte)
		}
		inst = rv.Interface()
	} else {
		inst = v
	}

	if iv, ok := inst.(iParseEp); ok {
		p = iv.Endpoint()
	} else {
		cname := getClassName(v)
		p = path.Join("classes", cname)
	}

	p = path.Join(ParseVersion, p)
	return p
}

type Config map[string]interface{}

type configRequestT struct{}

func (c *configRequestT) method() string {
	return "GET"
}

func (c *configRequestT) endpoint() (string, error) {
	u := url.URL{}
	u.Scheme = "https"
	u.Host = parseHost
	u.Path = path.Join(ParseVersion, "config")
	return u.String(), nil
}

func (c *configRequestT) body() (string, error) {
	return "", nil
}

func (c *configRequestT) useMasterKey() bool {
	return false
}

func (c *configRequestT) session() *sessionT {
	return nil
}

func (c *configRequestT) contentType() string {
	return ""
}

func GetConfig() (Config, error) {
	b, err := defaultClient.doRequest(&configRequestT{})
	if err != nil {
		return nil, err
	}

	c := struct {
		Params Config `json:"params"`
	}{}
	if err := json.Unmarshal(b, &c); err != nil {
		return nil, err
	}

	return c.Params, nil
}
<commit_msg>add some documentation to the ACL type<commit_after>package parse

import (
	"encoding/json"
	"fmt"
	"net/url"
	"path"
	"reflect"
	"time"
)

// An interface for custom Parse types. Contains a single method:
//
// ClassName() - returns a string containing the class name as it appears in your
// Parse database.
//
// Implement this interface if your class name does not match your struct
// name. If this class is not implemented, the name of the struct will
// be used when interacting with the Parse API
type iClassName interface {
	ClassName() string
}

// An interface for custom Parse types to override the endpoint used for querying.
//
// Contains a single method:
//
// Endpoint() - returns the endpoint to use when querying the Parse REST API.
//
// If this method is not implented, the endpoint is constructed as follows:
//
// /classes/{ClassName} - where {ClassName} is the name of the struct or the value returned by the ClassName
// method if implemented
type iParseEp interface {
	Endpoint() string
}

// A base type containing fields common to all Parse types
//
// Embed this struct in custom types to avoid having to declare
// these fields everywhere.
type Base struct {
	Id        string                 `parse:"objectId"`
	CreatedAt time.Time              `parse:"-"`
	UpdatedAt time.Time              `parse:"-"`
	ACL       ACL                    `parse:"ACL"`
	Extra     map[string]interface{} `parse:"-"`
}

// Represents the built-in Parse "User" class. Embed this type in a custom
// type containing any custom fields. When fetching user objects, any retrieved
// fields with no matching struct field will be stored in User.Extra (map[string]interface{})
type User struct {
	Base
	Username      string
	Email         string
	EmailVerified bool
}

func (u *User) ClassName() string {
	return "_User"
}

func (u *User) Endpoint() string {
	return "users"
}

// Represents the built-in Parse "Installation" class. Embed this type in a custom
// type containing any custom fields. When fetching user objects, any retrieved
// fields with no matching struct field will be stored in User.Extra (map[string]interface{})
type Installation struct {
	Base
}

func (i *Installation) ClassName() string {
	return "_Installation"
}

func (i *Installation) Endpoint() string {
	return "installations"
}

type ACL interface {
	// Returns whether public read access is enabled on this ACL
	PublicReadAccess() bool

	// Returns whether public write access is enabled on this ACL
	PublicWriteAccess() bool

	// Returns whether read access is enabled on this ACL for the
	// given role
	RoleReadAccess(role string) bool

	// Returns whether write access is enabled on this ACL for the
	// given role
	RoleWriteAccess(role string) bool

	// Returns whether read access is enabled on this ACL for the
	// given user
	ReadAccess(userId string) bool

	// Returns whether write access is enabled on this ACL for the
	// given user
	WriteAccess(userId string) bool

	// Allow the object to which this ACL is attached be read
	// by anyone
	SetPublicReadAccess(allowed bool) ACL

	// Allow the object to which this ACL is attached to be
	// updated by anyone
	SetPublicWriteAccess(allowed bool) ACL

	// Allow the object to which this ACL is attached to be
	// read by the provided role
	SetRoleReadAccess(role string, allowed bool) ACL

	// Allow the object to which this ACL is attached to be
	// updated by the provided role
	SetRoleWriteAccess(role string, allowed bool) ACL

	// Allow the object to which this ACL is attached to be
	// read by the provided user
	SetReadAccess(userId string, allowed bool) ACL

	// Allow the object to which this ACL is attached to be
	// updated by the provided user
	SetWriteAccess(userId string, allowed bool) ACL
}

type aclT struct {
	publicReadAccess  bool
	publicWriteAccess bool

	write map[string]bool
	read  map[string]bool
}

func NewACL() ACL {
	return &aclT{
		write: map[string]bool{},
		read:  map[string]bool{},
	}
}

func (a *aclT) PublicReadAccess() bool {
	return a.publicReadAccess
}

func (a *aclT) PublicWriteAccess() bool {
	return a.publicWriteAccess
}

func (a *aclT) RoleReadAccess(role string) bool {
	if tmp, ok := a.read["role:"+role]; ok {
		return tmp
	}
	return false
}

func (a *aclT) RoleWriteAccess(role string) bool {
	if tmp, ok := a.write["role:"+role]; ok {
		return tmp
	}
	return false
}

func (a *aclT) ReadAccess(userId string) bool {
	if tmp, ok := a.read[userId]; ok {
		return tmp
	}
	return false
}

func (a *aclT) WriteAccess(userId string) bool {
	if tmp, ok := a.write[userId]; ok {
		return tmp
	}
	return false
}

func (a *aclT) SetPublicReadAccess(allowed bool) ACL {
	a.publicReadAccess = allowed
	return a
}

func (a *aclT) SetPublicWriteAccess(allowed bool) ACL {
	a.publicWriteAccess = allowed
	return a
}

func (a *aclT) SetReadAccess(userId string, allowed bool) ACL {
	a.read[userId] = allowed
	return a
}

func (a *aclT) SetWriteAccess(userId string, allowed bool) ACL {
	a.write[userId] = allowed
	return a
}

func (a *aclT) SetRoleReadAccess(role string, allowed bool) ACL {
	a.read["role:"+role] = allowed
	return a
}

func (a *aclT) SetRoleWriteAccess(role string, allowed bool) ACL {
	a.write["role:"+role] = allowed
	return a
}

func (a *aclT) MarshalJSON() ([]byte, error) {
	m := map[string]map[string]bool{}

	for k, v := range a.read {
		if v {
			m[k] = map[string]bool{
				"read": v,
			}
		}
	}

	for k, v := range a.write {
		if v {
			if p, ok := m[k]; ok {
				p["write"] = v
			} else {
				m[k] = map[string]bool{
					"write": v,
				}
			}
		}
	}

	if a.publicReadAccess {
		m["*"] = map[string]bool{
			"read": true,
		}
	}

	if a.publicWriteAccess {
		if p, ok := m["*"]; !ok {
			m["*"] = map[string]bool{
				"write": true,
			}
		} else {
			p["write"] = true
		}
	}

	return json.Marshal(m)
}

func (a *aclT) UnmarshalJSON(b []byte) error {
	m := map[string]map[string]bool{}

	if err := json.Unmarshal(b, &m); err != nil {
		return err
	}

	if a.read == nil {
		a.read = map[string]bool{}
	}

	if a.write == nil {
		a.write = map[string]bool{}
	}

	for k, v := range m {
		if k == "*" {
			if w, ok := v["write"]; w && ok {
				a.publicWriteAccess = true
			}
			if r, ok := v["read"]; r && ok {
				a.publicReadAccess = true
			}
		} else {
			if w, ok := v["write"]; w && ok {
				a.write[k] = true
			}
			if r, ok := v["read"]; r && ok {
				a.read[k] = true
			}
		}
	}
	return nil
}

// Represents the Parse GeoPoint type
type GeoPoint struct {
	Latitude  float64
	Longitude float64
}

func (g GeoPoint) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type      string  `json:"__type"`
		Latitude  float64 `json:"latitude"`
		Longitude float64 `json:"longitude"`
	}{
		"GeoPoint",
		g.Latitude,
		g.Longitude,
	})
}

func (g *GeoPoint) UnmarshalJSON(b []byte) error {
	s := struct {
		Type      string  `json:"__type"`
		Latitude  float64 `json:"latitude"`
		Longitude float64 `json:"longitude"`
	}{}
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}
	if s.Type != "GeoPoint" {
		return fmt.Errorf("cannot unmarshal type %s to type GeoPoint", s.Type)
	}

	g.Latitude = s.Latitude
	g.Longitude = s.Longitude
	return nil
}

// Represents the Parse File type
type File struct {
}

// Represents a Parse Pointer type. When querying, creating, or updating
// objects, any struct types will be automatically converted to and from Pointer
// types as required. Direct use of this type should not be necessary
type Pointer struct {
	Id        string
	ClassName string
}

func (p Pointer) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type      string `json:"__type"`
		ClassName string `json:"className"`
		Id        string `json:"objectId"`
	}{
		"Pointer",
		p.ClassName,
		p.Id,
	})
}

// Represents the Parse Date type. Values of type time.Time will
// automatically converted to a Date type when constructing queries
// or creating objects. The inverse is true for retrieving objects.
// Direct use of this type should not be necessary
type Date time.Time

func (d Date) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Type string `json:"__type"`
		Iso  string `json:"iso"`
	}{
		"Date",
		time.Time(d).In(time.UTC).Format("2006-01-02T15:04:05.000Z"),
	})
}

func (d *Date) UnmarshalJSON(b []byte) error {
	s := struct {
		Type string `json:"__type"`
		Iso  string `json:"iso"`
	}{}
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}
	if s.Type != "Date" {
		return fmt.Errorf("cannot unmarshal type %s to type Date", s.Type)
	}

	t, err := time.Parse(s.Iso, "2006-01-02T15:04:05.000Z")
	if err != nil {
		return err
	}

	*d = Date(t)
	return nil
}

func getClassName(v interface{}) string {
	if tmp, ok := v.(iClassName); ok {
		return tmp.ClassName()
	} else {
		t := reflect.TypeOf(v)
		return t.Elem().Name()
	}
}

func getEndpointBase(v interface{}) string {
	var p string
	var inst interface{}

	rt := reflect.TypeOf(v)
	rt = rt.Elem()
	if rt.Kind() == reflect.Slice || rt.Kind() == reflect.Array {
		rte := rt.Elem()
		var rv reflect.Value
		if rte.Kind() == reflect.Ptr {
			rv = reflect.New(rte.Elem())
		} else {
			rv = reflect.New(rte)
		}
		inst = rv.Interface()
	} else {
		inst = v
	}

	if iv, ok := inst.(iParseEp); ok {
		p = iv.Endpoint()
	} else {
		cname := getClassName(v)
		p = path.Join("classes", cname)
	}

	p = path.Join(ParseVersion, p)
	return p
}

type Config map[string]interface{}

type configRequestT struct{}

func (c *configRequestT) method() string {
	return "GET"
}

func (c *configRequestT) endpoint() (string, error) {
	u := url.URL{}
	u.Scheme = "https"
	u.Host = parseHost
	u.Path = path.Join(ParseVersion, "config")
	return u.String(), nil
}

func (c *configRequestT) body() (string, error) {
	return "", nil
}

func (c *configRequestT) useMasterKey() bool {
	return false
}

func (c *configRequestT) session() *sessionT {
	return nil
}

func (c *configRequestT) contentType() string {
	return ""
}

func GetConfig() (Config, error) {
	b, err := defaultClient.doRequest(&configRequestT{})
	if err != nil {
		return nil, err
	}

	c := struct {
		Params Config `json:"params"`
	}{}
	if err := json.Unmarshal(b, &c); err != nil {
		return nil, err
	}

	return c.Params, nil
}
<|endoftext|>


<commit_before>package graphql

// Call represents a root call into a graphql schema
//
// Example string representation:
// node(42){fieldX}
type Call struct {
	Name      string
	Arguments Arguments
	Fields    Fields `json:",omitempty"`
}

// Argument is an argument to a Call
type Argument string

// Arguments is a collection of Argument values
type Arguments []Argument

// Fields is a collection of Field values
type Fields []Field

// Field represents a named field, a field call, or a set of Fields for a sub-object.
type Field struct {
	Call   *Call  `json:",omitempty"`
	Name   string `json:",omitempty"`
	Fields Fields `json:",omitempty"`
}
<commit_msg>omit args if empty<commit_after>package graphql

// Call represents a root call into a graphql schema
//
// Example string representation:
// node(42){fieldX}
type Call struct {
	Name      string
	Arguments Arguments `json:",omitempty"`
	Fields    Fields    `json:",omitempty"`
}

// Argument is an argument to a Call
type Argument string

// Arguments is a collection of Argument values
type Arguments []Argument

// Fields is a collection of Field values
type Fields []Field

// Field represents a named field, a field call, or a set of Fields for a sub-object.
type Field struct {
	Call   *Call  `json:",omitempty"`
	Name   string `json:",omitempty"`
	Fields Fields `json:",omitempty"`
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pkix

import (
	"encoding/asn1"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)

type jsonName struct {
	CommonName         []string
	SerialNumber       []string
	Country            []string
	Locality           []string
	Province           []string
	StreetAddress      []string
	Organization       []string
	OrganizationalUnit []string
	PostalCode         []string
	DomainComponent    []string //technically deprecated, but yolo
	UnknownAttributes  []AttributeTypeAndValue
}

func (jn *jsonName) MarshalJSON() ([]byte, error) {
	enc := make(map[string]interface{})
	if len(jn.CommonName) > 0 {
		enc["common_name"] = jn.CommonName
	}
	if len(jn.SerialNumber) > 0 {
		enc["serial_number"] = jn.SerialNumber
	}
	if len(jn.Country) > 0 {
		enc["country"] = jn.Country
	}
	if len(jn.Locality) > 0 {
		enc["locality"] = jn.Locality
	}
	if len(jn.Province) > 0 {
		enc["province"] = jn.Province
	}
	if len(jn.StreetAddress) > 0 {
		enc["street_address"] = jn.StreetAddress
	}
	if len(jn.Organization) > 0 {
		enc["organization"] = jn.Organization
	}
	if len(jn.OrganizationalUnit) > 0 {
		enc["organizational_unit"] = jn.OrganizationalUnit
	}
	if len(jn.PostalCode) > 0 {
		enc["postal_code"] = jn.PostalCode
	}
	if len(jn.DomainComponent) > 0 {
		enc["domain_component"] = jn.DomainComponent
	}
	for _, a := range jn.UnknownAttributes {
		enc[a.Type.String()] = a.Value
	}
	return json.Marshal(enc)
}

func convertToStrArray(i interface{}) []string {

	var strArray []string

	arr, _ := i.([]interface{})
	for _, val := range arr {
		if str, ok := val.(string); ok {
			strArray = append(strArray, str)
		}
	}

	return strArray
}

func (jn *jsonName) UnmarshalJSON(b []byte) error {
	nameMap := make(map[string]interface{})

	if err := json.Unmarshal(b, &nameMap); err != nil {
		return err
	}

	for key, val := range nameMap {
		switch key {
		case "common_name":
			jn.CommonName = convertToStrArray(val)
		case "serial_number":
			jn.SerialNumber = convertToStrArray(val)
		case "country":
			jn.Country = convertToStrArray(val)
		case "locality":
			jn.Locality = convertToStrArray(val)
		case "province":
			jn.Province = convertToStrArray(val)
		case "street_address":
			jn.StreetAddress = convertToStrArray(val)
		case "organization":
			jn.Organization = convertToStrArray(val)
		case "organizational_unit":
			jn.OrganizationalUnit = convertToStrArray(val)
		case "postal_code":
			jn.PostalCode = convertToStrArray(val)
		case "domain_component":
			jn.DomainComponent = convertToStrArray(val)
		default:
			attributeType := asn1.ObjectIdentifier{}
			valStr, okStr := val.(string)
			if !okStr {
				return fmt.Errorf("Expected string value for field %s, got %T", key, val)
			}

			for _, oidString := range strings.Split(valStr, ".") {
				oidInt, err := strconv.Atoi(oidString)
				if err != nil {
					return err
				}
				attributeType = append(attributeType, oidInt)
			}

			atv := AttributeTypeAndValue{
				Type:  attributeType,
				Value: val,
			}

			jn.UnknownAttributes = append(jn.UnknownAttributes, atv)
		}

	}

	return nil
}

type jsonAttributeTypeAndValue struct {
	Type  string      `json:"type"`
	Value interface{} `json:"value"`
}

func (a *AttributeTypeAndValue) MarshalJSON() ([]byte, error) {
	var enc jsonAttributeTypeAndValue
	enc.Type = a.Type.String()
	enc.Value = a.Value
	return json.Marshal(&enc)
}

type jsonExtension struct {
	Id       string `json:"id"`
	Critical bool   `json:"critical"`
	Value    []byte `json:"value"`
}

func (e *Extension) MarshalJSON() ([]byte, error) {
	ext := jsonExtension{
		Id:       e.Id.String(),
		Critical: e.Critical,
		Value:    e.Value,
	}
	return json.Marshal(ext)
}

type jsonOtherName struct {
	Id    string `json:"id"`
	Value []byte `json:"value"`
}

func (o *OtherName) MarshalJSON() ([]byte, error) {
	oName := jsonOtherName{
		Id:    o.Typeid.String(),
		Value: o.Value.Bytes,
	}
	return json.Marshal(oName)
}

func (o *OtherName) UnmarshalJSON(b []byte) error {
	var oName jsonOtherName

	if err := json.Unmarshal(b, &oName); err != nil {
		return err
	}

	arcs := strings.Split(oName.Id, ".")
	oid := make(asn1.ObjectIdentifier, len(arcs))

	for i, s := range arcs {
		tmp, err := strconv.ParseInt(s, 10, 32)
		if err != nil {
			return err
		}
		oid[i] = int(tmp)
	}
	o.Typeid = oid

	o.Value = asn1.RawValue{
		Tag:        0,
		Class:      asn1.ClassContextSpecific,
		IsCompound: true,
		Bytes:      oName.Value,
	}
	return nil
}

func (n *Name) MarshalJSON() ([]byte, error) {
	var enc jsonName
	attrs := n.ToRDNSequence()
	for _, attrSet := range attrs {
		for _, a := range attrSet {
			s, _ := a.Value.(string)
			if a.Type.Equal(oidCommonName) {
				enc.CommonName = append(enc.CommonName, s)
			} else if a.Type.Equal(oidSerialNumber) {
				enc.SerialNumber = append(enc.SerialNumber, s)
			} else if a.Type.Equal(oidCountry) {
				enc.Country = append(enc.Country, s)
			} else if a.Type.Equal(oidLocality) {
				enc.Locality = append(enc.Locality, s)
			} else if a.Type.Equal(oidProvince) {
				enc.Province = append(enc.Province, s)
			} else if a.Type.Equal(oidStreetAddress) {
				enc.StreetAddress = append(enc.StreetAddress, s)
			} else if a.Type.Equal(oidOrganization) {
				enc.Organization = append(enc.Organization, s)
			} else if a.Type.Equal(oidOrganizationalUnit) {
				enc.OrganizationalUnit = append(enc.OrganizationalUnit, s)
			} else if a.Type.Equal(oidPostalCode) {
				enc.PostalCode = append(enc.PostalCode, s)
			} else if a.Type.Equal(oidDomainComponent) {
				enc.DomainComponent = append(enc.DomainComponent, s)
			} else {
				enc.UnknownAttributes = append(enc.UnknownAttributes, a)
			}
		}
	}
	return json.Marshal(&enc)
}

func appendATV(names []AttributeTypeAndValue, fieldVals []string, asn1Id asn1.ObjectIdentifier) []AttributeTypeAndValue {
	if len(fieldVals) == 0 {
		return names
	}

	for _, val := range fieldVals {
		names = append(names, AttributeTypeAndValue{Type: asn1Id, Value: val})
	}

	return names
}

func (n *Name) UnmarshalJSON(b []byte) error {
	var jName jsonName

	if err := jName.UnmarshalJSON(b); err != nil {
		return err
	}

	// add everything to names
	n.Names = appendATV(n.Names, jName.Country, oidCountry)
	n.Names = appendATV(n.Names, jName.Organization, oidOrganization)
	n.Names = appendATV(n.Names, jName.OrganizationalUnit, oidOrganizationalUnit)
	n.Names = appendATV(n.Names, jName.Locality, oidLocality)
	n.Names = appendATV(n.Names, jName.Province, oidProvince)
	n.Names = appendATV(n.Names, jName.StreetAddress, oidStreetAddress)
	n.Names = appendATV(n.Names, jName.PostalCode, oidPostalCode)
	n.Names = appendATV(n.Names, jName.DomainComponent, oidDomainComponent)

	// populate specific fields
	n.Country = jName.Country
	n.Organization = jName.Organization
	n.OrganizationalUnit = jName.OrganizationalUnit
	n.Locality = jName.Locality
	n.Province = jName.Province
	n.StreetAddress = jName.StreetAddress
	n.PostalCode = jName.PostalCode
	n.DomainComponent = jName.DomainComponent

	// add first commonNames and serialNumbers to struct and Names
	if len(jName.CommonName) > 0 {
		n.CommonName = jName.CommonName[0]
		n.Names = append(n.Names, AttributeTypeAndValue{Type: oidCommonName, Value: jName.CommonName[0]})
	}
	if len(jName.SerialNumber) > 0 {
		n.SerialNumber = jName.SerialNumber[0]
		n.Names = append(n.Names, AttributeTypeAndValue{Type: oidSerialNumber, Value: jName.SerialNumber[0]})
	}

	// add extra commonNames and serialNumbers to extraNames
	if len(jName.CommonName) > 1 {
		for _, val := range jName.CommonName[1:] {
			n.ExtraNames = append(n.ExtraNames, AttributeTypeAndValue{Type: oidCommonName, Value: val})
		}
	}

	if len(jName.SerialNumber) > 1 {
		for _, val := range jName.SerialNumber[1:] {
			n.ExtraNames = append(n.ExtraNames, AttributeTypeAndValue{Type: oidSerialNumber, Value: val})
		}
	}

	return nil
}
<commit_msg>revert the small change that broke 1.5 support<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pkix

import (
	"encoding/asn1"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)

type jsonName struct {
	CommonName         []string
	SerialNumber       []string
	Country            []string
	Locality           []string
	Province           []string
	StreetAddress      []string
	Organization       []string
	OrganizationalUnit []string
	PostalCode         []string
	DomainComponent    []string //technically deprecated, but yolo
	UnknownAttributes  []AttributeTypeAndValue
}

func (jn *jsonName) MarshalJSON() ([]byte, error) {
	enc := make(map[string]interface{})
	if len(jn.CommonName) > 0 {
		enc["common_name"] = jn.CommonName
	}
	if len(jn.SerialNumber) > 0 {
		enc["serial_number"] = jn.SerialNumber
	}
	if len(jn.Country) > 0 {
		enc["country"] = jn.Country
	}
	if len(jn.Locality) > 0 {
		enc["locality"] = jn.Locality
	}
	if len(jn.Province) > 0 {
		enc["province"] = jn.Province
	}
	if len(jn.StreetAddress) > 0 {
		enc["street_address"] = jn.StreetAddress
	}
	if len(jn.Organization) > 0 {
		enc["organization"] = jn.Organization
	}
	if len(jn.OrganizationalUnit) > 0 {
		enc["organizational_unit"] = jn.OrganizationalUnit
	}
	if len(jn.PostalCode) > 0 {
		enc["postal_code"] = jn.PostalCode
	}
	if len(jn.DomainComponent) > 0 {
		enc["domain_component"] = jn.DomainComponent
	}
	for _, a := range jn.UnknownAttributes {
		enc[a.Type.String()] = a.Value
	}
	return json.Marshal(enc)
}

func convertToStrArray(i interface{}) []string {

	var strArray []string

	arr, _ := i.([]interface{})
	for _, val := range arr {
		if str, ok := val.(string); ok {
			strArray = append(strArray, str)
		}
	}

	return strArray
}

func (jn *jsonName) UnmarshalJSON(b []byte) error {
	nameMap := make(map[string]interface{})

	if err := json.Unmarshal(b, &nameMap); err != nil {
		return err
	}

	for key, val := range nameMap {
		switch key {
		case "common_name":
			jn.CommonName = convertToStrArray(val)
		case "serial_number":
			jn.SerialNumber = convertToStrArray(val)
		case "country":
			jn.Country = convertToStrArray(val)
		case "locality":
			jn.Locality = convertToStrArray(val)
		case "province":
			jn.Province = convertToStrArray(val)
		case "street_address":
			jn.StreetAddress = convertToStrArray(val)
		case "organization":
			jn.Organization = convertToStrArray(val)
		case "organizational_unit":
			jn.OrganizationalUnit = convertToStrArray(val)
		case "postal_code":
			jn.PostalCode = convertToStrArray(val)
		case "domain_component":
			jn.DomainComponent = convertToStrArray(val)
		default:
			attributeType := asn1.ObjectIdentifier{}
			valStr, okStr := val.(string)
			if !okStr {
				return fmt.Errorf("Expected string value for field %s, got %T", key, val)
			}

			for _, oidString := range strings.Split(valStr, ".") {
				oidInt, err := strconv.Atoi(oidString)
				if err != nil {
					return err
				}
				attributeType = append(attributeType, oidInt)
			}

			atv := AttributeTypeAndValue{
				Type:  attributeType,
				Value: val,
			}

			jn.UnknownAttributes = append(jn.UnknownAttributes, atv)
		}

	}

	return nil
}

type jsonAttributeTypeAndValue struct {
	Type  string      `json:"type"`
	Value interface{} `json:"value"`
}

func (a *AttributeTypeAndValue) MarshalJSON() ([]byte, error) {
	var enc jsonAttributeTypeAndValue
	enc.Type = a.Type.String()
	enc.Value = a.Value
	return json.Marshal(&enc)
}

type jsonExtension struct {
	Id       string `json:"id"`
	Critical bool   `json:"critical"`
	Value    []byte `json:"value"`
}

func (e *Extension) MarshalJSON() ([]byte, error) {
	ext := jsonExtension{
		Id:       e.Id.String(),
		Critical: e.Critical,
		Value:    e.Value,
	}
	return json.Marshal(ext)
}

type jsonOtherName struct {
	Id    string `json:"id"`
	Value []byte `json:"value"`
}

func (o *OtherName) MarshalJSON() ([]byte, error) {
	oName := jsonOtherName{
		Id:    o.Typeid.String(),
		Value: o.Value.Bytes,
	}
	return json.Marshal(oName)
}

const (
	asn1ClassUniversal       = 0
	asn1ClassApplication     = 1
	asn1ClassContextSpecific = 2
	asn1ClassPrivate         = 3
)

func (o *OtherName) UnmarshalJSON(b []byte) error {
	var oName jsonOtherName

	if err := json.Unmarshal(b, &oName); err != nil {
		return err
	}

	arcs := strings.Split(oName.Id, ".")
	oid := make(asn1.ObjectIdentifier, len(arcs))

	for i, s := range arcs {
		tmp, err := strconv.ParseInt(s, 10, 32)
		if err != nil {
			return err
		}
		oid[i] = int(tmp)
	}
	o.Typeid = oid

	o.Value = asn1.RawValue{
		Tag: 0,
		//TODO: change to asn1.ClassContextSpecific for next major release (i.e. 1.6)
		Class:      asn1ClassContextSpecific,
		IsCompound: true,
		Bytes:      oName.Value,
	}
	return nil
}

func (n *Name) MarshalJSON() ([]byte, error) {
	var enc jsonName
	attrs := n.ToRDNSequence()
	for _, attrSet := range attrs {
		for _, a := range attrSet {
			s, _ := a.Value.(string)
			if a.Type.Equal(oidCommonName) {
				enc.CommonName = append(enc.CommonName, s)
			} else if a.Type.Equal(oidSerialNumber) {
				enc.SerialNumber = append(enc.SerialNumber, s)
			} else if a.Type.Equal(oidCountry) {
				enc.Country = append(enc.Country, s)
			} else if a.Type.Equal(oidLocality) {
				enc.Locality = append(enc.Locality, s)
			} else if a.Type.Equal(oidProvince) {
				enc.Province = append(enc.Province, s)
			} else if a.Type.Equal(oidStreetAddress) {
				enc.StreetAddress = append(enc.StreetAddress, s)
			} else if a.Type.Equal(oidOrganization) {
				enc.Organization = append(enc.Organization, s)
			} else if a.Type.Equal(oidOrganizationalUnit) {
				enc.OrganizationalUnit = append(enc.OrganizationalUnit, s)
			} else if a.Type.Equal(oidPostalCode) {
				enc.PostalCode = append(enc.PostalCode, s)
			} else if a.Type.Equal(oidDomainComponent) {
				enc.DomainComponent = append(enc.DomainComponent, s)
			} else {
				enc.UnknownAttributes = append(enc.UnknownAttributes, a)
			}
		}
	}
	return json.Marshal(&enc)
}

func appendATV(names []AttributeTypeAndValue, fieldVals []string, asn1Id asn1.ObjectIdentifier) []AttributeTypeAndValue {
	if len(fieldVals) == 0 {
		return names
	}

	for _, val := range fieldVals {
		names = append(names, AttributeTypeAndValue{Type: asn1Id, Value: val})
	}

	return names
}

func (n *Name) UnmarshalJSON(b []byte) error {
	var jName jsonName

	if err := jName.UnmarshalJSON(b); err != nil {
		return err
	}

	// add everything to names
	n.Names = appendATV(n.Names, jName.Country, oidCountry)
	n.Names = appendATV(n.Names, jName.Organization, oidOrganization)
	n.Names = appendATV(n.Names, jName.OrganizationalUnit, oidOrganizationalUnit)
	n.Names = appendATV(n.Names, jName.Locality, oidLocality)
	n.Names = appendATV(n.Names, jName.Province, oidProvince)
	n.Names = appendATV(n.Names, jName.StreetAddress, oidStreetAddress)
	n.Names = appendATV(n.Names, jName.PostalCode, oidPostalCode)
	n.Names = appendATV(n.Names, jName.DomainComponent, oidDomainComponent)

	// populate specific fields
	n.Country = jName.Country
	n.Organization = jName.Organization
	n.OrganizationalUnit = jName.OrganizationalUnit
	n.Locality = jName.Locality
	n.Province = jName.Province
	n.StreetAddress = jName.StreetAddress
	n.PostalCode = jName.PostalCode
	n.DomainComponent = jName.DomainComponent

	// add first commonNames and serialNumbers to struct and Names
	if len(jName.CommonName) > 0 {
		n.CommonName = jName.CommonName[0]
		n.Names = append(n.Names, AttributeTypeAndValue{Type: oidCommonName, Value: jName.CommonName[0]})
	}
	if len(jName.SerialNumber) > 0 {
		n.SerialNumber = jName.SerialNumber[0]
		n.Names = append(n.Names, AttributeTypeAndValue{Type: oidSerialNumber, Value: jName.SerialNumber[0]})
	}

	// add extra commonNames and serialNumbers to extraNames
	if len(jName.CommonName) > 1 {
		for _, val := range jName.CommonName[1:] {
			n.ExtraNames = append(n.ExtraNames, AttributeTypeAndValue{Type: oidCommonName, Value: val})
		}
	}

	if len(jName.SerialNumber) > 1 {
		for _, val := range jName.SerialNumber[1:] {
			n.ExtraNames = append(n.ExtraNames, AttributeTypeAndValue{Type: oidSerialNumber, Value: val})
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package tgbot

import "encoding/json"

// Update represents an incoming update
type Update struct {
	UpdateID           int                 `json:"update_id"`
	Message            *Message            `json:"message"`
	EditedMessage      *Message            `json:"edited_message"`
	ChannelPost        *Message            `json:"channel_post"`
	EditedChannelPost  *Message            `json:"edited_channel_post"`
	InlineQuery        *InlineQuery        `json:"inline_query"`
	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
	CallbackQuery      *CallbackQuery      `json:"callback_query"`
	ShippingQuery      *ShippingQuery      `json:"shipping_query"`
	PreCheckoutQuery   *PreCheckoutQuery   `json:"pre_checkout_query"`
}

// Message represents a message
type Message struct {
	MessageID             int                `json:"message_id"`
	From                  *User              `json:"from"`
	Date                  int                `json:"date"`
	Chat                  *Chat              `json:"chat"`
	ForwardFrom           *User              `json:"forward_from"`
	ForwardFromChat       *Chat              `json:"forward_from_chat"`
	ForwardFromMessageID  int                `json:"forward_from_message_id"`
	ForwardSignature      string             `json:"forward_signature"`
	ForwardDate           int                `json:"forward_date"`
	ReplyToMessage        *Message           `json:"reply_to_message"`
	EditDate              int                `json:"edit_date"`
	AuthorSignature       string             `json:"author_signature"`
	Text                  string             `json:"text"`
	Entities              []*MessageEntity   `json:"entities"`
	Audio                 *Audio             `json:"audio"`
	Document              *Document          `json:"document"`
	Game                  *Game              `json:"game"`
	Photo                 []*PhotoSize       `json:"photo"`
	Sticker               *Sticker           `json:"sticker"`
	Video                 *Video             `json:"video"`
	Voice                 *Voice             `json:"voice"`
	VideoNote             *VideoNote         `json:"video_note"`
	NewChatMembers        []*User            `json:"new_chat_members"`
	Caption               string             `json:"caption"`
	Contact               *Contact           `json:"contact"`
	Location              *Location          `json:"location"`
	Venue                 *Venue             `json:"venue"`
	NewChatMember         *User              `json:"new_chat_member"`
	LeftChatMember        *User              `json:"left_chat_member"`
	NewChatTitle          string             `json:"new_chat_title"`
	NewChatPhoto          []*PhotoSize       `json:"new_chat_photo"`
	DeleteChatPhoto       bool               `json:"delete_chat_photo"`
	GroupChatCreated      bool               `json:"group_chat_created"`
	SupergroupChatCreated bool               `json:"supergroup_chat_created"`
	ChannelChatCreated    bool               `json:"channel_chat_created"`
	MigrateToChatID       int64              `json:"migrate_to_chat_id"`
	MigrateFromChatID     int64              `json:"migrate_from_chat_id"`
	PinnedMessage         *Message           `json:"pinned_message"`
	SuccessfulPayment     *SuccessfulPayment `json:"successful_payment"`
}

// User represents a user
type User struct {
	ID           int    `json:"id"`
	IsBot        bool   `json:"is_bot"`
	FirstName    string `json:"first_name"`
	LastName     string `json:"last_name"`
	Username     string `json:"username"`
	LanguageCode string `json:"language_code"`
}

// Chat represents a chat
type Chat struct {
	ID                          int64      `json:"id"`
	Type                        string     `json:"type"`
	Title                       string     `json:"title"`
	Username                    string     `json:"username"`
	FirstName                   string     `json:"first_name"`
	LastName                    string     `json:"last_name"`
	AllMembersAreAdministrators bool       `json:"all_members_are_administrators"`
	Photo                       *ChatPhoto `json:"photo"`
	Description                 string     `json:"description"`
	InviteLink                  string     `json:"invite_link"`
	PinnedMessage               *Message   `json:"pinned_message"`
}

// ChatPhoto represents a chat photo
type ChatPhoto struct {
	SmallFileID string `json:"small_file_id"`
	BigFileID   string `json:"big_file_id"`
}

// MessageEntity represents one special entity in a text message. For example, hashtags, usernames, URLs, etc.
type MessageEntity struct {
	Type   string `json:"type"`
	Offset int    `json:"offset"`
	Length int    `json:"length"`
	URL    string `json:"url"`
	User   *User  `json:"user"`
}

// Audio represents an audio file to be treated as music by the Telegram clients
type Audio struct {
	FileID    string `json:"file_id"`
	Duration  int    `json:"duration"`
	Performer string `json:"performer"`
	Title     string `json:"title"`
	MimeType  string `json:"mime_type"`
	FileSize  int    `json:"file_size"`
}

// Document represents a general file (as opposed to photos, voice messages and audio files)
type Document struct {
	FileID   string     `json:"file_id"`
	Thumb    *PhotoSize `json:"thumb"`
	FileName string     `json:"file_name"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// PhotoSize represents one size of a photo or a file / sticker thumbnail
type PhotoSize struct {
	FileID   string `json:"file_id"`
	Width    int    `json:"width"`
	Height   int    `json:"height"`
	FileSize int    `json:"file_size"`
}

// Game represents a game.
// Use BotFather to create and edit games, their short names will act as unique identifiers.
type Game struct {
	Title        string           `json:"title"`
	Description  string           `json:"description"`
	Photo        *PhotoSize       `json:"photo"`
	Text         string           `json:"text"`
	TextEntities []*MessageEntity `json:"text_entities"`
	Animation    *Animation       `json:"animation"`
}

// Animation represents an animation file to be displayed in the message containing a game
type Animation struct {
	FileID   string     `json:"file_id"`
	Thumb    *PhotoSize `json:"thumb"`
	FileName string     `json:"file_name"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// Sticker represents a sticker
type Sticker struct {
	FileID       string        `json:"file_id"`
	Width        int           `json:"width"`
	Height       int           `json:"height"`
	Thumb        *PhotoSize    `json:"thumb"`
	Emoji        string        `json:"emoji"`
	SetName      string        `json:"set_name"`
	MaskPosition *MaskPosition `json:"mask_position"`
	FileSize     int           `json:"file_size"`
}

// StickerSet represents a sticker set
type StickerSet struct {
	Name          string     `json:"name"`
	Title         string     `json:"title"`
	ContainsMasks bool       `json:"contains_masks"`
	Stickers      []*Sticker `json:"stickers"`
}

// MaskPosition describes the position on faces where a mask should be placed by default.
// TODO: Turn it into a method.
type MaskPosition struct {
	Point  string  `json:"point"`
	XShift float32 `json:"x_shift"`
	YShift float32 `json:"y_shift"`
	Scale  float32 `json:"scale"`
}

// Video represents a video file
type Video struct {
	FileID   string     `json:"file_id"`
	Width    int        `json:"width"`
	Height   int        `json:"height"`
	Duration int        `json:"duration"`
	Thumb    *PhotoSize `json:"thumb"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// Voice represents a voice note
type Voice struct {
	FileID   string `json:"file_id"`
	Duration int    `json:"duration"`
	MimeType string `json:"mime_type"`
	FileSize int    `json:"file_size"`
}

// VideoNote represents a video message
type VideoNote struct {
	FileID   string     `json:"file_id"`
	Length   int        `json:"length"`
	Duration int        `json:"duration"`
	Thumb    *PhotoSize `json:"thumb"`
	FileSize int        `json:"file_size"`
}

// Contact represents a phone contact
type Contact struct {
	PhoneNumber string `json:"phone_number"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
	UserID      int    `json:"user_id"`
}

// Location represents a point on the map
type Location struct {
	Longitude float32 `json:"longitude"`
	Latitude  float32 `json:"latitude"`
}

// Venue represents a venue
type Venue struct {
	Location     *Location `json:"location"`
	Title        string    `json:"title"`
	Address      string    `json:"address"`
	FoursquareID string    `json:"foursquare_id"`
}

// Invoice contains basic information about a invoice
type Invoice struct {
	Title          string `json:"title"`
	Description    string `json:"description"`
	StartParameter string `json:"start_parameter"`
	Currency       string `json:"currency"`
	TotalAmount    int    `json:"total_amount"`
}

// SuccessfulPayment contains basic information about a successful payment
type SuccessfulPayment struct {
	Currency                string     `json:"currency"`
	TotalAmount             int        `json:"total_amount"`
	InvoicePayload          string     `json:"invoice_payload"`
	ShippingOptionID        string     `json:"shipping_option_id"`
	OrderInfo               *OrderInfo `json:"order_info"`
	TelegramPaymentChargeID string     `json:"telegram_payment_charge_id"`
	ProviderPaymentChargeID string     `json:"provider_payment_charge_id"`
}

// OrderInfo represents information about an order
type OrderInfo struct {
	Name            string           `json:"name"`
	PhoneNumber     string           `json:"phone_number"`
	Email           string           `json:"email"`
	ShippingAddress *ShippingAddress `json:"shipping_address"`
}

// ShippingAddress represents a shipping address
type ShippingAddress struct {
	CountryCode string `json:"country_code"`
	State       string `json:"state"`
	City        string `json:"city"`
	StreetLine1 string `json:"street_line1"`
	StreetLine2 string `json:"street_line2"`
	PostCode    string `json:"post_code"`
}

// UserProfilePhotos represents a user's profile pictures
type UserProfilePhotos struct {
	TotalCount int            `json:"total_count"`
	Photos     [][]*PhotoSize `json:"photos"`
}

// File represents a file ready to be downloaded
type File struct {
	FileID   string `json:"file_id"`
	FileSize int    `json:"file_size"`
	FilePath string `json:"file_path"`
}

// ChatMember represents information about one member of a chat
type ChatMember struct {
	User                  *User  `json:"user"`
	Status                string `json:"status"`
	UntilDate             int    `json:"until_date"`
	CanBeEdited           bool   `json:"can_be_edited"`
	CanChangeInfo         bool   `json:"can_change_info"`
	CanPostMessages       bool   `json:"can_post_messages"`
	CanEditMessages       bool   `json:"can_edit_messages"`
	CanDeleteMessages     bool   `json:"can_delete_messages"`
	CanInviteUsers        bool   `json:"can_invite_users"`
	CanRestrictMembers    bool   `json:"can_restrict_members"`
	CanPinMessages        bool   `json:"can_pin_messages"`
	CanPromoteMembers     bool   `json:"can_promote_members"`
	CanSendMessages       bool   `json:"can_send_messages"`
	CanSendMediaMessages  bool   `json:"can_send_media_messages"`
	CanSendOtherMessages  bool   `json:"can_send_other_messages"`
	CanAddWebPagePreviews bool   `json:"can_add_web_page_previews"`
}

// CallbackGame is a placeholder, currently holds no information.
// Use BotFather to set up your game.
type CallbackGame struct{}

// InlineKeyboardButton represents one button of an inline keyboard.
// You must use exactly one of the optional fields.
type InlineKeyboardButton struct {
	Text                         string        `json:"text"`
	URL                          string        `json:"url"`
	CallbackData                 string        `json:"callback_data"`
	SwitchInlineQuery            string        `json:"switch_inline_query"`
	SwitchInlineQueryCurrentChat string        `json:"switch_inline_query_current_chat"`
	CallbackGame                 *CallbackGame `json:"callback_game"`
	Pay                          bool          `json:"pay"`
}

// KeyboardButton represents one button of the reply keyboard
type KeyboardButton struct {
	Text            string `json:"text"`
	RequestContact  bool   `json:"request_contact"`
	RequestLocation bool   `json:"request_location"`
}

// InlineQuery represents an incoming inline query.
// When the user sends an empty query, your bot could return some default or trending results.
type InlineQuery struct {
	ID       string    `json:"id"`
	From     *User     `json:"from"`
	Location *Location `json:"location"`
	Query    string    `json:"query"`
	Offset   string    `json:"offset"`
}

// ChosenInlineResult represents a result of an inline query
// that was chosen by the user and sent to their chat partner
type ChosenInlineResult struct {
	ResultID        string    `json:"result_id"`
	From            *User     `json:"from"`
	Location        *Location `json:"location"`
	InlineMessageID string    `json:"inline_message_id"`
	Query           string    `json:"query"`
}

// CallbackQuery represents an incoming callback query from a callback button
// in an inline keyboard. If the button that originated the query was attached
// to a message sent by the bot, the field message will be present.
type CallbackQuery struct {
	ID              string   `json:"id"`
	From            *User    `json:"from"`
	Message         *Message `json:"message"`
	InlineMessageID string   `json:"inline_message_id"`
	ChatInstance    string   `json:"chat_instance"`
	Data            string   `json:"data"`
	GameShortName   string   `json:"game_short_name"`
}

// ShippingQuery represents a shipping address
type ShippingQuery struct {
	ID              string           `json:"id"`
	From            *User            `json:"from"`
	InvoicePayload  string           `json:"invoice_payload"`
	ShippingAddress *ShippingAddress `json:"shipping_address"`
}

// PreCheckoutQuery represents information about an incoming pre-checkout query
type PreCheckoutQuery struct {
	ID               string     `json:"id"`
	From             *User      `json:"from"`
	Currency         string     `json:"currency"`
	TotalAmount      int        `json:"total_amount"`
	InvoicePayload   string     `json:"invoice_payload"`
	ShippingOptionID string     `json:"shipping_option_id"`
	OrderInfo        *OrderInfo `json:"order_info"`
}

type apiResponse struct {
	Ok          bool            `json:"ok"`
	Result      json.RawMessage `json:"result"`
	Description string          `json:"description"`
}
<commit_msg>Fix Game type<commit_after>package tgbot

import "encoding/json"

// Update represents an incoming update
type Update struct {
	UpdateID           int                 `json:"update_id"`
	Message            *Message            `json:"message"`
	EditedMessage      *Message            `json:"edited_message"`
	ChannelPost        *Message            `json:"channel_post"`
	EditedChannelPost  *Message            `json:"edited_channel_post"`
	InlineQuery        *InlineQuery        `json:"inline_query"`
	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
	CallbackQuery      *CallbackQuery      `json:"callback_query"`
	ShippingQuery      *ShippingQuery      `json:"shipping_query"`
	PreCheckoutQuery   *PreCheckoutQuery   `json:"pre_checkout_query"`
}

// Message represents a message
type Message struct {
	MessageID             int                `json:"message_id"`
	From                  *User              `json:"from"`
	Date                  int                `json:"date"`
	Chat                  *Chat              `json:"chat"`
	ForwardFrom           *User              `json:"forward_from"`
	ForwardFromChat       *Chat              `json:"forward_from_chat"`
	ForwardFromMessageID  int                `json:"forward_from_message_id"`
	ForwardSignature      string             `json:"forward_signature"`
	ForwardDate           int                `json:"forward_date"`
	ReplyToMessage        *Message           `json:"reply_to_message"`
	EditDate              int                `json:"edit_date"`
	AuthorSignature       string             `json:"author_signature"`
	Text                  string             `json:"text"`
	Entities              []*MessageEntity   `json:"entities"`
	Audio                 *Audio             `json:"audio"`
	Document              *Document          `json:"document"`
	Game                  *Game              `json:"game"`
	Photo                 []*PhotoSize       `json:"photo"`
	Sticker               *Sticker           `json:"sticker"`
	Video                 *Video             `json:"video"`
	Voice                 *Voice             `json:"voice"`
	VideoNote             *VideoNote         `json:"video_note"`
	NewChatMembers        []*User            `json:"new_chat_members"`
	Caption               string             `json:"caption"`
	Contact               *Contact           `json:"contact"`
	Location              *Location          `json:"location"`
	Venue                 *Venue             `json:"venue"`
	NewChatMember         *User              `json:"new_chat_member"`
	LeftChatMember        *User              `json:"left_chat_member"`
	NewChatTitle          string             `json:"new_chat_title"`
	NewChatPhoto          []*PhotoSize       `json:"new_chat_photo"`
	DeleteChatPhoto       bool               `json:"delete_chat_photo"`
	GroupChatCreated      bool               `json:"group_chat_created"`
	SupergroupChatCreated bool               `json:"supergroup_chat_created"`
	ChannelChatCreated    bool               `json:"channel_chat_created"`
	MigrateToChatID       int64              `json:"migrate_to_chat_id"`
	MigrateFromChatID     int64              `json:"migrate_from_chat_id"`
	PinnedMessage         *Message           `json:"pinned_message"`
	SuccessfulPayment     *SuccessfulPayment `json:"successful_payment"`
}

// User represents a user
type User struct {
	ID           int    `json:"id"`
	IsBot        bool   `json:"is_bot"`
	FirstName    string `json:"first_name"`
	LastName     string `json:"last_name"`
	Username     string `json:"username"`
	LanguageCode string `json:"language_code"`
}

// Chat represents a chat
type Chat struct {
	ID                          int64      `json:"id"`
	Type                        string     `json:"type"`
	Title                       string     `json:"title"`
	Username                    string     `json:"username"`
	FirstName                   string     `json:"first_name"`
	LastName                    string     `json:"last_name"`
	AllMembersAreAdministrators bool       `json:"all_members_are_administrators"`
	Photo                       *ChatPhoto `json:"photo"`
	Description                 string     `json:"description"`
	InviteLink                  string     `json:"invite_link"`
	PinnedMessage               *Message   `json:"pinned_message"`
}

// ChatPhoto represents a chat photo
type ChatPhoto struct {
	SmallFileID string `json:"small_file_id"`
	BigFileID   string `json:"big_file_id"`
}

// MessageEntity represents one special entity in a text message. For example, hashtags, usernames, URLs, etc.
type MessageEntity struct {
	Type   string `json:"type"`
	Offset int    `json:"offset"`
	Length int    `json:"length"`
	URL    string `json:"url"`
	User   *User  `json:"user"`
}

// Audio represents an audio file to be treated as music by the Telegram clients
type Audio struct {
	FileID    string `json:"file_id"`
	Duration  int    `json:"duration"`
	Performer string `json:"performer"`
	Title     string `json:"title"`
	MimeType  string `json:"mime_type"`
	FileSize  int    `json:"file_size"`
}

// Document represents a general file (as opposed to photos, voice messages and audio files)
type Document struct {
	FileID   string     `json:"file_id"`
	Thumb    *PhotoSize `json:"thumb"`
	FileName string     `json:"file_name"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// PhotoSize represents one size of a photo or a file / sticker thumbnail
type PhotoSize struct {
	FileID   string `json:"file_id"`
	Width    int    `json:"width"`
	Height   int    `json:"height"`
	FileSize int    `json:"file_size"`
}

// Game represents a game.
// Use BotFather to create and edit games, their short names will act as unique identifiers.
type Game struct {
	Title        string           `json:"title"`
	Description  string           `json:"description"`
	Photo        []*PhotoSize     `json:"photo"`
	Text         string           `json:"text"`
	TextEntities []*MessageEntity `json:"text_entities"`
	Animation    *Animation       `json:"animation"`
}

// Animation represents an animation file to be displayed in the message containing a game
type Animation struct {
	FileID   string     `json:"file_id"`
	Thumb    *PhotoSize `json:"thumb"`
	FileName string     `json:"file_name"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// Sticker represents a sticker
type Sticker struct {
	FileID       string        `json:"file_id"`
	Width        int           `json:"width"`
	Height       int           `json:"height"`
	Thumb        *PhotoSize    `json:"thumb"`
	Emoji        string        `json:"emoji"`
	SetName      string        `json:"set_name"`
	MaskPosition *MaskPosition `json:"mask_position"`
	FileSize     int           `json:"file_size"`
}

// StickerSet represents a sticker set
type StickerSet struct {
	Name          string     `json:"name"`
	Title         string     `json:"title"`
	ContainsMasks bool       `json:"contains_masks"`
	Stickers      []*Sticker `json:"stickers"`
}

// MaskPosition describes the position on faces where a mask should be placed by default.
// TODO: Turn it into a method.
type MaskPosition struct {
	Point  string  `json:"point"`
	XShift float32 `json:"x_shift"`
	YShift float32 `json:"y_shift"`
	Scale  float32 `json:"scale"`
}

// Video represents a video file
type Video struct {
	FileID   string     `json:"file_id"`
	Width    int        `json:"width"`
	Height   int        `json:"height"`
	Duration int        `json:"duration"`
	Thumb    *PhotoSize `json:"thumb"`
	MimeType string     `json:"mime_type"`
	FileSize int        `json:"file_size"`
}

// Voice represents a voice note
type Voice struct {
	FileID   string `json:"file_id"`
	Duration int    `json:"duration"`
	MimeType string `json:"mime_type"`
	FileSize int    `json:"file_size"`
}

// VideoNote represents a video message
type VideoNote struct {
	FileID   string     `json:"file_id"`
	Length   int        `json:"length"`
	Duration int        `json:"duration"`
	Thumb    *PhotoSize `json:"thumb"`
	FileSize int        `json:"file_size"`
}

// Contact represents a phone contact
type Contact struct {
	PhoneNumber string `json:"phone_number"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
	UserID      int    `json:"user_id"`
}

// Location represents a point on the map
type Location struct {
	Longitude float32 `json:"longitude"`
	Latitude  float32 `json:"latitude"`
}

// Venue represents a venue
type Venue struct {
	Location     *Location `json:"location"`
	Title        string    `json:"title"`
	Address      string    `json:"address"`
	FoursquareID string    `json:"foursquare_id"`
}

// Invoice contains basic information about a invoice
type Invoice struct {
	Title          string `json:"title"`
	Description    string `json:"description"`
	StartParameter string `json:"start_parameter"`
	Currency       string `json:"currency"`
	TotalAmount    int    `json:"total_amount"`
}

// SuccessfulPayment contains basic information about a successful payment
type SuccessfulPayment struct {
	Currency                string     `json:"currency"`
	TotalAmount             int        `json:"total_amount"`
	InvoicePayload          string     `json:"invoice_payload"`
	ShippingOptionID        string     `json:"shipping_option_id"`
	OrderInfo               *OrderInfo `json:"order_info"`
	TelegramPaymentChargeID string     `json:"telegram_payment_charge_id"`
	ProviderPaymentChargeID string     `json:"provider_payment_charge_id"`
}

// OrderInfo represents information about an order
type OrderInfo struct {
	Name            string           `json:"name"`
	PhoneNumber     string           `json:"phone_number"`
	Email           string           `json:"email"`
	ShippingAddress *ShippingAddress `json:"shipping_address"`
}

// ShippingAddress represents a shipping address
type ShippingAddress struct {
	CountryCode string `json:"country_code"`
	State       string `json:"state"`
	City        string `json:"city"`
	StreetLine1 string `json:"street_line1"`
	StreetLine2 string `json:"street_line2"`
	PostCode    string `json:"post_code"`
}

// UserProfilePhotos represents a user's profile pictures
type UserProfilePhotos struct {
	TotalCount int            `json:"total_count"`
	Photos     [][]*PhotoSize `json:"photos"`
}

// File represents a file ready to be downloaded
type File struct {
	FileID   string `json:"file_id"`
	FileSize int    `json:"file_size"`
	FilePath string `json:"file_path"`
}

// ChatMember represents information about one member of a chat
type ChatMember struct {
	User                  *User  `json:"user"`
	Status                string `json:"status"`
	UntilDate             int    `json:"until_date"`
	CanBeEdited           bool   `json:"can_be_edited"`
	CanChangeInfo         bool   `json:"can_change_info"`
	CanPostMessages       bool   `json:"can_post_messages"`
	CanEditMessages       bool   `json:"can_edit_messages"`
	CanDeleteMessages     bool   `json:"can_delete_messages"`
	CanInviteUsers        bool   `json:"can_invite_users"`
	CanRestrictMembers    bool   `json:"can_restrict_members"`
	CanPinMessages        bool   `json:"can_pin_messages"`
	CanPromoteMembers     bool   `json:"can_promote_members"`
	CanSendMessages       bool   `json:"can_send_messages"`
	CanSendMediaMessages  bool   `json:"can_send_media_messages"`
	CanSendOtherMessages  bool   `json:"can_send_other_messages"`
	CanAddWebPagePreviews bool   `json:"can_add_web_page_previews"`
}

// CallbackGame is a placeholder, currently holds no information.
// Use BotFather to set up your game.
type CallbackGame struct{}

// InlineKeyboardButton represents one button of an inline keyboard.
// You must use exactly one of the optional fields.
type InlineKeyboardButton struct {
	Text                         string        `json:"text"`
	URL                          string        `json:"url"`
	CallbackData                 string        `json:"callback_data"`
	SwitchInlineQuery            string        `json:"switch_inline_query"`
	SwitchInlineQueryCurrentChat string        `json:"switch_inline_query_current_chat"`
	CallbackGame                 *CallbackGame `json:"callback_game"`
	Pay                          bool          `json:"pay"`
}

// KeyboardButton represents one button of the reply keyboard
type KeyboardButton struct {
	Text            string `json:"text"`
	RequestContact  bool   `json:"request_contact"`
	RequestLocation bool   `json:"request_location"`
}

// InlineQuery represents an incoming inline query.
// When the user sends an empty query, your bot could return some default or trending results.
type InlineQuery struct {
	ID       string    `json:"id"`
	From     *User     `json:"from"`
	Location *Location `json:"location"`
	Query    string    `json:"query"`
	Offset   string    `json:"offset"`
}

// ChosenInlineResult represents a result of an inline query
// that was chosen by the user and sent to their chat partner
type ChosenInlineResult struct {
	ResultID        string    `json:"result_id"`
	From            *User     `json:"from"`
	Location        *Location `json:"location"`
	InlineMessageID string    `json:"inline_message_id"`
	Query           string    `json:"query"`
}

// CallbackQuery represents an incoming callback query from a callback button
// in an inline keyboard. If the button that originated the query was attached
// to a message sent by the bot, the field message will be present.
type CallbackQuery struct {
	ID              string   `json:"id"`
	From            *User    `json:"from"`
	Message         *Message `json:"message"`
	InlineMessageID string   `json:"inline_message_id"`
	ChatInstance    string   `json:"chat_instance"`
	Data            string   `json:"data"`
	GameShortName   string   `json:"game_short_name"`
}

// ShippingQuery represents a shipping address
type ShippingQuery struct {
	ID              string           `json:"id"`
	From            *User            `json:"from"`
	InvoicePayload  string           `json:"invoice_payload"`
	ShippingAddress *ShippingAddress `json:"shipping_address"`
}

// PreCheckoutQuery represents information about an incoming pre-checkout query
type PreCheckoutQuery struct {
	ID               string     `json:"id"`
	From             *User      `json:"from"`
	Currency         string     `json:"currency"`
	TotalAmount      int        `json:"total_amount"`
	InvoicePayload   string     `json:"invoice_payload"`
	ShippingOptionID string     `json:"shipping_option_id"`
	OrderInfo        *OrderInfo `json:"order_info"`
}

type apiResponse struct {
	Ok          bool            `json:"ok"`
	Result      json.RawMessage `json:"result"`
	Description string          `json:"description"`
}
<|endoftext|>


<commit_before>package eio

import (
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"encoding/json"
	"math/rand"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/golang/glog"
)

var emptyStringArray = make([]string, 0)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func sendError(writer http.ResponseWriter, e error, codes ...int) {
	httpCode, bizCode := http.StatusInternalServerError, 0
	if len(codes) > 0 {
		httpCode = codes[0]
	}
	if len(codes) > 1 {
		bizCode = codes[1]
	}
	writer.Header().Set("Content-Type", "application/json; charset=UTF8")
	writer.WriteHeader(httpCode)
	foo := struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	}{bizCode, e.Error()}
	if err := json.NewEncoder(writer).Encode(&foo); err != nil {
		panic(err)
	}
	glog.Warningln("ERR:", e)
}

func randomSessionID(seed uint32) string {
	bf := new(bytes.Buffer)
	for i := 0; i < 12; i++ {
		bf.WriteByte(byte(rand.Int31n(256)))
	}
	b := make([]byte, 4)
	binary.BigEndian.PutUint32(b, seed)
	for i := 1; i < 4; i++ {
		bf.WriteByte(b[i])
	}
	bs := bf.Bytes()
	s := base64.StdEncoding.EncodeToString(bs)
	s = strings.Replace(s, "/", "_", -1)
	s = strings.Replace(s, "+", "-", -1)
	return s
}

func now32() uint32 {
	return uint32(time.Now().Unix())
}

type queue struct {
	lock *sync.RWMutex
	q    []interface{}
}

func newQueue() *queue {
	foo := queue{
		lock: new(sync.RWMutex),
		q:    make([]interface{}, 0),
	}
	return &foo
}

func (p *queue) size() int {
	p.lock.RLock()
	p.lock.RUnlock()
	return len(p.q)
}

func (p *queue) append(item interface{}) {
	p.lock.Lock()
	p.q = append(p.q, item)
	p.lock.Unlock()
}

func (p *queue) pop() (interface{}, bool) {
	p.lock.Lock()
	defer p.lock.Unlock()
	if len(p.q) < 1 {
		return nil, false
	}
	var foo interface{}
	foo, p.q = p.q[0], p.q[1:]
	return foo, true
}
<commit_msg>add defer to the method of queue<commit_after>package eio

import (
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"encoding/json"
	"math/rand"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/golang/glog"
)

var emptyStringArray = make([]string, 0)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func sendError(writer http.ResponseWriter, e error, codes ...int) {
	httpCode, bizCode := http.StatusInternalServerError, 0
	if len(codes) > 0 {
		httpCode = codes[0]
	}
	if len(codes) > 1 {
		bizCode = codes[1]
	}
	writer.Header().Set("Content-Type", "application/json; charset=UTF8")
	writer.WriteHeader(httpCode)
	foo := struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	}{bizCode, e.Error()}
	if err := json.NewEncoder(writer).Encode(&foo); err != nil {
		panic(err)
	}
	glog.Warningln("ERR:", e)
}

func randomSessionID(seed uint32) string {
	bf := new(bytes.Buffer)
	for i := 0; i < 12; i++ {
		bf.WriteByte(byte(rand.Int31n(256)))
	}
	b := make([]byte, 4)
	binary.BigEndian.PutUint32(b, seed)
	for i := 1; i < 4; i++ {
		bf.WriteByte(b[i])
	}
	bs := bf.Bytes()
	s := base64.StdEncoding.EncodeToString(bs)
	s = strings.Replace(s, "/", "_", -1)
	s = strings.Replace(s, "+", "-", -1)
	return s
}

func now32() uint32 {
	return uint32(time.Now().Unix())
}

type queue struct {
	lock *sync.RWMutex
	q    []interface{}
}

func newQueue() *queue {
	foo := queue{
		lock: new(sync.RWMutex),
		q:    make([]interface{}, 0),
	}
	return &foo
}

func (p *queue) size() int {
	p.lock.RLock()
	defer p.lock.RUnlock()
	return len(p.q)
}

func (p *queue) append(item interface{}) {
	p.lock.Lock()
	p.q = append(p.q, item)
	p.lock.Unlock()
}

func (p *queue) pop() (interface{}, bool) {
	p.lock.Lock()
	defer p.lock.Unlock()
	if len(p.q) < 1 {
		return nil, false
	}
	var foo interface{}
	foo, p.q = p.q[0], p.q[1:]
	return foo, true
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"github.com/nsf/tulib"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

var invisible_rune_table = []rune{
	'@',  // 0
	'A',  // 1
	'B',  // 2
	'C',  // 3
	'D',  // 4
	'E',  // 5
	'F',  // 6
	'G',  // 7
	'H',  // 8
	'I',  // 9
	'J',  // 10
	'K',  // 11
	'L',  // 12
	'M',  // 13
	'N',  // 14
	'O',  // 15
	'P',  // 16
	'Q',  // 17
	'R',  // 18
	'S',  // 19
	'T',  // 20
	'U',  // 21
	'V',  // 22
	'W',  // 23
	'X',  // 24
	'Y',  // 25
	'Z',  // 26
	'[',  // 27
	'\\', // 28
	']',  // 29
	'^',  // 30
	'_',  // 31
}

func rune_advance_len(r rune, pos int) int {
	switch {
	case r == '\t':
		return tabstop_length - pos%tabstop_length
	case r < 32:
		// for invisible chars like ^R ^@ and such, two cells
		return 2
	}
	return 1
}

func vlen(data []byte, pos int) int {
	origin := pos
	for len(data) > 0 {
		r, rlen := utf8.DecodeRune(data)
		data = data[rlen:]
		pos += rune_advance_len(r, pos)
	}
	return pos - origin
}

func iter_nonspace_words(data []byte, cb func(word []byte)) {
	for {
		if len(data) == 0 {
			return
		}

		for is_space(data[0]) && len(data) > 0 {
			data = data[1:]
		}

		if len(data) == 0 {
			return
		}

		i := 0
		for i < len(data) && !is_space(data[i]) {
			i += 1
		}
		cb(data[:i])
		data = data[i:]
	}
}

func iter_words(data []byte, cb func(word []byte)) {
	for {
		if len(data) == 0 {
			return
		}

		r, rlen := utf8.DecodeRune(data)
		// skip non-word runes
		for !is_word(r) && len(data) > 0 {
			data = data[rlen:]
			r, rlen = utf8.DecodeRune(data)
		}

		if len(data) == 0 {
			return
		}

		// must be on a word rune
		i := 0
		for is_word(r) && i < len(data) {
			i += rlen
			r, rlen = utf8.DecodeRune(data[i:])
		}
		cb(data[:i])
		data = data[i:]
	}
}

func iter_words_backward(data []byte, cb func(word []byte)) {
	for {
		if len(data) == 0 {
			return
		}

		r, rlen := utf8.DecodeLastRune(data)
		// skip non-word runes
		for !is_word(r) && len(data) > 0 {
			data = data[:len(data)-rlen]
			r, rlen = utf8.DecodeLastRune(data)
		}

		if len(data) == 0 {
			return
		}

		// must be on a word rune
		i := len(data)
		for is_word(r) && i > 0 {
			i -= rlen
			r, rlen = utf8.DecodeLastRune(data[:i])
		}
		cb(data[i:])
		data = data[:i]
	}
}

func readdir_stat(dir string, f *os.File) ([]os.FileInfo, error) {
	names, err := f.Readdirnames(-1)
	if err != nil {
		return nil, err
	}

	fis := make([]os.FileInfo, len(names))
	for i, name := range names {
		fis[i], err = os.Stat(filepath.Join(dir, name))
		if err != nil {
			return nil, err
		}
	}
	return fis, nil
}

func index_first_non_space(s []byte) int {
	for i := 0; i < len(s); i++ {
		if s[i] != '\t' && s[i] != ' ' {
			return i
		}
	}
	return len(s)
}

func index_last_non_space(s []byte) int {
	for i := len(s) - 1; i >= 0; i-- {
		if s[i] != '\t' && s[i] != ' ' {
			return i
		}
	}
	return -1
}

func abs_path(filename string) string {
	path, err := filepath.Abs(filename)
	if err != nil {
		panic(err)
	}
	return path
}

func grow_byte_slice(s []byte, desired_cap int) []byte {
	if cap(s) < desired_cap {
		ns := make([]byte, len(s), desired_cap)
		copy(ns, s)
		return ns
	}
	return s
}

func insert_bytes(s []byte, offset int, data []byte) []byte {
	n := len(s) + len(data)
	s = grow_byte_slice(s, n)
	s = s[:n]
	copy(s[offset+len(data):], s[offset:])
	copy(s[offset:], data)
	return s
}

func copy_byte_slice(dst, src []byte) []byte {
	if cap(dst) < len(src) {
		dst = clone_byte_slice(src)
	}
	dst = dst[:len(src)]
	copy(dst, src)
	return dst
}

func clone_byte_slice(s []byte) []byte {
	c := make([]byte, len(s))
	copy(c, s)
	return c
}

// assumes the same line and a.boffset < b.offset order
func bytes_between(a, b cursor_location) []byte {
	return a.line.data[a.boffset:b.boffset]
}

func is_word(r rune) bool {
	return r == '_' || unicode.IsLetter(r) || unicode.IsNumber(r)
}

func is_space(b byte) bool {
	return b == ' ' || b == '\t' || b == '\n'
}

func find_place_for_rect(win, pref tulib.Rect) tulib.Rect {
	var vars [4]tulib.Rect

	vars[0] = pref.Intersection(win)
	if vars[0] == pref {
		// this is just a common path, everything fits in
		return pref
	}

	// If a rect doesn't fit in the window, try to select the most
	// optimal position amongst mirrored variants.

	// invert X
	vars[1] = pref
	vars[1].X = win.Width - pref.Width
	vars[1] = vars[1].Intersection(win)

	// invert Y
	vars[2] = pref
	vars[2].Y -= pref.Height + 1
	vars[2] = vars[2].Intersection(win)

	// invert X and Y
	vars[3] = pref
	vars[3].X = win.Width - pref.Width
	vars[3].Y -= pref.Height + 1
	vars[3] = vars[3].Intersection(win)

	optimal_i, optimal_w, optimal_h := 0, 0, 0
	// find optimal width
	for i := 0; i < 4; i++ {
		if vars[i].Width > optimal_w {
			optimal_w = vars[i].Width
		}
	}

	// find optimal height (amongst optimal widths) and its index
	for i := 0; i < 4; i++ {
		if vars[i].Width != optimal_w {
			continue
		}
		if vars[i].Height > optimal_h {
			optimal_h = vars[i].Height
			optimal_i = i
		}
	}
	return vars[optimal_i]
}

// Function will iterate 'data' contents, calling 'cb' on some data or on '\n',
// but never both. For example, given this data: "\n123\n123\n\n", it will call
// 'cb' 6 times: ['\n', '123', '\n', '123', '\n', '\n']
func iter_lines(data []byte, cb func([]byte)) {
	offset := 0
	for {
		if offset == len(data) {
			return
		}

		i := bytes.IndexByte(data[offset:], '\n')
		switch i {
		case -1:
			cb(data[offset:])
			return
		case 0:
			cb(data[offset : offset+1])
			offset++
			continue
		}

		cb(data[offset : offset+i])
		cb(data[offset+i : offset+i+1])
		offset += i + 1
	}
}

var double_comma = []byte(",,")

func split_double_csv(data []byte) (a, b []byte) {
	i := bytes.Index(data, double_comma)
	if i == -1 {
		return data, nil
	}

	return data[:i], data[i+2:]
}

type line_reader struct {
	data   []byte
	offset int
}

func new_line_reader(data []byte) line_reader {
	return line_reader{data, 0}
}

func (l *line_reader) read_line() []byte {
	data := l.data[l.offset:]
	i := bytes.Index(data, []byte{'\n'})
	if i == -1 {
		l.offset = len(l.data)
		return data
	}

	l.offset += i + 1
	return data[:i]
}

func atoi(data []byte) (int, error) {
	return strconv.Atoi(string(data))
}

func substitute_home(path string) string {
	if !strings.HasPrefix(path, "~") {
		return path
	}
	home := os.Getenv("HOME")
	if home == "" {
		panic("HOME is not set")
	}
	return filepath.Join(home, path[1:])
}

func substitute_symlinks(path string) string {
	if path == "" {
		return ""
	}
	after, err := filepath.EvalSymlinks(path)
	if err != nil {
		return path
	}

	if strings.HasSuffix(path, string(filepath.Separator)) {
		return after + string(filepath.Separator)
	}
	return after
}

func is_file_hidden(path string) bool {
	if path == "." || path == ".." {
		return true
	}

	if len(path) > 1 {
		if strings.HasPrefix(path, "./") {
			return false
		}
		if strings.HasPrefix(path, "..") {
			return false
		}
		if strings.HasPrefix(path, ".") {
			return true
		}
	}
	return false
}
<commit_msg>A couple of logic/bug fixes for util functions.<commit_after>package main

import (
	"bytes"
	"github.com/nsf/tulib"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

var invisible_rune_table = []rune{
	'@',  // 0
	'A',  // 1
	'B',  // 2
	'C',  // 3
	'D',  // 4
	'E',  // 5
	'F',  // 6
	'G',  // 7
	'H',  // 8
	'I',  // 9
	'J',  // 10
	'K',  // 11
	'L',  // 12
	'M',  // 13
	'N',  // 14
	'O',  // 15
	'P',  // 16
	'Q',  // 17
	'R',  // 18
	'S',  // 19
	'T',  // 20
	'U',  // 21
	'V',  // 22
	'W',  // 23
	'X',  // 24
	'Y',  // 25
	'Z',  // 26
	'[',  // 27
	'\\', // 28
	']',  // 29
	'^',  // 30
	'_',  // 31
}

func rune_advance_len(r rune, pos int) int {
	switch {
	case r == '\t':
		return tabstop_length - pos%tabstop_length
	case r < 32:
		// for invisible chars like ^R ^@ and such, two cells
		return 2
	}
	return 1
}

func vlen(data []byte, pos int) int {
	origin := pos
	for len(data) > 0 {
		r, rlen := utf8.DecodeRune(data)
		data = data[rlen:]
		pos += rune_advance_len(r, pos)
	}
	return pos - origin
}

func iter_nonspace_words(data []byte, cb func(word []byte)) {
	for {
		for len(data) > 0 && is_space(data[0]) {
			data = data[1:]
		}

		if len(data) == 0 {
			return
		}

		i := 0
		for i < len(data) && !is_space(data[i]) {
			i += 1
		}
		cb(data[:i])
		data = data[i:]
	}
}

func iter_words(data []byte, cb func(word []byte)) {
	for {
		if len(data) == 0 {
			return
		}

		r, rlen := utf8.DecodeRune(data)
		// skip non-word runes
		for !is_word(r) {
			data = data[rlen:]
			if len(data) == 0 {
				return
			}
			r, rlen = utf8.DecodeRune(data)
		}

		// must be on a word rune
		i := 0
		for is_word(r) && i < len(data) {
			i += rlen
			r, rlen = utf8.DecodeRune(data[i:])
		}
		cb(data[:i])
		data = data[i:]
	}
}

func iter_words_backward(data []byte, cb func(word []byte)) {
	for {
		if len(data) == 0 {
			return
		}

		r, rlen := utf8.DecodeLastRune(data)
		// skip non-word runes
		for !is_word(r) {
			data = data[:len(data)-rlen]
			if len(data) == 0 {
				return
			}
			r, rlen = utf8.DecodeLastRune(data)
		}

		// must be on a word rune
		i := len(data)
		for is_word(r) && i > 0 {
			i -= rlen
			r, rlen = utf8.DecodeLastRune(data[:i])
		}
		cb(data[i:])
		data = data[:i]
	}
}

func readdir_stat(dir string, f *os.File) ([]os.FileInfo, error) {
	names, err := f.Readdirnames(-1)
	if err != nil {
		return nil, err
	}

	fis := make([]os.FileInfo, len(names))
	for i, name := range names {
		fis[i], err = os.Stat(filepath.Join(dir, name))
		if err != nil {
			return nil, err
		}
	}
	return fis, nil
}

func index_first_non_space(s []byte) int {
	for i := 0; i < len(s); i++ {
		if s[i] != '\t' && s[i] != ' ' {
			return i
		}
	}
	return len(s)
}

func index_last_non_space(s []byte) int {
	for i := len(s) - 1; i >= 0; i-- {
		if s[i] != '\t' && s[i] != ' ' {
			return i
		}
	}
	return -1
}

func abs_path(filename string) string {
	path, err := filepath.Abs(filename)
	if err != nil {
		panic(err)
	}
	return path
}

func grow_byte_slice(s []byte, desired_cap int) []byte {
	if cap(s) < desired_cap {
		ns := make([]byte, len(s), desired_cap)
		copy(ns, s)
		return ns
	}
	return s
}

func insert_bytes(s []byte, offset int, data []byte) []byte {
	n := len(s) + len(data)
	s = grow_byte_slice(s, n)
	s = s[:n]
	copy(s[offset+len(data):], s[offset:])
	copy(s[offset:], data)
	return s
}

func copy_byte_slice(dst, src []byte) []byte {
	if cap(dst) < len(src) {
		dst = clone_byte_slice(src)
	}
	dst = dst[:len(src)]
	copy(dst, src)
	return dst
}

func clone_byte_slice(s []byte) []byte {
	c := make([]byte, len(s))
	copy(c, s)
	return c
}

// assumes the same line and a.boffset < b.offset order
func bytes_between(a, b cursor_location) []byte {
	return a.line.data[a.boffset:b.boffset]
}

func is_word(r rune) bool {
	return r == '_' || unicode.IsLetter(r) || unicode.IsNumber(r)
}

func is_space(b byte) bool {
	return b == ' ' || b == '\t' || b == '\n'
}

func find_place_for_rect(win, pref tulib.Rect) tulib.Rect {
	var vars [4]tulib.Rect

	vars[0] = pref.Intersection(win)
	if vars[0] == pref {
		// this is just a common path, everything fits in
		return pref
	}

	// If a rect doesn't fit in the window, try to select the most
	// optimal position amongst mirrored variants.

	// invert X
	vars[1] = pref
	vars[1].X = win.Width - pref.Width
	vars[1] = vars[1].Intersection(win)

	// invert Y
	vars[2] = pref
	vars[2].Y -= pref.Height + 1
	vars[2] = vars[2].Intersection(win)

	// invert X and Y
	vars[3] = pref
	vars[3].X = win.Width - pref.Width
	vars[3].Y -= pref.Height + 1
	vars[3] = vars[3].Intersection(win)

	optimal_i, optimal_w, optimal_h := 0, 0, 0
	// find optimal width
	for i := 0; i < 4; i++ {
		if vars[i].Width > optimal_w {
			optimal_w = vars[i].Width
		}
	}

	// find optimal height (amongst optimal widths) and its index
	for i := 0; i < 4; i++ {
		if vars[i].Width != optimal_w {
			continue
		}
		if vars[i].Height > optimal_h {
			optimal_h = vars[i].Height
			optimal_i = i
		}
	}
	return vars[optimal_i]
}

// Function will iterate 'data' contents, calling 'cb' on some data or on '\n',
// but never both. For example, given this data: "\n123\n123\n\n", it will call
// 'cb' 6 times: ['\n', '123', '\n', '123', '\n', '\n']
func iter_lines(data []byte, cb func([]byte)) {
	offset := 0
	for {
		if offset == len(data) {
			return
		}

		i := bytes.IndexByte(data[offset:], '\n')
		switch i {
		case -1:
			cb(data[offset:])
			return
		case 0:
			cb(data[offset : offset+1])
			offset++
			continue
		}

		cb(data[offset : offset+i])
		cb(data[offset+i : offset+i+1])
		offset += i + 1
	}
}

var double_comma = []byte(",,")

func split_double_csv(data []byte) (a, b []byte) {
	i := bytes.Index(data, double_comma)
	if i == -1 {
		return data, nil
	}

	return data[:i], data[i+2:]
}

type line_reader struct {
	data   []byte
	offset int
}

func new_line_reader(data []byte) line_reader {
	return line_reader{data, 0}
}

func (l *line_reader) read_line() []byte {
	data := l.data[l.offset:]
	i := bytes.Index(data, []byte{'\n'})
	if i == -1 {
		l.offset = len(l.data)
		return data
	}

	l.offset += i + 1
	return data[:i]
}

func atoi(data []byte) (int, error) {
	return strconv.Atoi(string(data))
}

func substitute_home(path string) string {
	if !strings.HasPrefix(path, "~") {
		return path
	}
	home := os.Getenv("HOME")
	if home == "" {
		panic("HOME is not set")
	}
	return filepath.Join(home, path[1:])
}

func substitute_symlinks(path string) string {
	if path == "" {
		return ""
	}
	after, err := filepath.EvalSymlinks(path)
	if err != nil {
		return path
	}

	if strings.HasSuffix(path, string(filepath.Separator)) {
		return after + string(filepath.Separator)
	}
	return after
}

func is_file_hidden(path string) bool {
	if path == "." || path == ".." {
		return true
	}

	if len(path) > 1 {
		if strings.HasPrefix(path, "./") {
			return false
		}
		if strings.HasPrefix(path, "..") {
			return false
		}
		if strings.HasPrefix(path, ".") {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func execute(cmd *exec.Cmd) error {
	fmt.Println("+", strings.Join(cmd.Args, " "))

	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	return cmd.Run()
}
<commit_msg>Inject available env variables into commands (#33)<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func execute(cmd *exec.Cmd) error {
	fmt.Println("+", strings.Join(cmd.Args, " "))

	cmd.Env = os.Environ()
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	return cmd.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.crypto/bcrypt"
	"encoding/base64"
	"github.com/moln/httpextra"
	"net/http"
	"strings"
)

// Validations validates a set of tests, returning a slice of validation errors if any.
func Validations(tests ...func() (error, error)) ([]string, error) {
	var (
		validationErrs []string
		fatal          error
		err            error
	)

	for _, test := range tests {
		err, fatal = test()
		if fatal != nil {
			break
		}

		if err != nil {
			if validationErrs == nil {
				validationErrs = make([]string, 0)
			}

			validationErrs = append(validationErrs, err.Error())
		}
	}

	if fatal != nil {
		return nil, fatal
	} else {
		return validationErrs, fatal
	}
}

// HandleValidations responds to a request if any failures or validation errors.
func HandleValidations(rw http.ResponseWriter, req *http.Request, errs []string, err error) bool {
	if errs != nil || err != nil {
		msg := make(map[string]interface{})
		status := http.StatusBadRequest
		res := &httpextra.Response{ContentTypes, rw, req}

		if err != nil {
			msg["error"] = err.Error()
			status = http.StatusInternalServerError
		} else {
			msg["errors"] = errs
		}

		res.Send(msg, status)
		return false
	}

	return true
}

// Authenticate authenticates the request handling responses for required auth.
func Authenticate(conn *Conn, rw http.ResponseWriter, req *http.Request) *User {
	authorization := req.Header.Get("Authorization")
	authType := ""
	authValue := ""

	sendErr := func(err string, status int) {
		if status == http.StatusUnauthorized {
			rw.Header().Set("WWW-Authenticate", "Token")
		}

		res := &httpextra.Response{ContentTypes, rw, req}
		res.Send(map[string]string{"error": err}, status)
	}

	if authorization == "" {
		sendErr(http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return nil
	}

	// Split auth type and value
	authSplit := strings.SplitN(authorization, " ", 2)
	authType = strings.ToLower(authSplit[0])

	if len(authSplit) < 2 || authSplit[1] == "" {
		sendErr(ErrNoAuthorizationValue.Error(), http.StatusUnauthorized)
		return nil
	}
	authValue = authSplit[1]

	if authType == "token" {
		user, err := conn.GetUserByToken(authValue)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}

		if user != nil {
			return user
		}
	}

	if authType == "basic" {
		data, err := base64.StdEncoding.DecodeString(authValue)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}
		dataSplit := strings.SplitN(string(data), ":", 2)
		name := dataSplit[0]

		if len(dataSplit) < 2 || dataSplit[1] == "" {
			sendErr(ErrNoAuthorizationPassword.Error(), http.StatusUnauthorized)
			return nil
		}

		user, err := conn.GetUser(name)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}

		if user != nil {
			matches, err := MatchPass(dataSplit[1], user.Password)
			if err != nil {
				sendErr(err.Error(), http.StatusInternalServerError)
				return nil
			}

			if matches {
				return user
			}
		}
	}

	sendErr(http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
	return nil
}

// MatchPass checks if a given password matches a given hashed password
func MatchPass(plainPass, hashPass string) (bool, error) {
	match := false

	err := bcrypt.CompareHashAndPassword([]byte(hashPass), []byte(plainPass))
	if err == nil {
		match = true
	}
	if err == bcrypt.ErrMismatchedHashAndPassword {
		err = nil
	}

	return match, err
}
<commit_msg>Basic authentication compliance.<commit_after>package main

import (
	"code.google.com/p/go.crypto/bcrypt"
	"encoding/base64"
	"github.com/moln/httpextra"
	"net/http"
	"strings"
)

// Validations validates a set of tests, returning a slice of validation errors if any.
func Validations(tests ...func() (error, error)) ([]string, error) {
	var (
		validationErrs []string
		fatal          error
		err            error
	)

	for _, test := range tests {
		err, fatal = test()
		if fatal != nil {
			break
		}

		if err != nil {
			if validationErrs == nil {
				validationErrs = make([]string, 0)
			}

			validationErrs = append(validationErrs, err.Error())
		}
	}

	if fatal != nil {
		return nil, fatal
	} else {
		return validationErrs, fatal
	}
}

// HandleValidations responds to a request if any failures or validation errors.
func HandleValidations(rw http.ResponseWriter, req *http.Request, errs []string, err error) bool {
	if errs != nil || err != nil {
		msg := make(map[string]interface{})
		status := http.StatusBadRequest
		res := &httpextra.Response{ContentTypes, rw, req}

		if err != nil {
			msg["error"] = err.Error()
			status = http.StatusInternalServerError
		} else {
			msg["errors"] = errs
		}

		res.Send(msg, status)
		return false
	}

	return true
}

// Authenticate authenticates the request handling responses for required auth.
func Authenticate(conn *Conn, rw http.ResponseWriter, req *http.Request) *User {
	authorization := req.Header.Get("Authorization")
	authType := ""
	authValue := ""

	sendErr := func(err string, status int) {
		if status == http.StatusUnauthorized {
			if authType == "" {
				authType = "token"
			}
			params := "realm=\"" + req.Host + "\""

			rw.Header().Set("WWW-Authenticate", strings.Title(authType)+" "+params)
		}

		res := &httpextra.Response{ContentTypes, rw, req}
		res.Send(map[string]string{"error": err}, status)
	}

	if authorization == "" {
		sendErr(http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return nil
	}

	// Split auth type and value
	authSplit := strings.SplitN(authorization, " ", 2)
	authType = strings.ToLower(authSplit[0])

	if len(authSplit) < 2 || authSplit[1] == "" {
		sendErr(ErrNoAuthorizationValue.Error(), http.StatusUnauthorized)
		return nil
	}
	authValue = authSplit[1]

	if authType == "token" {
		user, err := conn.GetUserByToken(authValue)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}

		if user != nil {
			return user
		}
	}

	if authType == "basic" {
		data, err := base64.StdEncoding.DecodeString(authValue)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}
		dataSplit := strings.SplitN(string(data), ":", 2)
		name := dataSplit[0]

		if len(dataSplit) < 2 || dataSplit[1] == "" {
			sendErr(ErrNoAuthorizationPassword.Error(), http.StatusUnauthorized)
			return nil
		}

		user, err := conn.GetUser(name)
		if err != nil {
			sendErr(err.Error(), http.StatusInternalServerError)
			return nil
		}

		if user != nil {
			matches, err := MatchPass(dataSplit[1], user.Password)
			if err != nil {
				sendErr(err.Error(), http.StatusInternalServerError)
				return nil
			}

			if matches {
				return user
			}
		}
	}

	sendErr(http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
	return nil
}

// MatchPass checks if a given password matches a given hashed password
func MatchPass(plainPass, hashPass string) (bool, error) {
	match := false

	err := bcrypt.CompareHashAndPassword([]byte(hashPass), []byte(plainPass))
	if err == nil {
		match = true
	}
	if err == bcrypt.ErrMismatchedHashAndPassword {
		err = nil
	}

	return match, err
}
<|endoftext|>


<commit_before>package zmq3

import (
	"fmt"
)

/*
Send multi-part message on socket.

Any `[]string' or `[][]byte' is split into separate `string's or `[]byte's

Any other part that isn't a `string' or `[]byte' is converted
to `string' with `fmt.Sprintf("%v", part)'.

Returns total bytes sent.
*/
func (soc *Socket) SendMessage(parts ...interface{}) (total int, err error) {
	return soc.sendMessage(0, parts...)
}

/*
Like SendMessage(), but adding the DONTWAIT flag.
*/
func (soc *Socket) SendMessageDontwait(parts ...interface{}) (total int, err error) {
	return soc.sendMessage(DONTWAIT, parts...)
}

func (soc *Socket) sendMessage(dontwait Flag, parts ...interface{}) (total int, err error) {
	// TODO: make this faster

	// flatten first, just in case the last part may be an empty []string or [][]byte
	pp := make([]interface{}, 0)
	for _, p := range parts {
		switch t := p.(type) {
		case []string:
			for _, s := range t {
				pp = append(pp, s)
			}
		case [][]byte:
			for _, b := range t {
				pp = append(pp, b)
			}
		default:
			pp = append(pp, t)
		}
	}

	n := len(pp)
	if n == 0 {
		return
	}
	opt := SNDMORE | dontwait
	for i, p := range pp {
		if i == n-1 {
			opt = dontwait
		}
		switch t := p.(type) {
		case string:
			j, e := soc.Send(t, opt)
			if e == nil {
				total += j
			} else {
				return -1, e
			}
		case []byte:
			j, e := soc.SendBytes(t, opt)
			if e == nil {
				total += j
			} else {
				return -1, e
			}
		default:
			j, e := soc.Send(fmt.Sprintf("%v", t), opt)
			if e == nil {
				total += j
			} else {
				return -1, e
			}
		}
	}
	return
}

/*
Receive parts as message from socket.

Returns last non-nil error code.
*/
func (soc *Socket) RecvMessage(flags Flag) (msg []string, err error) {
	msg = make([]string, 0)
	for {
		s, e := soc.Recv(flags)
		if e == nil {
			msg = append(msg, s)
		} else {
			return msg[0:0], e
		}
		more, e := soc.GetRcvmore()
		if e == nil {
			if !more {
				break
			}
		} else {
			return msg[0:0], e
		}
	}
	return
}

/*
Receive parts as message from socket.

Returns last non-nil error code.
*/
func (soc *Socket) RecvMessageBytes(flags Flag) (msg [][]byte, err error) {
	msg = make([][]byte, 0)
	for {
		b, e := soc.RecvBytes(flags)
		if e == nil {
			msg = append(msg, b)
		} else {
			return msg[0:0], e
		}
		more, e := soc.GetRcvmore()
		if e == nil {
			if !more {
				break
			}
		} else {
			return msg[0:0], e
		}
	}
	return
}
<commit_msg>faster SendMessage() and SendMessageDontwait()<commit_after>package zmq3

import (
	"fmt"
)

/*
Send multi-part message on socket.

Any `[]string' or `[][]byte' is split into separate `string's or `[]byte's

Any other part that isn't a `string' or `[]byte' is converted
to `string' with `fmt.Sprintf("%v", part)'.

Returns total bytes sent.
*/
func (soc *Socket) SendMessage(parts ...interface{}) (total int, err error) {
	return soc.sendMessage(0, parts...)
}

/*
Like SendMessage(), but adding the DONTWAIT flag.
*/
func (soc *Socket) SendMessageDontwait(parts ...interface{}) (total int, err error) {
	return soc.sendMessage(DONTWAIT, parts...)
}

func (soc *Socket) sendMessage(dontwait Flag, parts ...interface{}) (total int, err error) {

	var last int
PARTS:
	for last = len(parts) - 1; last >= 0; last-- {
		switch t := parts[last].(type) {
		case []string:
			if len(t) > 0 {
				break PARTS
			}
		case [][]byte:
			if len(t) > 0 {
				break PARTS
			}
		default:
			break PARTS
		}
	}

	opt := SNDMORE | dontwait
	for i := 0; i <= last; i++ {
		if i == last {
			opt = dontwait
		}
		switch t := parts[i].(type) {
		case []string:
			opt = SNDMORE | dontwait
			n := len(t) - 1
			for j, s := range t {
				if j == n && i == last {
					opt = dontwait
				}
				c, e := soc.Send(s, opt)
				if e == nil {
					total += c
				} else {
					return -1, e
				}
			}
		case [][]byte:
			opt = SNDMORE | dontwait
			n := len(t) - 1
			for j, b := range t {
				if j == n && i == last {
					opt = dontwait
				}
				c, e := soc.SendBytes(b, opt)
				if e == nil {
					total += c
				} else {
					return -1, e
				}
			}
		case string:
			c, e := soc.Send(t, opt)
			if e == nil {
				total += c
			} else {
				return -1, e
			}
		case []byte:
			c, e := soc.SendBytes(t, opt)
			if e == nil {
				total += c
			} else {
				return -1, e
			}
		default:
			c, e := soc.Send(fmt.Sprintf("%v", t), opt)
			if e == nil {
				total += c
			} else {
				return -1, e
			}
		}
	}
	return
}

/*
Receive parts as message from socket.

Returns last non-nil error code.
*/
func (soc *Socket) RecvMessage(flags Flag) (msg []string, err error) {
	msg = make([]string, 0)
	for {
		s, e := soc.Recv(flags)
		if e == nil {
			msg = append(msg, s)
		} else {
			return msg[0:0], e
		}
		more, e := soc.GetRcvmore()
		if e == nil {
			if !more {
				break
			}
		} else {
			return msg[0:0], e
		}
	}
	return
}

/*
Receive parts as message from socket.

Returns last non-nil error code.
*/
func (soc *Socket) RecvMessageBytes(flags Flag) (msg [][]byte, err error) {
	msg = make([][]byte, 0)
	for {
		b, e := soc.RecvBytes(flags)
		if e == nil {
			msg = append(msg, b)
		} else {
			return msg[0:0], e
		}
		more, e := soc.GetRcvmore()
		if e == nil {
			if !more {
				break
			}
		} else {
			return msg[0:0], e
		}
	}
	return
}
<|endoftext|>


<commit_before>package mastodon

import (
	"fmt"
	"strings"
)

// GeneratePlaceholders returns the field placeholders for use in SQL queries.
func GeneratePlaceholders(num int) string {
	placeholders := ""
	for i := 0; i < num; i++ {
		placeholders += fmt.Sprintf("$%d, ", i+1)
	}
	return strings.TrimSuffix(placeholders, ", ")
}
<commit_msg>Added a named placeholder function.<commit_after>package mastodon

import (
	"fmt"
	"strings"
)

// GeneratePlaceholders returns the field placeholders for use in SQL queries.
func GeneratePlaceholders(num int) string {
	placeholders := ""
	for i := 0; i < num; i++ {
		placeholders += fmt.Sprintf("$%d, ", i+1)
	}
	return strings.TrimSuffix(placeholders, ", ")
}

// GenerateNamedPlaceholders returns named placeholders (:field_name) for use in SQL queries.
func GenerateNamedPlaceholders(fields []string) string {
	placeholders := ""
	for _, field := range fields {
		placeholders += fmt.Sprintf(":%s, ", field)
	}
	return strings.TrimSuffix(placeholders, ", ")
}
<|endoftext|>