<commit_before>package types

import (
	"os"
	"time"

	"github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/engine-api/types/registry"
	"github.com/docker/go-connections/nat"
)

// ContainerCreateResponse contains the information returned to a client on the
// creation of a new container.
type ContainerCreateResponse struct {
	// ID is the ID of the created container.
	ID string `json:"Id"`

	// Warnings are any warnings encountered during the creation of the container.
	Warnings []string `json:"Warnings"`
}

// ContainerExecCreateResponse contains response of Remote API:
// POST "/containers/{name:.*}/exec"
type ContainerExecCreateResponse struct {
	// ID is the exec ID.
	ID string `json:"Id"`
}

// ContainerUpdateResponse contains response of Remote API:
// POST /containers/{name:.*}/update
type ContainerUpdateResponse struct {
	// Warnings are any warnings encountered during the updating of the container.
	Warnings []string `json:"Warnings"`
}

// AuthResponse contains response of Remote API:
// POST "/auth"
type AuthResponse struct {
	// Status is the authentication status
	Status string `json:"Status"`
}

// ContainerWaitResponse contains response of Remote API:
// POST "/containers/"+containerID+"/wait"
type ContainerWaitResponse struct {
	// StatusCode is the status code of the wait job
	StatusCode int `json:"StatusCode"`
}

// ContainerCommitResponse contains response of Remote API:
// POST "/commit?container="+containerID
type ContainerCommitResponse struct {
	ID string `json:"Id"`
}

// ContainerChange contains response of Remote API:
// GET "/containers/{name:.*}/changes"
type ContainerChange struct {
	Kind int
	Path string
}

// ImageHistory contains response of Remote API:
// GET "/images/{name:.*}/history"
type ImageHistory struct {
	ID        string `json:"Id"`
	Created   int64
	CreatedBy string
	Tags      []string
	Size      int64
	Comment   string
}

// ImageDelete contains response of Remote API:
// DELETE "/images/{name:.*}"
type ImageDelete struct {
	Untagged string `json:",omitempty"`
	Deleted  string `json:",omitempty"`
}

// Image contains response of Remote API:
// GET "/images/json"
type Image struct {
	ID          string `json:"Id"`
	ParentID    string `json:"ParentId"`
	RepoTags    []string
	RepoDigests []string
	Created     int64
	Size        int64
	VirtualSize int64
	Labels      map[string]string
}

// GraphDriverData returns Image's graph driver config info
// when calling inspect command
type GraphDriverData struct {
	Name string
	Data map[string]string
}

// ImageInspect contains response of Remote API:
// GET "/images/{name:.*}/json"
type ImageInspect struct {
	ID              string `json:"Id"`
	RepoTags        []string
	RepoDigests     []string
	Parent          string
	Comment         string
	Created         string
	Container       string
	ContainerConfig *container.Config
	DockerVersion   string
	Author          string
	Config          *container.Config
	Architecture    string
	Os              string
	Size            int64
	VirtualSize     int64
	GraphDriver     GraphDriverData
}

// Port stores open ports info of container
// e.g. {"PrivatePort": 8080, "PublicPort": 80, "Type": "tcp"}
type Port struct {
	IP          string `json:",omitempty"`
	PrivatePort int
	PublicPort  int `json:",omitempty"`
	Type        string
}

// Container contains response of Remote API:
// GET  "/containers/json"
type Container struct {
	ID         string `json:"Id"`
	Names      []string
	Image      string
	ImageID    string
	Command    string
	Created    int64
	Ports      []Port
	SizeRw     int64 `json:",omitempty"`
	SizeRootFs int64 `json:",omitempty"`
	Labels     map[string]string
	Status     string
	HostConfig struct {
		NetworkMode string `json:",omitempty"`
	}
	NetworkSettings *SummaryNetworkSettings
}

// CopyConfig contains request body of Remote API:
// POST "/containers/"+containerID+"/copy"
type CopyConfig struct {
	Resource string
}

// ContainerPathStat is used to encode the header from
// GET "/containers/{name:.*}/archive"
// "Name" is the file or directory name.
type ContainerPathStat struct {
	Name       string      `json:"name"`
	Size       int64       `json:"size"`
	Mode       os.FileMode `json:"mode"`
	Mtime      time.Time   `json:"mtime"`
	LinkTarget string      `json:"linkTarget"`
}

// ContainerProcessList contains response of Remote API:
// GET "/containers/{name:.*}/top"
type ContainerProcessList struct {
	Processes [][]string
	Titles    []string
}

// Version contains response of Remote API:
// GET "/version"
type Version struct {
	Version       string
	APIVersion    string `json:"ApiVersion"`
	GitCommit     string
	GoVersion     string
	Os            string
	Arch          string
	KernelVersion string `json:",omitempty"`
	Experimental  bool   `json:",omitempty"`
	BuildTime     string `json:",omitempty"`
}

// Info contains response of Remote API:
// GET "/info"
type Info struct {
	ID                 string
	Containers         int
	Images             int
	Driver             string
	DriverStatus       [][2]string
	Plugins            PluginsInfo
	MemoryLimit        bool
	SwapLimit          bool
	CPUCfsPeriod       bool `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool `json:"CpuCfsQuota"`
	CPUShares          bool
	CPUSet             bool
	IPv4Forwarding     bool
	BridgeNfIptables   bool
	BridgeNfIP6tables  bool `json:"BridgeNfIp6tables"`
	Debug              bool
	NFd                int
	OomKillDisable     bool
	NGoroutines        int
	SystemTime         string
	ExecutionDriver    string
	LoggingDriver      string
	NEventsListener    int
	KernelVersion      string
	OperatingSystem    string
	OSType             string
	Architecture       string
	IndexServerAddress string
	RegistryConfig     *registry.ServiceConfig
	InitSha1           string
	InitPath           string
	NCPU               int
	MemTotal           int64
	DockerRootDir      string
	HTTPProxy          string `json:"HttpProxy"`
	HTTPSProxy         string `json:"HttpsProxy"`
	NoProxy            string
	Name               string
	Labels             []string
	ExperimentalBuild  bool
	ServerVersion      string
	ClusterStore       string
	ClusterAdvertise   string
}

// PluginsInfo is temp struct holds Plugins name
// registered with docker daemon. It used by Info struct
type PluginsInfo struct {
	// List of Volume plugins registered
	Volume []string
	// List of Network plugins registered
	Network []string
	// List of Authorization plugins registered
	Authorization []string
}

// ExecStartCheck is a temp struct used by execStart
// Config fields is part of ExecConfig in runconfig package
type ExecStartCheck struct {
	// ExecStart will first check if it's detached
	Detach bool
	// Check if there's a tty
	Tty bool
}

// ContainerState stores container's running state
// it's part of ContainerJSONBase and will return by "inspect" command
type ContainerState struct {
	Status     string
	Running    bool
	Paused     bool
	Restarting bool
	OOMKilled  bool
	Dead       bool
	Pid        int
	ExitCode   int
	Error      string
	StartedAt  string
	FinishedAt string
}

// ContainerJSONBase contains response of Remote API:
// GET "/containers/{name:.*}/json"
type ContainerJSONBase struct {
	ID              string `json:"Id"`
	Created         string
	Path            string
	Args            []string
	State           *ContainerState
	Image           string
	ResolvConfPath  string
	HostnamePath    string
	HostsPath       string
	LogPath         string
	Name            string
	RestartCount    int
	Driver          string
	MountLabel      string
	ProcessLabel    string
	AppArmorProfile string
	ExecIDs         []string
	HostConfig      *container.HostConfig
	GraphDriver     GraphDriverData
	SizeRw          *int64 `json:",omitempty"`
	SizeRootFs      *int64 `json:",omitempty"`
}

// ContainerJSON is newly used struct along with MountPoint
type ContainerJSON struct {
	*ContainerJSONBase
	Mounts          []MountPoint
	Config          *container.Config
	NetworkSettings *NetworkSettings
}

// NetworkSettings exposes the network settings in the api
type NetworkSettings struct {
	NetworkSettingsBase
	DefaultNetworkSettings
	Networks map[string]*network.EndpointSettings
}

// SummaryNetworkSettings provides a summary of container's networks
// in /containers/json
type SummaryNetworkSettings struct {
	Networks map[string]*network.EndpointSettings
}

// NetworkSettingsBase holds basic information about networks
type NetworkSettingsBase struct {
	Bridge                 string
	SandboxID              string
	HairpinMode            bool
	LinkLocalIPv6Address   string
	LinkLocalIPv6PrefixLen int
	Ports                  nat.PortMap
	SandboxKey             string
	SecondaryIPAddresses   []network.Address
	SecondaryIPv6Addresses []network.Address
}

// DefaultNetworkSettings holds network information
// during the 2 release deprecation period.
// It will be removed in Docker 1.11.
type DefaultNetworkSettings struct {
	EndpointID          string
	Gateway             string
	GlobalIPv6Address   string
	GlobalIPv6PrefixLen int
	IPAddress           string
	IPPrefixLen         int
	IPv6Gateway         string
	MacAddress          string
}

// MountPoint represents a mount point configuration inside the container.
type MountPoint struct {
	Name        string `json:",omitempty"`
	Source      string
	Destination string
	Driver      string `json:",omitempty"`
	Mode        string
	RW          bool
	Propagation string
}

// Volume represents the configuration of a volume for the remote API
type Volume struct {
	Name       string // Name is the name of the volume
	Driver     string // Driver is the Driver name used to create the volume
	Mountpoint string // Mountpoint is the location on disk of the volume
}

// VolumesListResponse contains the response for the remote API:
// GET "/volumes"
type VolumesListResponse struct {
	Volumes  []*Volume // Volumes is the list of volumes being returned
	Warnings []string  // Warnings is a list of warnings that occurred when getting the list from the volume drivers
}

// VolumeCreateRequest contains the response for the remote API:
// POST "/volumes/create"
type VolumeCreateRequest struct {
	Name       string            // Name is the requested name of the volume
	Driver     string            // Driver is the name of the driver that should be used to create the volume
	DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume.
}

// NetworkResource is the body of the "get network" http response message
type NetworkResource struct {
	Name       string
	ID         string `json:"Id"`
	Scope      string
	Driver     string
	IPAM       network.IPAM
	Containers map[string]EndpointResource
	Options    map[string]string
}

// EndpointResource contains network resources allocated and used for a container in a network
type EndpointResource struct {
	Name        string
	EndpointID  string
	MacAddress  string
	IPv4Address string
	IPv6Address string
}

// NetworkCreate is the expected body of the "create network" http request message
type NetworkCreate struct {
	Name           string
	CheckDuplicate bool
	Driver         string
	IPAM           network.IPAM
	Options        map[string]string
}

// NetworkCreateResponse is the response message sent by the server for network create call
type NetworkCreateResponse struct {
	ID      string `json:"Id"`
	Warning string
}

// NetworkConnect represents the data to be used to connect a container to the network
type NetworkConnect struct {
	Container      string
	EndpointConfig *network.EndpointSettings `json:"endpoint_config"`
}

// NetworkDisconnect represents the data to be used to disconnect a container from the network
type NetworkDisconnect struct {
	Container string
}
<commit_msg>Add a Human Readable State for container<commit_after>package types

import (
	"os"
	"time"

	"github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/engine-api/types/registry"
	"github.com/docker/go-connections/nat"
)

// ContainerCreateResponse contains the information returned to a client on the
// creation of a new container.
type ContainerCreateResponse struct {
	// ID is the ID of the created container.
	ID string `json:"Id"`

	// Warnings are any warnings encountered during the creation of the container.
	Warnings []string `json:"Warnings"`
}

// ContainerExecCreateResponse contains response of Remote API:
// POST "/containers/{name:.*}/exec"
type ContainerExecCreateResponse struct {
	// ID is the exec ID.
	ID string `json:"Id"`
}

// ContainerUpdateResponse contains response of Remote API:
// POST /containers/{name:.*}/update
type ContainerUpdateResponse struct {
	// Warnings are any warnings encountered during the updating of the container.
	Warnings []string `json:"Warnings"`
}

// AuthResponse contains response of Remote API:
// POST "/auth"
type AuthResponse struct {
	// Status is the authentication status
	Status string `json:"Status"`
}

// ContainerWaitResponse contains response of Remote API:
// POST "/containers/"+containerID+"/wait"
type ContainerWaitResponse struct {
	// StatusCode is the status code of the wait job
	StatusCode int `json:"StatusCode"`
}

// ContainerCommitResponse contains response of Remote API:
// POST "/commit?container="+containerID
type ContainerCommitResponse struct {
	ID string `json:"Id"`
}

// ContainerChange contains response of Remote API:
// GET "/containers/{name:.*}/changes"
type ContainerChange struct {
	Kind int
	Path string
}

// ImageHistory contains response of Remote API:
// GET "/images/{name:.*}/history"
type ImageHistory struct {
	ID        string `json:"Id"`
	Created   int64
	CreatedBy string
	Tags      []string
	Size      int64
	Comment   string
}

// ImageDelete contains response of Remote API:
// DELETE "/images/{name:.*}"
type ImageDelete struct {
	Untagged string `json:",omitempty"`
	Deleted  string `json:",omitempty"`
}

// Image contains response of Remote API:
// GET "/images/json"
type Image struct {
	ID          string `json:"Id"`
	ParentID    string `json:"ParentId"`
	RepoTags    []string
	RepoDigests []string
	Created     int64
	Size        int64
	VirtualSize int64
	Labels      map[string]string
}

// GraphDriverData returns Image's graph driver config info
// when calling inspect command
type GraphDriverData struct {
	Name string
	Data map[string]string
}

// ImageInspect contains response of Remote API:
// GET "/images/{name:.*}/json"
type ImageInspect struct {
	ID              string `json:"Id"`
	RepoTags        []string
	RepoDigests     []string
	Parent          string
	Comment         string
	Created         string
	Container       string
	ContainerConfig *container.Config
	DockerVersion   string
	Author          string
	Config          *container.Config
	Architecture    string
	Os              string
	Size            int64
	VirtualSize     int64
	GraphDriver     GraphDriverData
}

// Port stores open ports info of container
// e.g. {"PrivatePort": 8080, "PublicPort": 80, "Type": "tcp"}
type Port struct {
	IP          string `json:",omitempty"`
	PrivatePort int
	PublicPort  int `json:",omitempty"`
	Type        string
}

// Container contains response of Remote API:
// GET  "/containers/json"
type Container struct {
	ID         string `json:"Id"`
	Names      []string
	Image      string
	ImageID    string
	Command    string
	Created    int64
	Ports      []Port
	SizeRw     int64 `json:",omitempty"`
	SizeRootFs int64 `json:",omitempty"`
	Labels     map[string]string
	State      string
	Status     string
	HostConfig struct {
		NetworkMode string `json:",omitempty"`
	}
	NetworkSettings *SummaryNetworkSettings
}

// CopyConfig contains request body of Remote API:
// POST "/containers/"+containerID+"/copy"
type CopyConfig struct {
	Resource string
}

// ContainerPathStat is used to encode the header from
// GET "/containers/{name:.*}/archive"
// "Name" is the file or directory name.
type ContainerPathStat struct {
	Name       string      `json:"name"`
	Size       int64       `json:"size"`
	Mode       os.FileMode `json:"mode"`
	Mtime      time.Time   `json:"mtime"`
	LinkTarget string      `json:"linkTarget"`
}

// ContainerProcessList contains response of Remote API:
// GET "/containers/{name:.*}/top"
type ContainerProcessList struct {
	Processes [][]string
	Titles    []string
}

// Version contains response of Remote API:
// GET "/version"
type Version struct {
	Version       string
	APIVersion    string `json:"ApiVersion"`
	GitCommit     string
	GoVersion     string
	Os            string
	Arch          string
	KernelVersion string `json:",omitempty"`
	Experimental  bool   `json:",omitempty"`
	BuildTime     string `json:",omitempty"`
}

// Info contains response of Remote API:
// GET "/info"
type Info struct {
	ID                 string
	Containers         int
	Images             int
	Driver             string
	DriverStatus       [][2]string
	Plugins            PluginsInfo
	MemoryLimit        bool
	SwapLimit          bool
	CPUCfsPeriod       bool `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool `json:"CpuCfsQuota"`
	CPUShares          bool
	CPUSet             bool
	IPv4Forwarding     bool
	BridgeNfIptables   bool
	BridgeNfIP6tables  bool `json:"BridgeNfIp6tables"`
	Debug              bool
	NFd                int
	OomKillDisable     bool
	NGoroutines        int
	SystemTime         string
	ExecutionDriver    string
	LoggingDriver      string
	NEventsListener    int
	KernelVersion      string
	OperatingSystem    string
	OSType             string
	Architecture       string
	IndexServerAddress string
	RegistryConfig     *registry.ServiceConfig
	InitSha1           string
	InitPath           string
	NCPU               int
	MemTotal           int64
	DockerRootDir      string
	HTTPProxy          string `json:"HttpProxy"`
	HTTPSProxy         string `json:"HttpsProxy"`
	NoProxy            string
	Name               string
	Labels             []string
	ExperimentalBuild  bool
	ServerVersion      string
	ClusterStore       string
	ClusterAdvertise   string
}

// PluginsInfo is temp struct holds Plugins name
// registered with docker daemon. It used by Info struct
type PluginsInfo struct {
	// List of Volume plugins registered
	Volume []string
	// List of Network plugins registered
	Network []string
	// List of Authorization plugins registered
	Authorization []string
}

// ExecStartCheck is a temp struct used by execStart
// Config fields is part of ExecConfig in runconfig package
type ExecStartCheck struct {
	// ExecStart will first check if it's detached
	Detach bool
	// Check if there's a tty
	Tty bool
}

// ContainerState stores container's running state
// it's part of ContainerJSONBase and will return by "inspect" command
type ContainerState struct {
	Status     string
	Running    bool
	Paused     bool
	Restarting bool
	OOMKilled  bool
	Dead       bool
	Pid        int
	ExitCode   int
	Error      string
	StartedAt  string
	FinishedAt string
}

// ContainerJSONBase contains response of Remote API:
// GET "/containers/{name:.*}/json"
type ContainerJSONBase struct {
	ID              string `json:"Id"`
	Created         string
	Path            string
	Args            []string
	State           *ContainerState
	Image           string
	ResolvConfPath  string
	HostnamePath    string
	HostsPath       string
	LogPath         string
	Name            string
	RestartCount    int
	Driver          string
	MountLabel      string
	ProcessLabel    string
	AppArmorProfile string
	ExecIDs         []string
	HostConfig      *container.HostConfig
	GraphDriver     GraphDriverData
	SizeRw          *int64 `json:",omitempty"`
	SizeRootFs      *int64 `json:",omitempty"`
}

// ContainerJSON is newly used struct along with MountPoint
type ContainerJSON struct {
	*ContainerJSONBase
	Mounts          []MountPoint
	Config          *container.Config
	NetworkSettings *NetworkSettings
}

// NetworkSettings exposes the network settings in the api
type NetworkSettings struct {
	NetworkSettingsBase
	DefaultNetworkSettings
	Networks map[string]*network.EndpointSettings
}

// SummaryNetworkSettings provides a summary of container's networks
// in /containers/json
type SummaryNetworkSettings struct {
	Networks map[string]*network.EndpointSettings
}

// NetworkSettingsBase holds basic information about networks
type NetworkSettingsBase struct {
	Bridge                 string
	SandboxID              string
	HairpinMode            bool
	LinkLocalIPv6Address   string
	LinkLocalIPv6PrefixLen int
	Ports                  nat.PortMap
	SandboxKey             string
	SecondaryIPAddresses   []network.Address
	SecondaryIPv6Addresses []network.Address
}

// DefaultNetworkSettings holds network information
// during the 2 release deprecation period.
// It will be removed in Docker 1.11.
type DefaultNetworkSettings struct {
	EndpointID          string
	Gateway             string
	GlobalIPv6Address   string
	GlobalIPv6PrefixLen int
	IPAddress           string
	IPPrefixLen         int
	IPv6Gateway         string
	MacAddress          string
}

// MountPoint represents a mount point configuration inside the container.
type MountPoint struct {
	Name        string `json:",omitempty"`
	Source      string
	Destination string
	Driver      string `json:",omitempty"`
	Mode        string
	RW          bool
	Propagation string
}

// Volume represents the configuration of a volume for the remote API
type Volume struct {
	Name       string // Name is the name of the volume
	Driver     string // Driver is the Driver name used to create the volume
	Mountpoint string // Mountpoint is the location on disk of the volume
}

// VolumesListResponse contains the response for the remote API:
// GET "/volumes"
type VolumesListResponse struct {
	Volumes  []*Volume // Volumes is the list of volumes being returned
	Warnings []string  // Warnings is a list of warnings that occurred when getting the list from the volume drivers
}

// VolumeCreateRequest contains the response for the remote API:
// POST "/volumes/create"
type VolumeCreateRequest struct {
	Name       string            // Name is the requested name of the volume
	Driver     string            // Driver is the name of the driver that should be used to create the volume
	DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume.
}

// NetworkResource is the body of the "get network" http response message
type NetworkResource struct {
	Name       string
	ID         string `json:"Id"`
	Scope      string
	Driver     string
	IPAM       network.IPAM
	Containers map[string]EndpointResource
	Options    map[string]string
}

// EndpointResource contains network resources allocated and used for a container in a network
type EndpointResource struct {
	Name        string
	EndpointID  string
	MacAddress  string
	IPv4Address string
	IPv6Address string
}

// NetworkCreate is the expected body of the "create network" http request message
type NetworkCreate struct {
	Name           string
	CheckDuplicate bool
	Driver         string
	IPAM           network.IPAM
	Options        map[string]string
}

// NetworkCreateResponse is the response message sent by the server for network create call
type NetworkCreateResponse struct {
	ID      string `json:"Id"`
	Warning string
}

// NetworkConnect represents the data to be used to connect a container to the network
type NetworkConnect struct {
	Container      string
	EndpointConfig *network.EndpointSettings `json:"endpoint_config"`
}

// NetworkDisconnect represents the data to be used to disconnect a container from the network
type NetworkDisconnect struct {
	Container string
}
<|endoftext|>


<commit_before>package message

import (
	"fmt"
	"time"
)

type Message struct {
	From      string
	Previous  string
	Seq       int
	Timestamp time.Time

	Content string

	Hash      string
	Signature string
}

func (m *Message) IsValid() bool {
	return true
}

func (m *Message) Bytes() []byte {
	// Small hack
	return fmt.Sprintf("%v", m)
}
<commit_msg>[message] Fix convert to bytes<commit_after>package message

import (
	"fmt"
	"time"
)

type Message struct {
	From      string
	Previous  string
	Seq       int
	Timestamp time.Time

	Content string

	Hash      string
	Signature string
}

func (m *Message) IsValid() bool {
	return true
}

func (m *Message) Bytes() []byte {
	// Small hack
	return []byte(fmt.Sprintf("%v", m))
}
<|endoftext|>


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

// Package message implements functions to model/manipulate messages specified by
// the method interface of the APT software package manager. For more information
// about the APT method interface see, http://www.fifi.org/doc/libapt-pkg-doc/method.html/ch2.html#s2.3.
package message

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
)

// Header models the first line of a message specified by the APT method
// interface.
type Header struct {
	Status      int
	Description string
}

// Field models the lines of a message specified by the APT method interface
// that follow a Header line.
type Field struct {
	Name  string
	Value string
}

// Message models an entore message specified by the APT method interface. It
// includes a Header and a list of Fields.
type Message struct {
	Header *Header
	Fields []*Field
}

// FromBytes takes a byte representation of a Message and unmarshals it into a
// Message.
func FromBytes(b []byte) (*Message, error) {
	m := &Message{}
	err := m.unmarshalText(b)
	if err != nil {
		return nil, err
	}
	return m, nil
}

// GetFieldValue returns the Value property of the Field with the given name.
// If no field is found with the given name, it returns a zero length string.
// This is useful for Fields that appear only once in a given Message.
func (m *Message) GetFieldValue(name string) (string, bool) {
	for _, f := range m.Fields {
		if f.Name == name {
			return f.Value, true
		}
	}
	return "", false
}

// GetFieldList returns a slice of Fields with the given name. This is useful
// when looking for a collection of fields with a given name from the same
// Message, e.g. 'Config-Item'.
func (m *Message) GetFieldList(name string) []*Field {
	fields := []*Field{}
	for _, f := range m.Fields {
		if f.Name == name {
			fields = append(fields, f)
		}
	}
	return fields
}

// String returns a string representation of a Message formatted according to
// the APT method interface.
func (m *Message) String() string {
	buf := &bytes.Buffer{}
	for _, f := range m.Fields {
		buf.WriteString(f.String())
		buf.WriteString("\n")
	}
	return fmt.Sprintf("%s\n%s", m.Header.String(), buf.String())
}

// String returns a string representation of a Header formatted according to
// the APT method interface.
func (h *Header) String() string {
	return fmt.Sprintf("%d %s", h.Status, h.Description)
}

// String returns a string representation of a Field formatted according to the
// APT method interface.
func (f *Field) String() string {
	return fmt.Sprintf("%s: %s", f.Name, f.Value)
}

func (m *Message) marshalText() ([]byte, error) {
	t := m.String()
	return []byte(t), nil
}

func (m *Message) unmarshalText(b []byte) error {
	var err error
	*m, err = parse(string(b))
	return err
}

// parse splits a string message by line, and then constructs a Message from a
// Header and slice of Fields.
func parse(value string) (Message, error) {
	lines := strings.Split(strings.TrimSpace(value), "\n")
	headerLine := lines[0]
	fieldLines := lines[1:]

	header, err := parseHeader(headerLine)
	if err != nil {
		return Message{}, err
	}
	fields := parseFields(fieldLines)
	return Message{Header: header, Fields: fields}, nil
}

// parseHeader splits a string header by white space and constructs a Header
// based on the status code and description.
//
// Lines might look like the following:
//
// 102 Status
// 200 URI Start
// 201 URI Done
// 601 Configuration
func parseHeader(line string) (*Header, error) {
	line = strings.TrimSpace(line)
	headerTkns := strings.Split(line, " ")
	statusString := strings.TrimSpace(headerTkns[0])
	statusCode, err := strconv.Atoi(statusString)
	if err != nil {
		return nil, err
	}
	descTkns := make([]string, len(headerTkns[1:]))
	for idx, descTkn := range headerTkns[1:] {
		descTkns[idx] = strings.TrimSpace(descTkn)
	}
	return &Header{Status: statusCode, Description: strings.Join(descTkns, " ")}, nil
}

func parseFields(lines []string) []*Field {
	fields := []*Field{}
	for _, l := range lines {
		fields = append(fields, parseField(l))
	}
	return fields
}

// parseField splits a string field by colon and constructs a Field based on
// the name and value.
//
// Lines might look like the following:
//
// URI:s3://my-s3-repository/project-a/dists/trusty/main/binary-amd64/Packages
// Config-Item: Aptitude::Get-Root-Command=sudo:/usr/bin/sudo
func parseField(line string) *Field {
	line = strings.TrimSpace(line)
	tokens := strings.Split(line, ":")

	// the line may have additional colons, so the value needs to be any tokens
	// after the first joined with a colon
	valueTkns := make([]string, len(tokens[1:]))
	for idx, valueTkn := range tokens[1:] {
		valueTkns[idx] = strings.TrimSpace(valueTkn)
	}
	return &Field{Name: tokens[0], Value: strings.Join(valueTkns, ":")}
}
<commit_msg>reduce code verbosity<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package message implements functions to model/manipulate messages specified by
// the method interface of the APT software package manager. For more information
// about the APT method interface see, http://www.fifi.org/doc/libapt-pkg-doc/method.html/ch2.html#s2.3.
package message

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
)

// Header models the first line of a message specified by the APT method
// interface.
type Header struct {
	Status      int
	Description string
}

// Field models the lines of a message specified by the APT method interface
// that follow a Header line.
type Field struct {
	Name  string
	Value string
}

// Message models an entore message specified by the APT method interface. It
// includes a Header and a list of Fields.
type Message struct {
	Header *Header
	Fields []*Field
}

// FromBytes takes a byte representation of a Message and unmarshals it into a
// Message.
func FromBytes(b []byte) (*Message, error) {
	m := &Message{}
	err := m.unmarshalText(b)
	if err != nil {
		return nil, err
	}
	return m, nil
}

// GetFieldValue returns the Value property of the Field with the given name.
// If no field is found with the given name, it returns a zero length string.
// This is useful for Fields that appear only once in a given Message.
func (m *Message) GetFieldValue(name string) (string, bool) {
	for _, f := range m.Fields {
		if f.Name == name {
			return f.Value, true
		}
	}
	return "", false
}

// GetFieldList returns a slice of Fields with the given name. This is useful
// when looking for a collection of fields with a given name from the same
// Message, e.g. 'Config-Item'.
func (m *Message) GetFieldList(name string) []*Field {
	fields := []*Field{}
	for _, f := range m.Fields {
		if f.Name == name {
			fields = append(fields, f)
		}
	}
	return fields
}

// String returns a string representation of a Message formatted according to
// the APT method interface.
func (m *Message) String() string {
	buf := &bytes.Buffer{}
	for _, f := range m.Fields {
		buf.WriteString(f.String())
		buf.WriteString("\n")
	}
	return fmt.Sprintf("%s\n%s", m.Header.String(), buf.String())
}

// String returns a string representation of a Header formatted according to
// the APT method interface.
func (h *Header) String() string {
	return fmt.Sprintf("%d %s", h.Status, h.Description)
}

// String returns a string representation of a Field formatted according to the
// APT method interface.
func (f *Field) String() string {
	return fmt.Sprintf("%s: %s", f.Name, f.Value)
}

func (m *Message) marshalText() ([]byte, error) {
	t := m.String()
	return []byte(t), nil
}

func (m *Message) unmarshalText(b []byte) error {
	var err error
	*m, err = parse(string(b))
	return err
}

// parse splits a string message by line, and then constructs a Message from a
// Header and slice of Fields.
func parse(value string) (Message, error) {
	lines := strings.Split(strings.TrimSpace(value), "\n")
	headerLine := lines[0]
	fieldLines := lines[1:]

	header, err := parseHeader(headerLine)
	if err != nil {
		return Message{}, err
	}
	fields := parseFields(fieldLines)
	return Message{Header: header, Fields: fields}, nil
}

// parseHeader splits a string header by white space and constructs a Header
// based on the status code and description.
//
// Lines might look like the following:
//
// 102 Status
// 200 URI Start
// 201 URI Done
// 601 Configuration
func parseHeader(line string) (*Header, error) {
	tokens := strings.Split(strings.TrimSpace(line), " ")
	status := strings.TrimSpace(tokens[0])
	statusCode, err := strconv.Atoi(status)
	if err != nil {
		return nil, err
	}
	descTkns := make([]string, len(tokens[1:]))
	for idx, descTkn := range tokens[1:] {
		descTkns[idx] = strings.TrimSpace(descTkn)
	}
	return &Header{Status: statusCode, Description: strings.Join(descTkns, " ")}, nil
}

func parseFields(lines []string) []*Field {
	fields := []*Field{}
	for _, l := range lines {
		fields = append(fields, parseField(l))
	}
	return fields
}

// parseField splits a string field by colon and constructs a Field based on
// the name and value.
//
// Lines might look like the following:
//
// URI:s3://my-s3-repository/project-a/dists/trusty/main/binary-amd64/Packages
// Config-Item: Aptitude::Get-Root-Command=sudo:/usr/bin/sudo
func parseField(line string) *Field {
	tokens := strings.Split(strings.TrimSpace(line), ":")

	// the line may have additional colons, so the value needs to be any tokens
	// after the first joined with a colon
	valueTkns := make([]string, len(tokens[1:]))
	for idx, valueTkn := range tokens[1:] {
		valueTkns[idx] = strings.TrimSpace(valueTkn)
	}
	return &Field{Name: tokens[0], Value: strings.Join(valueTkns, ":")}
}
<|endoftext|>


<commit_before>// +build amd64,s390x
// errorcheck -0 -d=ssa/phiopt/debug=3

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

package main

//go:noinline
func f0(a bool) bool {
	x := false
	if a {
		x = true
	} else {
		x = false
	}
	return x // ERROR "converted OpPhi to Copy$"
}

//go:noinline
func f1(a bool) bool {
	x := false
	if a {
		x = false
	} else {
		x = true
	}
	return x // ERROR "converted OpPhi to Not$"
}

//go:noinline
func f2(a, b int) bool {
	x := true
	if a == b {
		x = false
	}
	return x // ERROR "converted OpPhi to Not$"
}

//go:noinline
func f3(a, b int) bool {
	x := false
	if a == b {
		x = true
	}
	return x // ERROR "converted OpPhi to Copy$"
}

//go:noinline
func f4(a, b bool) bool {
	return a || b // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f5or(a int, b bool) bool {
	var x bool
	if a == 0 {
		x = true
	} else {
		x = b
	}
	return x // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f5and(a int, b bool) bool {
	var x bool
	if a == 0 {
		x = b
	} else {
		x = false
	}
	return x // ERROR "converted OpPhi to AndB$"
}

//go:noinline
func f6or(a int, b bool) bool {
	x := b
	if a == 0 {
		// f6or has side effects so the OpPhi should not be converted.
		x = f6or(a, b)
	}
	return x
}

//go:noinline
func f6and(a int, b bool) bool {
	x := b
	if a == 0 {
		// f6and has side effects so the OpPhi should not be converted.
		x = f6and(a, b)
	}
	return x
}

//go:noinline
func f7or(a bool, b bool) bool {
	return a || b // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f7and(a bool, b bool) bool {
	return a && b // ERROR "converted OpPhi to AndB$"
}

func main() {
}
<commit_msg>test: re-enable phi optimization test<commit_after>// +build amd64 s390x
// errorcheck -0 -d=ssa/phiopt/debug=3

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

package main

//go:noinline
func f0(a bool) bool {
	x := false
	if a {
		x = true
	} else {
		x = false
	}
	return x // ERROR "converted OpPhi to Copy$"
}

//go:noinline
func f1(a bool) bool {
	x := false
	if a {
		x = false
	} else {
		x = true
	}
	return x // ERROR "converted OpPhi to Not$"
}

//go:noinline
func f2(a, b int) bool {
	x := true
	if a == b {
		x = false
	}
	return x // ERROR "converted OpPhi to Not$"
}

//go:noinline
func f3(a, b int) bool {
	x := false
	if a == b {
		x = true
	}
	return x // ERROR "converted OpPhi to Copy$"
}

//go:noinline
func f4(a, b bool) bool {
	return a || b // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f5or(a int, b bool) bool {
	var x bool
	if a == 0 {
		x = true
	} else {
		x = b
	}
	return x // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f5and(a int, b bool) bool {
	var x bool
	if a == 0 {
		x = b
	} else {
		x = false
	}
	return x // ERROR "converted OpPhi to AndB$"
}

//go:noinline
func f6or(a int, b bool) bool {
	x := b
	if a == 0 {
		// f6or has side effects so the OpPhi should not be converted.
		x = f6or(a, b)
	}
	return x
}

//go:noinline
func f6and(a int, b bool) bool {
	x := b
	if a == 0 {
		// f6and has side effects so the OpPhi should not be converted.
		x = f6and(a, b)
	}
	return x
}

//go:noinline
func f7or(a bool, b bool) bool {
	return a || b // ERROR "converted OpPhi to OrB$"
}

//go:noinline
func f7and(a bool, b bool) bool {
	return a && b // ERROR "converted OpPhi to AndB$"
}

func main() {
}
<|endoftext|>


<commit_before>// Copyright 2011 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 runtime_test

import (
	"math"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

var stop = make(chan bool, 1)

func perpetuumMobile() {
	select {
	case <-stop:
	default:
		go perpetuumMobile()
	}
}

func TestStopTheWorldDeadlock(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping during short test")
	}
	maxprocs := runtime.GOMAXPROCS(3)
	compl := make(chan bool, 2)
	go func() {
		for i := 0; i != 1000; i += 1 {
			runtime.GC()
		}
		compl <- true
	}()
	go func() {
		for i := 0; i != 1000; i += 1 {
			runtime.GOMAXPROCS(3)
		}
		compl <- true
	}()
	go perpetuumMobile()
	<-compl
	<-compl
	stop <- true
	runtime.GOMAXPROCS(maxprocs)
}

func TestYieldProgress(t *testing.T) {
	testYieldProgress(t, false)
}

func TestYieldLockedProgress(t *testing.T) {
	testYieldProgress(t, true)
}

func testYieldProgress(t *testing.T, locked bool) {
	c := make(chan bool)
	cack := make(chan bool)
	go func() {
		if locked {
			runtime.LockOSThread()
		}
		for {
			select {
			case <-c:
				cack <- true
				return
			default:
				runtime.Gosched()
			}
		}
	}()
	time.Sleep(10 * time.Millisecond)
	c <- true
	<-cack
}

func TestYieldLocked(t *testing.T) {
	const N = 10
	c := make(chan bool)
	go func() {
		runtime.LockOSThread()
		for i := 0; i < N; i++ {
			runtime.Gosched()
			time.Sleep(time.Millisecond)
		}
		c <- true
		// runtime.UnlockOSThread() is deliberately omitted
	}()
	<-c
}

func TestBlockLocked(t *testing.T) {
	const N = 10
	c := make(chan bool)
	go func() {
		runtime.LockOSThread()
		for i := 0; i < N; i++ {
			c <- true
		}
		runtime.UnlockOSThread()
	}()
	for i := 0; i < N; i++ {
		<-c
	}
}

func stackGrowthRecursive(i int) {
	var pad [128]uint64
	if i != 0 && pad[0] == 0 {
		stackGrowthRecursive(i - 1)
	}
}

func TestSchedLocalQueue(t *testing.T) {
	runtime.TestSchedLocalQueue1()
}

func TestSchedLocalQueueSteal(t *testing.T) {
	runtime.TestSchedLocalQueueSteal1()
}

func benchmarkStackGrowth(b *testing.B, rec int) {
	const CallsPerSched = 1000
	procs := runtime.GOMAXPROCS(-1)
	N := int32(b.N / CallsPerSched)
	c := make(chan bool, procs)
	for p := 0; p < procs; p++ {
		go func() {
			for atomic.AddInt32(&N, -1) >= 0 {
				runtime.Gosched()
				for g := 0; g < CallsPerSched; g++ {
					stackGrowthRecursive(rec)
				}
			}
			c <- true
		}()
	}
	for p := 0; p < procs; p++ {
		<-c
	}
}

func BenchmarkStackGrowth(b *testing.B) {
	benchmarkStackGrowth(b, 10)
}

func BenchmarkStackGrowthDeep(b *testing.B) {
	benchmarkStackGrowth(b, 1024)
}

func BenchmarkSyscall(b *testing.B) {
	const CallsPerSched = 1000
	procs := runtime.GOMAXPROCS(-1)
	N := int32(b.N / CallsPerSched)
	c := make(chan bool, procs)
	for p := 0; p < procs; p++ {
		go func() {
			for atomic.AddInt32(&N, -1) >= 0 {
				runtime.Gosched()
				for g := 0; g < CallsPerSched; g++ {
					runtime.Entersyscall()
					runtime.Exitsyscall()
				}
			}
			c <- true
		}()
	}
	for p := 0; p < procs; p++ {
		<-c
	}
}

func BenchmarkSyscallWork(b *testing.B) {
	const CallsPerSched = 1000
	const LocalWork = 100
	procs := runtime.GOMAXPROCS(-1)
	N := int32(b.N / CallsPerSched)
	c := make(chan bool, procs)
	for p := 0; p < procs; p++ {
		go func() {
			foo := 42
			for atomic.AddInt32(&N, -1) >= 0 {
				runtime.Gosched()
				for g := 0; g < CallsPerSched; g++ {
					runtime.Entersyscall()
					for i := 0; i < LocalWork; i++ {
						foo *= 2
						foo /= 2
					}
					runtime.Exitsyscall()
				}
			}
			c <- foo == 42
		}()
	}
	for p := 0; p < procs; p++ {
		<-c
	}
}

func BenchmarkCreateGoroutines(b *testing.B) {
	benchmarkCreateGoroutines(b, 1)
}

func BenchmarkCreateGoroutinesParallel(b *testing.B) {
	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
}

func benchmarkCreateGoroutines(b *testing.B, procs int) {
	c := make(chan bool)
	var f func(n int)
	f = func(n int) {
		if n == 0 {
			c <- true
			return
		}
		go f(n - 1)
	}
	for i := 0; i < procs; i++ {
		go f(b.N / procs)
	}
	for i := 0; i < procs; i++ {
		<-c
	}
}

type Matrix [][]float64

func BenchmarkMatmult(b *testing.B) {
	b.StopTimer()
	// matmult is O(N**3) but testing expects O(b.N),
	// so we need to take cube root of b.N
	n := int(math.Cbrt(float64(b.N))) + 1
	A := makeMatrix(n)
	B := makeMatrix(n)
	C := makeMatrix(n)
	b.StartTimer()
	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
}

func makeMatrix(n int) Matrix {
	m := make(Matrix, n)
	for i := 0; i < n; i++ {
		m[i] = make([]float64, n)
		for j := 0; j < n; j++ {
			m[i][j] = float64(i*n + j)
		}
	}
	return m
}

func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
	di := i1 - i0
	dj := j1 - j0
	dk := k1 - k0
	if di >= dj && di >= dk && di >= threshold {
		// divide in two by y axis
		mi := i0 + di/2
		done1 := make(chan struct{}, 1)
		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
		<-done1
	} else if dj >= dk && dj >= threshold {
		// divide in two by x axis
		mj := j0 + dj/2
		done1 := make(chan struct{}, 1)
		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
		<-done1
	} else if dk >= threshold {
		// divide in two by "k" axis
		// deliberately not parallel because of data races
		mk := k0 + dk/2
		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
	} else {
		// the matrices are small enough, compute directly
		for i := i0; i < i1; i++ {
			for j := j0; j < j1; j++ {
				for k := k0; k < k1; k++ {
					C[i][j] += A[i][k] * B[k][j]
				}
			}
		}
	}
	if done != nil {
		done <- struct{}{}
	}
}
<commit_msg>runtime: refactor Syscall benchmark And add a benchmark where #goroutines>GOMAXPROCS, because it's the most interesting case. Current results on darwin/amd64, Intel Core 2 Duo 2.13 GHz, 2 cores: BenchmarkSyscall	100000000	        56.0 ns/op BenchmarkSyscall-2	50000000	        57.2 ns/op BenchmarkSyscallWork	10000000	       635 ns/op BenchmarkSyscallWork-2	10000000	       315 ns/op BenchmarkSyscallExcess	 1000000	      2698 ns/op BenchmarkSyscallExcess-2	 5000000	      1192 ns/op BenchmarkSyscallExcessWork	 1000000	      2832 ns/op BenchmarkSyscallExcessWork-2	 2000000	      1966 ns/op<commit_after>// Copyright 2011 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 runtime_test

import (
	"math"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

var stop = make(chan bool, 1)

func perpetuumMobile() {
	select {
	case <-stop:
	default:
		go perpetuumMobile()
	}
}

func TestStopTheWorldDeadlock(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping during short test")
	}
	maxprocs := runtime.GOMAXPROCS(3)
	compl := make(chan bool, 2)
	go func() {
		for i := 0; i != 1000; i += 1 {
			runtime.GC()
		}
		compl <- true
	}()
	go func() {
		for i := 0; i != 1000; i += 1 {
			runtime.GOMAXPROCS(3)
		}
		compl <- true
	}()
	go perpetuumMobile()
	<-compl
	<-compl
	stop <- true
	runtime.GOMAXPROCS(maxprocs)
}

func TestYieldProgress(t *testing.T) {
	testYieldProgress(t, false)
}

func TestYieldLockedProgress(t *testing.T) {
	testYieldProgress(t, true)
}

func testYieldProgress(t *testing.T, locked bool) {
	c := make(chan bool)
	cack := make(chan bool)
	go func() {
		if locked {
			runtime.LockOSThread()
		}
		for {
			select {
			case <-c:
				cack <- true
				return
			default:
				runtime.Gosched()
			}
		}
	}()
	time.Sleep(10 * time.Millisecond)
	c <- true
	<-cack
}

func TestYieldLocked(t *testing.T) {
	const N = 10
	c := make(chan bool)
	go func() {
		runtime.LockOSThread()
		for i := 0; i < N; i++ {
			runtime.Gosched()
			time.Sleep(time.Millisecond)
		}
		c <- true
		// runtime.UnlockOSThread() is deliberately omitted
	}()
	<-c
}

func TestBlockLocked(t *testing.T) {
	const N = 10
	c := make(chan bool)
	go func() {
		runtime.LockOSThread()
		for i := 0; i < N; i++ {
			c <- true
		}
		runtime.UnlockOSThread()
	}()
	for i := 0; i < N; i++ {
		<-c
	}
}

func stackGrowthRecursive(i int) {
	var pad [128]uint64
	if i != 0 && pad[0] == 0 {
		stackGrowthRecursive(i - 1)
	}
}

func TestSchedLocalQueue(t *testing.T) {
	runtime.TestSchedLocalQueue1()
}

func TestSchedLocalQueueSteal(t *testing.T) {
	runtime.TestSchedLocalQueueSteal1()
}

func benchmarkStackGrowth(b *testing.B, rec int) {
	const CallsPerSched = 1000
	procs := runtime.GOMAXPROCS(-1)
	N := int32(b.N / CallsPerSched)
	c := make(chan bool, procs)
	for p := 0; p < procs; p++ {
		go func() {
			for atomic.AddInt32(&N, -1) >= 0 {
				runtime.Gosched()
				for g := 0; g < CallsPerSched; g++ {
					stackGrowthRecursive(rec)
				}
			}
			c <- true
		}()
	}
	for p := 0; p < procs; p++ {
		<-c
	}
}

func BenchmarkStackGrowth(b *testing.B) {
	benchmarkStackGrowth(b, 10)
}

func BenchmarkStackGrowthDeep(b *testing.B) {
	benchmarkStackGrowth(b, 1024)
}

func BenchmarkSyscall(b *testing.B) {
	benchmarkSyscall(b, 0, 1)
}

func BenchmarkSyscallWork(b *testing.B) {
	benchmarkSyscall(b, 100, 1)
}

func BenchmarkSyscallExcess(b *testing.B) {
	benchmarkSyscall(b, 0, 4)
}

func BenchmarkSyscallExcessWork(b *testing.B) {
	benchmarkSyscall(b, 100, 4)
}

func benchmarkSyscall(b *testing.B, work, excess int) {
	const CallsPerSched = 1000
	procs := runtime.GOMAXPROCS(-1) * excess
	N := int32(b.N / CallsPerSched)
	c := make(chan bool, procs)
	for p := 0; p < procs; p++ {
		go func() {
			foo := 42
			for atomic.AddInt32(&N, -1) >= 0 {
				runtime.Gosched()
				for g := 0; g < CallsPerSched; g++ {
					runtime.Entersyscall()
					for i := 0; i < work; i++ {
						foo *= 2
						foo /= 2
					}
					runtime.Exitsyscall()
				}
			}
			c <- foo == 42
		}()
	}
	for p := 0; p < procs; p++ {
		<-c
	}
}

func BenchmarkCreateGoroutines(b *testing.B) {
	benchmarkCreateGoroutines(b, 1)
}

func BenchmarkCreateGoroutinesParallel(b *testing.B) {
	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
}

func benchmarkCreateGoroutines(b *testing.B, procs int) {
	c := make(chan bool)
	var f func(n int)
	f = func(n int) {
		if n == 0 {
			c <- true
			return
		}
		go f(n - 1)
	}
	for i := 0; i < procs; i++ {
		go f(b.N / procs)
	}
	for i := 0; i < procs; i++ {
		<-c
	}
}

type Matrix [][]float64

func BenchmarkMatmult(b *testing.B) {
	b.StopTimer()
	// matmult is O(N**3) but testing expects O(b.N),
	// so we need to take cube root of b.N
	n := int(math.Cbrt(float64(b.N))) + 1
	A := makeMatrix(n)
	B := makeMatrix(n)
	C := makeMatrix(n)
	b.StartTimer()
	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
}

func makeMatrix(n int) Matrix {
	m := make(Matrix, n)
	for i := 0; i < n; i++ {
		m[i] = make([]float64, n)
		for j := 0; j < n; j++ {
			m[i][j] = float64(i*n + j)
		}
	}
	return m
}

func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
	di := i1 - i0
	dj := j1 - j0
	dk := k1 - k0
	if di >= dj && di >= dk && di >= threshold {
		// divide in two by y axis
		mi := i0 + di/2
		done1 := make(chan struct{}, 1)
		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
		<-done1
	} else if dj >= dk && dj >= threshold {
		// divide in two by x axis
		mj := j0 + dj/2
		done1 := make(chan struct{}, 1)
		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
		<-done1
	} else if dk >= threshold {
		// divide in two by "k" axis
		// deliberately not parallel because of data races
		mk := k0 + dk/2
		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
	} else {
		// the matrices are small enough, compute directly
		for i := i0; i < i1; i++ {
			for j := j0; j < j1; j++ {
				for k := k0; k < k1; k++ {
					C[i][j] += A[i][k] * B[k][j]
				}
			}
		}
	}
	if done != nil {
		done <- struct{}{}
	}
}
<|endoftext|>


<commit_before>package oauth2

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	phttp "github.com/coreos/go-oidc/http"
)

const (
	ResponseTypeCode = "code"
)

const (
	GrantTypeAuthCode     = "authorization_code"
	GrantTypeClientCreds  = "client_credentials"
	GrantTypeImplicit     = "implicit"
	GrantTypeRefreshToken = "refresh_token"

	AuthMethodClientSecretPost  = "client_secret_post"
	AuthMethodClientSecretBasic = "client_secret_basic"
	AuthMethodClientSecretJWT   = "client_secret_jwt"
	AuthMethodPrivateKeyJWT     = "private_key_jwt"
)

type Config struct {
	Credentials ClientCredentials
	Scope       []string
	RedirectURL string
	AuthURL     string
	TokenURL    string

	// Must be one of the AuthMethodXXX methods above. Right now, only
	// AuthMethodClientSecretPost and AuthMethodClientSecretBasic are supported.
	AuthMethod string
}

type Client struct {
	hc          phttp.Client
	creds       ClientCredentials
	scope       []string
	authURL     *url.URL
	redirectURL *url.URL
	tokenURL    *url.URL
	authMethod  string
}

type ClientCredentials struct {
	ID     string
	Secret string
}

func NewClient(hc phttp.Client, cfg Config) (c *Client, err error) {
	if len(cfg.Credentials.ID) == 0 {
		err = errors.New("missing client id")
		return
	}

	if len(cfg.Credentials.Secret) == 0 {
		err = errors.New("missing client secret")
		return
	}

	if cfg.AuthMethod == "" {
		cfg.AuthMethod = AuthMethodClientSecretBasic
	} else if cfg.AuthMethod != AuthMethodClientSecretPost && cfg.AuthMethod != AuthMethodClientSecretBasic {
		err = fmt.Errorf("auth method %q is not supported", cfg.AuthMethod)
		return
	}

	au, err := phttp.ParseNonEmptyURL(cfg.AuthURL)
	if err != nil {
		return
	}

	tu, err := phttp.ParseNonEmptyURL(cfg.TokenURL)
	if err != nil {
		return
	}

	// Allow empty redirect URL in the case where the client
	// only needs to verify a given token.
	ru, err := url.Parse(cfg.RedirectURL)
	if err != nil {
		return
	}

	c = &Client{
		creds:       cfg.Credentials,
		scope:       cfg.Scope,
		redirectURL: ru,
		authURL:     au,
		tokenURL:    tu,
		hc:          hc,
		authMethod:  cfg.AuthMethod,
	}

	return
}

// Generate the url for initial redirect to oauth provider.
func (c *Client) AuthCodeURL(state, accessType, prompt string) string {
	v := c.commonURLValues()
	v.Set("state", state)
	if strings.ToLower(accessType) == "offline" {
		v.Set("access_type", "offline")
	}

	if prompt != "" {
		v.Set("prompt", prompt)
	}
	v.Set("response_type", "code")

	q := v.Encode()
	u := *c.authURL
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

func (c *Client) commonURLValues() url.Values {
	return url.Values{
		"redirect_uri": {c.redirectURL.String()},
		"scope":        {strings.Join(c.scope, " ")},
		"client_id":    {c.creds.ID},
	}
}

func (c *Client) newAuthenticatedRequest(url string, values url.Values) (*http.Request, error) {
	var req *http.Request
	var err error
	switch c.authMethod {
	case AuthMethodClientSecretPost:
		values.Set("client_secret", c.creds.Secret)
		req, err = http.NewRequest("POST", url, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
	case AuthMethodClientSecretBasic:
		req, err = http.NewRequest("POST", url, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
		req.SetBasicAuth(c.creds.ID, c.creds.Secret)
	default:
		panic("misconfigured client: auth method not supported")
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	return req, nil

}

// ClientCredsToken posts the client id and secret to obtain a token scoped to the OAuth2 client via the "client_credentials" grant type.
// May not be supported by all OAuth2 servers.
func (c *Client) ClientCredsToken(scope []string) (result TokenResponse, err error) {
	v := url.Values{
		"scope":      {strings.Join(scope, " ")},
		"grant_type": {GrantTypeClientCreds},
	}

	req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
	if err != nil {
		return
	}

	resp, err := c.hc.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	return parseTokenResponse(resp)
}

// RequestToken requests a token from the Token Endpoint with the specified grantType.
// If 'grantType' == GrantTypeAuthCode, then 'value' should be the authorization code.
// If 'grantType' == GrantTypeRefreshToken, then 'value' should be the refresh token.
func (c *Client) RequestToken(grantType, value string) (result TokenResponse, err error) {
	v := c.commonURLValues()

	v.Set("grant_type", grantType)
	v.Set("client_secret", c.creds.Secret)
	switch grantType {
	case GrantTypeAuthCode:
		v.Set("code", value)
	case GrantTypeRefreshToken:
		v.Set("refresh_token", value)
	default:
		err = fmt.Errorf("unsupported grant_type: %v", grantType)
		return
	}

	req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
	if err != nil {
		return
	}

	resp, err := c.hc.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	return parseTokenResponse(resp)
}

func parseTokenResponse(resp *http.Response) (result TokenResponse, err error) {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		err = unmarshalError(body)
		return
	}

	contentType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
	if err != nil {
		return
	}

	result = TokenResponse{
		RawBody: body,
	}

	if contentType == "application/x-www-form-urlencoded" || contentType == "text/plain" {
		var vals url.Values
		vals, err = url.ParseQuery(string(body))
		if err != nil {
			return
		}
		result.AccessToken = vals.Get("access_token")
		result.TokenType = vals.Get("token_type")
		result.IDToken = vals.Get("id_token")
		result.RefreshToken = vals.Get("refresh_token")
		result.Scope = vals.Get("scope")
		e := vals.Get("expires_in")
		if e == "" {
			e = vals.Get("expires")
		}
		result.Expires, err = strconv.Atoi(e)
		if err != nil {
			return
		}
	} else {
		b := make(map[string]interface{})
		if err = json.Unmarshal(body, &b); err != nil {
			return
		}
		result.AccessToken, _ = b["access_token"].(string)
		result.TokenType, _ = b["token_type"].(string)
		result.IDToken, _ = b["id_token"].(string)
		result.RefreshToken, _ = b["refresh_token"].(string)
		result.Scope, _ = b["scope"].(string)
		e, ok := b["expires_in"].(int)
		if !ok {
			e, _ = b["expires"].(int)
		}
		result.Expires = e
	}

	return
}

type TokenResponse struct {
	AccessToken  string
	TokenType    string
	Expires      int
	IDToken      string
	RefreshToken string // OPTIONAL.
	Scope        string // OPTIONAL, if identical to the scope requested by the client, otherwise, REQUIRED.
	RawBody      []byte // In case callers need some other non-standard info from the token response
}

type AuthCodeRequest struct {
	ResponseType string
	ClientID     string
	RedirectURL  *url.URL
	Scope        []string
	State        string
}

func ParseAuthCodeRequest(q url.Values) (AuthCodeRequest, error) {
	acr := AuthCodeRequest{
		ResponseType: q.Get("response_type"),
		ClientID:     q.Get("client_id"),
		State:        q.Get("state"),
		Scope:        make([]string, 0),
	}

	qs := strings.TrimSpace(q.Get("scope"))
	if qs != "" {
		acr.Scope = strings.Split(qs, " ")
	}

	err := func() error {
		if acr.ClientID == "" {
			return NewError(ErrorInvalidRequest)
		}

		redirectURL := q.Get("redirect_uri")
		if redirectURL != "" {
			ru, err := url.Parse(redirectURL)
			if err != nil {
				return NewError(ErrorInvalidRequest)
			}
			acr.RedirectURL = ru
		}

		return nil
	}()

	return acr, err
}
<commit_msg>oauth2: don't fail if the token response does not expire<commit_after>package oauth2

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	phttp "github.com/coreos/go-oidc/http"
)

const (
	ResponseTypeCode = "code"
)

const (
	GrantTypeAuthCode     = "authorization_code"
	GrantTypeClientCreds  = "client_credentials"
	GrantTypeImplicit     = "implicit"
	GrantTypeRefreshToken = "refresh_token"

	AuthMethodClientSecretPost  = "client_secret_post"
	AuthMethodClientSecretBasic = "client_secret_basic"
	AuthMethodClientSecretJWT   = "client_secret_jwt"
	AuthMethodPrivateKeyJWT     = "private_key_jwt"
)

type Config struct {
	Credentials ClientCredentials
	Scope       []string
	RedirectURL string
	AuthURL     string
	TokenURL    string

	// Must be one of the AuthMethodXXX methods above. Right now, only
	// AuthMethodClientSecretPost and AuthMethodClientSecretBasic are supported.
	AuthMethod string
}

type Client struct {
	hc          phttp.Client
	creds       ClientCredentials
	scope       []string
	authURL     *url.URL
	redirectURL *url.URL
	tokenURL    *url.URL
	authMethod  string
}

type ClientCredentials struct {
	ID     string
	Secret string
}

func NewClient(hc phttp.Client, cfg Config) (c *Client, err error) {
	if len(cfg.Credentials.ID) == 0 {
		err = errors.New("missing client id")
		return
	}

	if len(cfg.Credentials.Secret) == 0 {
		err = errors.New("missing client secret")
		return
	}

	if cfg.AuthMethod == "" {
		cfg.AuthMethod = AuthMethodClientSecretBasic
	} else if cfg.AuthMethod != AuthMethodClientSecretPost && cfg.AuthMethod != AuthMethodClientSecretBasic {
		err = fmt.Errorf("auth method %q is not supported", cfg.AuthMethod)
		return
	}

	au, err := phttp.ParseNonEmptyURL(cfg.AuthURL)
	if err != nil {
		return
	}

	tu, err := phttp.ParseNonEmptyURL(cfg.TokenURL)
	if err != nil {
		return
	}

	// Allow empty redirect URL in the case where the client
	// only needs to verify a given token.
	ru, err := url.Parse(cfg.RedirectURL)
	if err != nil {
		return
	}

	c = &Client{
		creds:       cfg.Credentials,
		scope:       cfg.Scope,
		redirectURL: ru,
		authURL:     au,
		tokenURL:    tu,
		hc:          hc,
		authMethod:  cfg.AuthMethod,
	}

	return
}

// Generate the url for initial redirect to oauth provider.
func (c *Client) AuthCodeURL(state, accessType, prompt string) string {
	v := c.commonURLValues()
	v.Set("state", state)
	if strings.ToLower(accessType) == "offline" {
		v.Set("access_type", "offline")
	}

	if prompt != "" {
		v.Set("prompt", prompt)
	}
	v.Set("response_type", "code")

	q := v.Encode()
	u := *c.authURL
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

func (c *Client) commonURLValues() url.Values {
	return url.Values{
		"redirect_uri": {c.redirectURL.String()},
		"scope":        {strings.Join(c.scope, " ")},
		"client_id":    {c.creds.ID},
	}
}

func (c *Client) newAuthenticatedRequest(url string, values url.Values) (*http.Request, error) {
	var req *http.Request
	var err error
	switch c.authMethod {
	case AuthMethodClientSecretPost:
		values.Set("client_secret", c.creds.Secret)
		req, err = http.NewRequest("POST", url, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
	case AuthMethodClientSecretBasic:
		req, err = http.NewRequest("POST", url, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
		req.SetBasicAuth(c.creds.ID, c.creds.Secret)
	default:
		panic("misconfigured client: auth method not supported")
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	return req, nil

}

// ClientCredsToken posts the client id and secret to obtain a token scoped to the OAuth2 client via the "client_credentials" grant type.
// May not be supported by all OAuth2 servers.
func (c *Client) ClientCredsToken(scope []string) (result TokenResponse, err error) {
	v := url.Values{
		"scope":      {strings.Join(scope, " ")},
		"grant_type": {GrantTypeClientCreds},
	}

	req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
	if err != nil {
		return
	}

	resp, err := c.hc.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	return parseTokenResponse(resp)
}

// RequestToken requests a token from the Token Endpoint with the specified grantType.
// If 'grantType' == GrantTypeAuthCode, then 'value' should be the authorization code.
// If 'grantType' == GrantTypeRefreshToken, then 'value' should be the refresh token.
func (c *Client) RequestToken(grantType, value string) (result TokenResponse, err error) {
	v := c.commonURLValues()

	v.Set("grant_type", grantType)
	v.Set("client_secret", c.creds.Secret)
	switch grantType {
	case GrantTypeAuthCode:
		v.Set("code", value)
	case GrantTypeRefreshToken:
		v.Set("refresh_token", value)
	default:
		err = fmt.Errorf("unsupported grant_type: %v", grantType)
		return
	}

	req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
	if err != nil {
		return
	}

	resp, err := c.hc.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	return parseTokenResponse(resp)
}

func parseTokenResponse(resp *http.Response) (result TokenResponse, err error) {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		err = unmarshalError(body)
		return
	}

	contentType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
	if err != nil {
		return
	}

	result = TokenResponse{
		RawBody: body,
	}

	if contentType == "application/x-www-form-urlencoded" || contentType == "text/plain" {
		var vals url.Values
		vals, err = url.ParseQuery(string(body))
		if err != nil {
			return
		}
		result.AccessToken = vals.Get("access_token")
		result.TokenType = vals.Get("token_type")
		result.IDToken = vals.Get("id_token")
		result.RefreshToken = vals.Get("refresh_token")
		result.Scope = vals.Get("scope")
		e := vals.Get("expires_in")
		if e == "" {
			e = vals.Get("expires")
		}
		if e != "" {
			result.Expires, err = strconv.Atoi(e)
			if err != nil {
				return
			}
		}
	} else {
		b := make(map[string]interface{})
		if err = json.Unmarshal(body, &b); err != nil {
			return
		}
		result.AccessToken, _ = b["access_token"].(string)
		result.TokenType, _ = b["token_type"].(string)
		result.IDToken, _ = b["id_token"].(string)
		result.RefreshToken, _ = b["refresh_token"].(string)
		result.Scope, _ = b["scope"].(string)
		e, ok := b["expires_in"].(int)
		if !ok {
			e, _ = b["expires"].(int)
		}
		result.Expires = e
	}

	return
}

type TokenResponse struct {
	AccessToken  string
	TokenType    string
	Expires      int
	IDToken      string
	RefreshToken string // OPTIONAL.
	Scope        string // OPTIONAL, if identical to the scope requested by the client, otherwise, REQUIRED.
	RawBody      []byte // In case callers need some other non-standard info from the token response
}

type AuthCodeRequest struct {
	ResponseType string
	ClientID     string
	RedirectURL  *url.URL
	Scope        []string
	State        string
}

func ParseAuthCodeRequest(q url.Values) (AuthCodeRequest, error) {
	acr := AuthCodeRequest{
		ResponseType: q.Get("response_type"),
		ClientID:     q.Get("client_id"),
		State:        q.Get("state"),
		Scope:        make([]string, 0),
	}

	qs := strings.TrimSpace(q.Get("scope"))
	if qs != "" {
		acr.Scope = strings.Split(qs, " ")
	}

	err := func() error {
		if acr.ClientID == "" {
			return NewError(ErrorInvalidRequest)
		}

		redirectURL := q.Get("redirect_uri")
		if redirectURL != "" {
			ru, err := url.Parse(redirectURL)
			if err != nil {
				return NewError(ErrorInvalidRequest)
			}
			acr.RedirectURL = ru
		}

		return nil
	}()

	return acr, err
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"
)

type endpointList []string

func (e *endpointList) Set(value string) error {
	// Accumulate endpoints when multiple options exists
	*e = append(*e, value)
	return nil
}
func (e *endpointList) String() string {
	return fmt.Sprint(*e)
}

// The set of accepted flags
var (
	srvEndpoints          endpointList
	srvPath               = flag.String("srv-path", "", "Service path (e.g github.com/foo/foo-srv)")
	srvBaseEndpoint       = flag.String("srv-base", "", "Service base endpoint. If omitted the service name will be used")
	srvDescr              = flag.String("srv-descr", "", "Service description")
	messageType           = flag.String("srv-message-type", "protobuf", "The message serialization to use. One of 'protobuf' or 'json'")
	initGitRepo           = flag.Bool("init-git-repo", true, "Initialize a git repo at the output folder")
	overwrite             = flag.Bool("overwrite-files", false, "Overwrite files in output folder if the folder already exists")
	useEtcd               = flag.Bool("etcd-enabled", true, "Use etcd for service discovery")
	useThrottle           = flag.Bool("throttle-enabled", false, "Use request throttle middleware")
	throttleMaxConcurrent = flag.Int("throttle-max-concurrent", 1000, "Max concurrent service requests")
	throttleMaxExecTime   = flag.Int("throttle-max-exec-time", 0, "Max execution time for a request in ms. No limit if set to 0")
	useTracer             = flag.Bool("tracer-enabled", true, "Use request tracing middleware")
	tracerQueueSize       = flag.Int("tracer-queue-size", 1000, "Max concurrent trace messages in queue")
	tracerTTL             = flag.Int("tracer-entry-ttl", 24*3600, "Trace entry TTL in seconds. TTL will be disabled if set to 0")

	pkgFolder = ""
	srvName   = ""
)

const (
	Protobuf = "protobuf"
	Json     = "json"
)

func init() {
	flag.Var(&srvEndpoints, "srv-endpoint", "An endpoint name (e.g AddUser), You may specify multiple endpoints by repeating the --srv-endpoint flag")
}

// Get the list of templates (*.tpl) under path. The method will scan the path recursively.
func getTemplates(path string) []string {
	list := make([]string, 0)
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		// Recurse into dirs
		if info.IsDir() {
			return nil
		}

		if strings.HasSuffix(info.Name(), "_tpl") {
			list = append(list, path)
		}

		return nil
	})

	return list
}

func parseArgs() error {
	flag.Parse()

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return fmt.Errorf("GOPATH env var not defined")
	}

	// Trim trailing slash if present
	*srvPath = strings.TrimRight(*srvPath, "/")

	if *srvPath == "" {
		return fmt.Errorf("Please specify the service path with the --srv-path option")
	}

	srvName = (*srvPath)[strings.LastIndex(*srvPath, "/")+1:]

	pkgFolder = fmt.Sprintf("%s/src/%s", gopath, *srvPath)
	info, err := os.Stat(pkgFolder)
	if err == nil {
		if !info.IsDir() {
			return fmt.Errorf("Specified package folder %s is actually a file", pkgFolder)
		}
		if !*overwrite {
			return fmt.Errorf("Specified package folder %s already exists. Use the --overwrite-files flag to proceed", pkgFolder)
		}
	}

	if *srvBaseEndpoint == "" {
		*srvBaseEndpoint = srvName
	}

	if len(srvEndpoints) == 0 {
		return fmt.Errorf("You need to specify at least one endpoint name using the --srv-endpoint flag")
	}

	if *messageType != Protobuf && *messageType != Json {
		return fmt.Errorf("Invalid service message type. Supported values are 'protobuf' and 'json'")
	}
	return nil
}

func initGit() error {
	fmt.Printf("\r\u274C  Init empty git repo")
	err := exec.Command("git", "init", pkgFolder).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Init empty git repo\n")
		return fmt.Errorf("Error initializing git repo: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Init empty git repo\n")

	return nil
}

func initBindings() error {
	fmt.Printf("\r\u274C  Creating initial protobuf bindings")
	err := exec.Command(
		"protoc",
		fmt.Sprintf("--%s=%s", "go_out", pkgFolder),
		fmt.Sprintf("--proto_path=%s", pkgFolder),
		fmt.Sprintf("%s/messages.proto", pkgFolder),
	).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Creating initial protobuf bindings\n")
		return fmt.Errorf("Error running protoc: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Creating initial protobuf bindings\n")

	return nil
}

func formatCode() error {
	fmt.Printf("\r\u274C  Running go fmt")
	err := exec.Command(
		"go",
		"fmt",
		fmt.Sprintf("%s/...", pkgFolder),
	).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Running go fmt\n")
		return fmt.Errorf("Error running go fmt: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Running go fmt\n")

	return nil
}

func genService() error {

	var err error

	fmt.Printf("Creating new usrv service at %s\n", pkgFolder)
	err = os.MkdirAll(pkgFolder, os.ModeDir|os.ModePerm)
	if err != nil {
		return fmt.Errorf("Error creating folder %s: %s", pkgFolder, err.Error())
	}

	// Build context
	context := map[string]interface{}{
		"PkgName":               "srv",
		"SrvPath":               *srvPath,
		"SrvName":               srvName,
		"SrvDescription":        *srvDescr,
		"SrvMessageType":        *messageType,
		"SrvBaseEndpoint":       *srvBaseEndpoint,
		"SrvEndpoints":          srvEndpoints,
		"UseEtcd":               *useEtcd,
		"UseThrottle":           *useThrottle,
		"ThrottleMaxConcurrent": *throttleMaxConcurrent,
		"ThrottleMaxExecTime":   *throttleMaxExecTime,
		"UseTracer":             *useTracer,
		"TracerQueueSize":       *tracerQueueSize,
		"TracerTTL":             *tracerTTL,
	}

	// Execute templates
	for _, tplFile := range getTemplates("templates") {
		// Depending on the selected message type exclude either protobuf template or json template
		if *messageType == Protobuf && strings.Contains(tplFile, "messages.go") {
			continue
		} else if *messageType == Json && strings.Contains(tplFile, ".proto") {
			continue
		}

		// Strip the _tpl extension and the templates/ prefix
		dstFilename := strings.Replace(
			strings.Replace(tplFile, "_tpl", "", 1),
			"templates/",
			"",
			1,
		)

		// Template contains a folder?
		if strings.Index(dstFilename, "/") != -1 {
			dstFolder := fmt.Sprintf(
				"%s/%s",
				pkgFolder,
				dstFilename[0:strings.LastIndex(dstFilename, "/")],
			)
			err = os.MkdirAll(dstFolder, os.ModeDir|os.ModePerm)
			if err != nil {
				return fmt.Errorf("Error creating folder %s: %s", dstFolder, err.Error())
			}
		}

		// Read template
		tplData, err := ioutil.ReadFile(tplFile)
		if err != nil {
			return fmt.Errorf("Error reading template %s: %s", tplFile, err.Error())
		}

		tpl, err := template.New(dstFilename).Parse(string(tplData))
		if err != nil {
			return fmt.Errorf("Error parsing template %s: %s", tplFile, err.Error())
		}

		dstPath := fmt.Sprintf("%s/%s", pkgFolder, dstFilename)
		outFile, err := os.Create(dstPath)
		if err != nil {
			return fmt.Errorf("Error opening %s for writing: %s", dstPath, err.Error())
		}
		fmt.Printf("\r\u231B  Processing: %s -> %s", tplFile, dstFilename)
		defer outFile.Close()

		err = tpl.Execute(outFile, context)
		if err != nil {
			fmt.Printf("\r\u274C  Processing: %s -> %s\n", tplFile, dstFilename)
			return fmt.Errorf("Error executing template %s: %s", tplFile, err.Error())
		}
		fmt.Printf("\r\u2713  Processing: %s -> %s\n", tplFile, dstFilename)
	}

	// Run go-fmt
	err = formatCode()
	if err != nil {
		return err
	}

	fmt.Printf("\u2713  Service created successfully")

	// Create initial bindings when using protobuf
	if *messageType == Protobuf {
		err = initBindings()
		if err != nil {
			return err
		}
	}

	// Init git repo
	if *initGitRepo {
		err = initGit()
		if err != nil {
			return err
		}
	}

	fmt.Println("\nNotes:")
	if *messageType == Protobuf {
		fmt.Printf("- The service protobuf messages are defined in %s/messages.proto.\n  After making any changes to the .proto file run 'go generate' to rebuild the go bindings.\n", pkgFolder)
	} else if *messageType == Json {
		fmt.Printf("- The service messages are defined in %s/messages.go.\n", pkgFolder)
	}
	fmt.Printf("- Add your service implementation inside %s/service.go.\n", pkgFolder)
	if *useEtcd {
		fmt.Printf("- The service is set up to use etcd for automatic configuration.\n  See %s/README.md for more details.\n", pkgFolder)
	}
	if *initGitRepo {
		fmt.Printf("- An empty git repo has been created for you.\n")
	}
	fmt.Printf("\n\n")
	return nil
}

func main() {
	// Parse args
	err := parseArgs()
	if err != nil {
		fmt.Fprintf(os.Stderr, "\u274C  %s\n\n", err.Error())
		flag.Usage()
		os.Exit(1)
	}

	// Preflight checks
	if *messageType == Protobuf {
		_, err = exec.LookPath("protoc-gen-go")
		if err != nil {
			fmt.Fprintf(os.Stderr, "\u274C  protoc-gen-go not be located in your current $PATH\n   Try running: go get -u github.com/golang/protobuf/{proto,protoc-gen-go}\n")
			os.Exit(1)
		}
	}

	// Create service
	err = genService()
	if err != nil {
		fmt.Printf("\u274C  %s\n", err.Error())
		os.Exit(1)
	}
}
<commit_msg>Changed default command line arg values<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"
)

type endpointList []string

func (e *endpointList) Set(value string) error {
	// Accumulate endpoints when multiple options exists
	*e = append(*e, value)
	return nil
}
func (e *endpointList) String() string {
	return fmt.Sprint(*e)
}

// The set of accepted flags
var (
	srvEndpoints          endpointList
	srvPath               = flag.String("srv-path", "", "Service path (e.g github.com/foo/foo-srv)")
	srvBaseEndpoint       = flag.String("srv-base", "", "Service base endpoint. If omitted the service name will be used")
	srvDescr              = flag.String("srv-descr", "", "Service description")
	messageType           = flag.String("srv-message-type", "protobuf", "The message serialization to use. One of 'protobuf' or 'json'")
	initGitRepo           = flag.Bool("init-git-repo", true, "Initialize a git repo at the output folder")
	overwrite             = flag.Bool("overwrite-files", false, "Overwrite files in output folder if the folder already exists")
	useEtcd               = flag.Bool("etcd-enabled", false, "Use etcd for service discovery")
	useThrottle           = flag.Bool("throttle-enabled", false, "Use request throttle middleware")
	throttleMaxConcurrent = flag.Int("throttle-max-concurrent", 1000, "Max concurrent service requests")
	throttleMaxExecTime   = flag.Int("throttle-max-exec-time", 0, "Max execution time for a request in ms. No limit if set to 0")
	useTracer             = flag.Bool("tracer-enabled", false, "Use request tracing middleware")
	tracerQueueSize       = flag.Int("tracer-queue-size", 1000, "Max concurrent trace messages in queue")
	tracerTTL             = flag.Int("tracer-entry-ttl", 24*3600, "Trace entry TTL in seconds. TTL will be disabled if set to 0")

	pkgFolder = ""
	srvName   = ""
)

const (
	Protobuf = "protobuf"
	Json     = "json"
)

func init() {
	flag.Var(&srvEndpoints, "srv-endpoint", "An endpoint name (e.g AddUser), You may specify multiple endpoints by repeating the --srv-endpoint flag")
}

// Get the list of templates (*.tpl) under path. The method will scan the path recursively.
func getTemplates(path string) []string {
	list := make([]string, 0)
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		// Recurse into dirs
		if info.IsDir() {
			return nil
		}

		if strings.HasSuffix(info.Name(), "_tpl") {
			list = append(list, path)
		}

		return nil
	})

	return list
}

func parseArgs() error {
	flag.Parse()

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return fmt.Errorf("GOPATH env var not defined")
	}

	// Trim trailing slash if present
	*srvPath = strings.TrimRight(*srvPath, "/")

	if *srvPath == "" {
		return fmt.Errorf("Please specify the service path with the --srv-path option")
	}

	srvName = (*srvPath)[strings.LastIndex(*srvPath, "/")+1:]

	pkgFolder = fmt.Sprintf("%s/src/%s", gopath, *srvPath)
	info, err := os.Stat(pkgFolder)
	if err == nil {
		if !info.IsDir() {
			return fmt.Errorf("Specified package folder %s is actually a file", pkgFolder)
		}
		if !*overwrite {
			return fmt.Errorf("Specified package folder %s already exists. Use the --overwrite-files flag to proceed", pkgFolder)
		}
	}

	if *srvBaseEndpoint == "" {
		*srvBaseEndpoint = srvName
	}

	if len(srvEndpoints) == 0 {
		return fmt.Errorf("You need to specify at least one endpoint name using the --srv-endpoint flag")
	}

	if *messageType != Protobuf && *messageType != Json {
		return fmt.Errorf("Invalid service message type. Supported values are 'protobuf' and 'json'")
	}
	return nil
}

func initGit() error {
	fmt.Printf("\r\u274C  Init empty git repo")
	err := exec.Command("git", "init", pkgFolder).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Init empty git repo\n")
		return fmt.Errorf("Error initializing git repo: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Init empty git repo\n")

	return nil
}

func initBindings() error {
	fmt.Printf("\r\u274C  Creating initial protobuf bindings")
	err := exec.Command(
		"protoc",
		fmt.Sprintf("--%s=%s", "go_out", pkgFolder),
		fmt.Sprintf("--proto_path=%s", pkgFolder),
		fmt.Sprintf("%s/messages.proto", pkgFolder),
	).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Creating initial protobuf bindings\n")
		return fmt.Errorf("Error running protoc: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Creating initial protobuf bindings\n")

	return nil
}

func formatCode() error {
	fmt.Printf("\r\u274C  Running goimports")
	err := exec.Command(
		"goimports",
		"-w",
		fmt.Sprintf("%s/", pkgFolder),
	).Run()
	if err != nil {
		fmt.Printf("\r\u274C  Running goimports\n")
		return fmt.Errorf("Error running goimports: %s", err.Error())
	}
	fmt.Printf("\r\u2713  Running goimports\n")

	return nil
}

func genService() error {

	var err error

	fmt.Printf("Creating new usrv service at %s\n", pkgFolder)
	err = os.MkdirAll(pkgFolder, os.ModeDir|os.ModePerm)
	if err != nil {
		return fmt.Errorf("Error creating folder %s: %s", pkgFolder, err.Error())
	}

	// Build context
	context := map[string]interface{}{
		"PkgName":               "srv",
		"SrvPath":               *srvPath,
		"SrvName":               srvName,
		"SrvDescription":        *srvDescr,
		"SrvMessageType":        *messageType,
		"SrvBaseEndpoint":       *srvBaseEndpoint,
		"SrvEndpoints":          srvEndpoints,
		"UseEtcd":               *useEtcd,
		"UseThrottle":           *useThrottle,
		"ThrottleMaxConcurrent": *throttleMaxConcurrent,
		"ThrottleMaxExecTime":   *throttleMaxExecTime,
		"UseTracer":             *useTracer,
		"TracerQueueSize":       *tracerQueueSize,
		"TracerTTL":             *tracerTTL,
	}

	// Execute templates
	for _, tplFile := range getTemplates("templates") {
		// Depending on the selected message type exclude either protobuf template or json template
		if *messageType == Protobuf && strings.Contains(tplFile, "messages.go") {
			continue
		} else if *messageType == Json && strings.Contains(tplFile, ".proto") {
			continue
		}

		// Strip the _tpl extension and the templates/ prefix
		dstFilename := strings.Replace(
			strings.Replace(tplFile, "_tpl", "", 1),
			"templates/",
			"",
			1,
		)

		// Template contains a folder?
		if strings.Index(dstFilename, "/") != -1 {
			dstFolder := fmt.Sprintf(
				"%s/%s",
				pkgFolder,
				dstFilename[0:strings.LastIndex(dstFilename, "/")],
			)
			err = os.MkdirAll(dstFolder, os.ModeDir|os.ModePerm)
			if err != nil {
				return fmt.Errorf("Error creating folder %s: %s", dstFolder, err.Error())
			}
		}

		// Read template
		tplData, err := ioutil.ReadFile(tplFile)
		if err != nil {
			return fmt.Errorf("Error reading template %s: %s", tplFile, err.Error())
		}

		tpl, err := template.New(dstFilename).Parse(string(tplData))
		if err != nil {
			return fmt.Errorf("Error parsing template %s: %s", tplFile, err.Error())
		}

		dstPath := fmt.Sprintf("%s/%s", pkgFolder, dstFilename)
		outFile, err := os.Create(dstPath)
		if err != nil {
			return fmt.Errorf("Error opening %s for writing: %s", dstPath, err.Error())
		}
		fmt.Printf("\r\u231B  Processing: %s -> %s", tplFile, dstFilename)
		defer outFile.Close()

		err = tpl.Execute(outFile, context)
		if err != nil {
			fmt.Printf("\r\u274C  Processing: %s -> %s\n", tplFile, dstFilename)
			return fmt.Errorf("Error executing template %s: %s", tplFile, err.Error())
		}
		fmt.Printf("\r\u2713  Processing: %s -> %s\n", tplFile, dstFilename)
	}

	// Run go-fmt
	err = formatCode()
	if err != nil {
		return err
	}

	fmt.Printf("\u2713  Service created successfully")

	// Create initial bindings when using protobuf
	if *messageType == Protobuf {
		err = initBindings()
		if err != nil {
			return err
		}
	}

	// Init git repo
	if *initGitRepo {
		err = initGit()
		if err != nil {
			return err
		}
	}

	fmt.Println("\nNotes:")
	if *messageType == Protobuf {
		fmt.Printf("- The service protobuf messages are defined in %s/messages.proto.\n  After making any changes to the .proto file run 'go generate' to rebuild the go bindings.\n", pkgFolder)
	} else if *messageType == Json {
		fmt.Printf("- The service messages are defined in %s/messages.go.\n", pkgFolder)
	}
	fmt.Printf("- Add your service implementation inside %s/service.go.\n", pkgFolder)
	if *useEtcd {
		fmt.Printf("- The service is set up to use etcd for automatic configuration.\n  See %s/README.md for more details.\n", pkgFolder)
	}
	if *initGitRepo {
		fmt.Printf("- An empty git repo has been created for you.\n")
	}
	fmt.Printf("\n\n")
	return nil
}

func main() {
	// Parse args
	err := parseArgs()
	if err != nil {
		fmt.Fprintf(os.Stderr, "\u274C  %s\n\n", err.Error())
		flag.Usage()
		os.Exit(1)
	}

	// Preflight checks
	if *messageType == Protobuf {
		_, err = exec.LookPath("protoc-gen-go")
		if err != nil {
			fmt.Fprintf(os.Stderr, "\u274C  protoc-gen-go not be located in your current $PATH\n   Try running: go get -u github.com/golang/protobuf/{proto,protoc-gen-go}\n")
			os.Exit(1)
		}
	}

	// Create service
	err = genService()
	if err != nil {
		fmt.Printf("\u274C  %s\n", err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package adsb

import (
	"fmt"
	"time"

	"github.com/skypies/geo"
)

type IcaoId string

// http://woodair.net/SBS/Article/Barebones42_Socket_Data.htm
// https://github.com/MalcolmRobb/dump1090/blob/master/mode_s.c#L834
//
// ** NOTE ** : we're not actually populating all of this yet
//
type Msg struct {
	// This set of data is basically the SBS1 format, not the ADS-B format.

	Type string `json:"-"` // = 0 // type	 (MSG, STA, ID, AIR, SEL or CLK). We ignore all but MSG.
	SubType int64 `json:"-"` // = 1 // Type	 MSG sub types 1 to 8. Not used by other message types.
	// Session = 2 // ID	 Database Session record number
	// AircraftID = 3 //	 Database Aircraft record number
	Icao24 IcaoId //  = 4 //	 Aircraft Mode S hexadecimal code

	////
	// NOTE - these are only going to be in UTC iff you've set adsb.TimeLocation to agree with
	// localtime on the machine running dump1090, which outputs non-timezoned 'local' time data.
	////
	GeneratedTimestampUTC time.Time
	LoggedTimestampUTC    time.Time `json:"-"`

	//DateGen = 6 // message generated	  As it says
	//TimeGen = 7 // message generated	  As it says
	//DateLog = 8 // message logged	  As it says
	//TimeLog = 9 // message logged	  As it says
	Callsign string // = 10 //	 An eight digit flight ID - can be flight number or registration
	Altitude int64 // = 11 //	 Mode C altitude. Height relative to 1013.2mb (Flight Level).
	GroundSpeed int64 // = 12 //	 Speed over ground (not indicated airspeed)
	Track int64 // = 13 //	 Track of aircraft (not heading). Derived from the velocity E/W, N/S

	Position geo.Latlong
	//Latitude float64 // = 14 //	 North and East positive. South and West negative.
	//Longitude float64 // = 15 //	 North and East positive. South and West negative.

	VerticalRate int64 // = 16 //	 64ft resolution
	Squawk string // = 17 //	 Assigned Mode A squawk code.
	AlertSquawkChange bool `json:"-"`// = 18 // (Squawk change)	 Flag to indicate squawk has changed.
	Emergency bool `json:"-"`// = 19 //	 Flag to indicate emergency code has been set
	SPI bool `json:"-"`// = 20 // (Ident)	 Flag to indicate transponder Ident has been activated.
	IsOnGround bool `json:"-"`// = 21 //	 Flag to indicate ground squat switch is active

	// These fields are present for extended basestation format messages (i.e. MLAT)
	NumStations int64 `json:"-"`
	//ErrorEstimate int64 `json:"-"`  // Not sure if this is a float or an int, or what it means

	// Flags filled (and only valid) during initial SBS parsing, for fields not
	// always present
	hasAltitude     bool
	hasCallsign     bool
	hasSquawk       bool
	hasGroundSpeed  bool
	hasTrack        bool
	hasPosition     bool
	hasVerticalRate bool
}

func (m Msg)IsMLAT() bool { return m.Type == "MLAT" }

//func (m Msg)HasAltitude()     bool { return m.hasAltitude }
func (m Msg)HasCallsign()     bool { return m.hasCallsign }
func (m Msg)HasSquawk()       bool { return m.hasSquawk }
func (m Msg)HasGroundSpeed()  bool { return m.hasGroundSpeed }
func (m Msg)HasTrack()        bool { return m.hasTrack }
func (m Msg)HasPosition()     bool { return m.hasPosition }
func (m Msg)HasVerticalRate() bool { return m.hasVerticalRate }

func (m Msg)String() string {
	s := fmt.Sprintf("%s%d : %s", m.Type, m.SubType, m.Icao24)
	if m.HasPosition() {
		s += fmt.Sprintf(" %s", m.Position)
	}
	return s
}
<commit_msg>Expose message type in the JSON; this is so consumers can differentiate between ADSB ("MSG") and MLAT ("MLAT") messages without needing additional data.<commit_after>package adsb

import (
	"fmt"
	"time"

	"github.com/skypies/geo"
)

type IcaoId string

// http://woodair.net/SBS/Article/Barebones42_Socket_Data.htm
// https://github.com/MalcolmRobb/dump1090/blob/master/mode_s.c#L834
//
// ** NOTE ** : we're not actually populating all of this yet
//
type Msg struct {
	// This set of data is basically the SBS1 format, not the ADS-B format.

	Type string //`json:"-"` // = 0 // type	 (MSG, STA, ID, AIR, SEL or CLK). We ignore all but MSG.
	SubType int64 `json:"-"` // = 1 // Type	 MSG sub types 1 to 8. Not used by other message types.
	// Session = 2 // ID	 Database Session record number
	// AircraftID = 3 //	 Database Aircraft record number
	Icao24 IcaoId //  = 4 //	 Aircraft Mode S hexadecimal code

	////
	// NOTE - these are only going to be in UTC iff you've set adsb.TimeLocation to agree with
	// localtime on the machine running dump1090, which outputs non-timezoned 'local' time data.
	////
	GeneratedTimestampUTC time.Time
	LoggedTimestampUTC    time.Time `json:"-"`

	//DateGen = 6 // message generated	  As it says
	//TimeGen = 7 // message generated	  As it says
	//DateLog = 8 // message logged	  As it says
	//TimeLog = 9 // message logged	  As it says
	Callsign string // = 10 //	 An eight digit flight ID - can be flight number or registration
	Altitude int64 // = 11 //	 Mode C altitude. Height relative to 1013.2mb (Flight Level).
	GroundSpeed int64 // = 12 //	 Speed over ground (not indicated airspeed)
	Track int64 // = 13 //	 Track of aircraft (not heading). Derived from the velocity E/W, N/S

	Position geo.Latlong
	//Latitude float64 // = 14 //	 North and East positive. South and West negative.
	//Longitude float64 // = 15 //	 North and East positive. South and West negative.

	VerticalRate int64 // = 16 //	 64ft resolution
	Squawk string // = 17 //	 Assigned Mode A squawk code.
	AlertSquawkChange bool `json:"-"`// = 18 // (Squawk change)	 Flag to indicate squawk has changed.
	Emergency bool `json:"-"`// = 19 //	 Flag to indicate emergency code has been set
	SPI bool `json:"-"`// = 20 // (Ident)	 Flag to indicate transponder Ident has been activated.
	IsOnGround bool `json:"-"`// = 21 //	 Flag to indicate ground squat switch is active

	// These fields are present for extended basestation format messages (i.e. MLAT)
	NumStations int64 `json:"-"`
	//ErrorEstimate int64 `json:"-"`  // Not sure if this is a float or an int, or what it means

	// Flags filled (and only valid) during initial SBS parsing, for fields not
	// always present
	hasAltitude     bool
	hasCallsign     bool
	hasSquawk       bool
	hasGroundSpeed  bool
	hasTrack        bool
	hasPosition     bool
	hasVerticalRate bool
}

func (m Msg)IsMLAT() bool { return m.Type == "MLAT" }

//func (m Msg)HasAltitude()     bool { return m.hasAltitude }
func (m Msg)HasCallsign()     bool { return m.hasCallsign }
func (m Msg)HasSquawk()       bool { return m.hasSquawk }
func (m Msg)HasGroundSpeed()  bool { return m.hasGroundSpeed }
func (m Msg)HasTrack()        bool { return m.hasTrack }
func (m Msg)HasPosition()     bool { return m.hasPosition }
func (m Msg)HasVerticalRate() bool { return m.hasVerticalRate }

func (m Msg)String() string {
	s := fmt.Sprintf("%s%d : %s", m.Type, m.SubType, m.Icao24)
	if m.HasPosition() {
		s += fmt.Sprintf(" %s", m.Position)
	}
	return s
}
<|endoftext|>


<commit_before>package adsb

import (
	"fmt"
	"time"

	"github.com/skypies/geo"
)

type IcaoId string

// http://woodair.net/SBS/Article/Barebones42_Socket_Data.htm
// https://github.com/MalcolmRobb/dump1090/blob/master/mode_s.c#L834
//
// ** NOTE ** : we're not actually populating all of this yet
//
type Msg struct {
	// This set of data is basically the SBS1 format, not the ADS-B format.

	Type string // = 0 // type	 (MSG, STA, ID, AIR, SEL or CLK). We ignore all but MSG.
	SubType int64 // = 1 // Type	 MSG sub types 1 to 8. Not used by other message types.
	// Session = 2 // ID	 Database Session record number
	// AircraftID = 3 //	 Database Aircraft record number
	Icao24 IcaoId //  = 4 //	 Aircraft Mode S hexadecimal code
	GeneratedTimestampUTC time.Time
	LoggedTimestampUTC    time.Time
	//DateGen = 6 // message generated	  As it says
	//TimeGen = 7 // message generated	  As it says
	//DateLog = 8 // message logged	  As it says
	//TimeLog = 9 // message logged	  As it says
	Callsign string // = 10 //	 An eight digit flight ID - can be flight number or registration
	Altitude int64 // = 11 //	 Mode C altitude. Height relative to 1013.2mb (Flight Level).
	GroundSpeed int64 // = 12 //	 Speed over ground (not indicated airspeed)
	Track int64 // = 13 //	 Track of aircraft (not heading). Derived from the velocity E/W, N/S

	Position geo.Latlong
	//Latitude float64 // = 14 //	 North and East positive. South and West negative.
	//Longitude float64 // = 15 //	 North and East positive. South and West negative.

	VerticalRate int64 // = 16 //	 64ft resolution
	Squawk string // = 17 //	 Assigned Mode A squawk code.
	AlertSquawkChange bool // = 18 // (Squawk change)	 Flag to indicate squawk has changed.
	Emergency bool // = 19 //	 Flag to indicate emergency code has been set
	SPI bool // = 20 // (Ident)	 Flag to indicate transponder Ident has been activated.
	IsOnGround bool // = 21 //	 Flag to indicate ground squat switch is active

	// Flags filled (and only valid) during parsing, interrogated by methods below
	hasPosition bool
}

func (m Msg)HasPosition() bool { return m.hasPosition }

func (m Msg)String() string {
	s := fmt.Sprintf("%s%d : %s", m.Type, m.SubType, m.Icao24)
	if m.HasPosition() {
		s += fmt.Sprintf(" %s", m.Position)
	}
	return s
}

// Signature is a subset of a composite ADSB message that can be considered
// to identify the content of the message; if two messages have equivalent
// Signatures, then we can consider them to be identical / duplicates.
type Signature struct {
	Pos geo.Latlong
	Icao24 IcaoId
}
func (m *CompositeMsg)GetSignature() Signature {
	return Signature{
		Pos: m.Position,
		Icao24: m.Icao24,
	}
}

// CompositeMsg has the same data fields as a Msg, but contains data from multiple Msgs. This is
// because ADS-B messages are normally emitted with only some fields filled; to get altitude, speed
// location *and* callsign, you need to combine ~3 messages. We use a distinct type for these, to be
// unambiguous about where the data came from.
type CompositeMsg struct {
	Msg // Embedded stuct
	// Real UTC timefields ??
	ReceiverName  string // Some identifier for the ADS-B receiver that generated this data
}

func (cm CompositeMsg)String() string {
	pos := fmt.Sprintf(" (%.7f,%.7f)", cm.Position.Lat, cm.Position.Long)
	return fmt.Sprintf("%s%d+ : %s[%7.7s] %5df, %3dk, %5df/m, %3ddeg, %s @ %s (%s)",
		cm.Type, cm.SubType, cm.Icao24, cm.Callsign,
		cm.Altitude, cm.GroundSpeed, cm.VerticalRate, cm.Track, pos, cm.GeneratedTimestampUTC,
		cm.ReceiverName)
}

type CompositeMsgPtrByTimeAsc []*CompositeMsg
func (a CompositeMsgPtrByTimeAsc) Len() int          { return len(a) }
func (a CompositeMsgPtrByTimeAsc) Swap(i,j int)      { a[i],a[j] = a[j],a[i] }
func (a CompositeMsgPtrByTimeAsc) Less(i,j int) bool {
	return a[j].GeneratedTimestampUTC.After(a[i].GeneratedTimestampUTC)
}
<commit_msg>Oops, second part of this.<commit_after>package adsb

import (
	"fmt"
	"time"

	"github.com/skypies/geo"
)

type IcaoId string

// http://woodair.net/SBS/Article/Barebones42_Socket_Data.htm
// https://github.com/MalcolmRobb/dump1090/blob/master/mode_s.c#L834
//
// ** NOTE ** : we're not actually populating all of this yet
//
type Msg struct {
	// This set of data is basically the SBS1 format, not the ADS-B format.

	Type string // = 0 // type	 (MSG, STA, ID, AIR, SEL or CLK). We ignore all but MSG.
	SubType int64 // = 1 // Type	 MSG sub types 1 to 8. Not used by other message types.
	// Session = 2 // ID	 Database Session record number
	// AircraftID = 3 //	 Database Aircraft record number
	Icao24 IcaoId //  = 4 //	 Aircraft Mode S hexadecimal code
	GeneratedTimestampUTC time.Time
	LoggedTimestampUTC    time.Time
	//DateGen = 6 // message generated	  As it says
	//TimeGen = 7 // message generated	  As it says
	//DateLog = 8 // message logged	  As it says
	//TimeLog = 9 // message logged	  As it says
	Callsign string // = 10 //	 An eight digit flight ID - can be flight number or registration
	Altitude int64 // = 11 //	 Mode C altitude. Height relative to 1013.2mb (Flight Level).
	GroundSpeed int64 // = 12 //	 Speed over ground (not indicated airspeed)
	Track int64 // = 13 //	 Track of aircraft (not heading). Derived from the velocity E/W, N/S

	Position geo.Latlong
	//Latitude float64 // = 14 //	 North and East positive. South and West negative.
	//Longitude float64 // = 15 //	 North and East positive. South and West negative.

	VerticalRate int64 // = 16 //	 64ft resolution
	Squawk string // = 17 //	 Assigned Mode A squawk code.
	AlertSquawkChange bool // = 18 // (Squawk change)	 Flag to indicate squawk has changed.
	Emergency bool // = 19 //	 Flag to indicate emergency code has been set
	SPI bool // = 20 // (Ident)	 Flag to indicate transponder Ident has been activated.
	IsOnGround bool // = 21 //	 Flag to indicate ground squat switch is active

	// Flags filled (and only valid) during parsing, interrogated by methods below
	hasPosition bool
}

func (m Msg)HasPosition() bool { return m.hasPosition }

func (m Msg)String() string {
	s := fmt.Sprintf("%s%d : %s", m.Type, m.SubType, m.Icao24)
	if m.HasPosition() {
		s += fmt.Sprintf(" %s", m.Position)
	}
	return s
}
<|endoftext|>