<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
	"github.com/sdboyer/gps"
)

var initCmd = &command{
	fn:   runInit,
	name: "init",
	short: `
	Write Manifest file in the root of the project directory.
	`,
	long: `
	Populates Manifest file with current deps of this project.
	The specified version of each dependent repository is the version
	available in the user's workspaces (as specified by GOPATH).
	If the dependency is not present in any workspaces it is not be
	included in the Manifest.
	Writes Lock file(?)
	Creates vendor/ directory(?)

    Notes from DOC:
    Reads existing dependency information written by other tools.
    Noting any information that is lost (unsupported features, etc).
    This functionality will be removed after a transition period (1 year?).
    Write Manifest file in the root of the project directory.
    * Populates Manifest file with current deps of this project.
    The specified version of each dependent repository is the version available in the user's workspaces (including vendor/ directories, if present).
    If the dependency is not present in any workspaces it will not be included in the Manifest. A warning will be issued for these dependencies.
    Creates vendor/ directory (if it does not exist)
    Copies the project’s dependencies from the workspace to the vendor/ directory (if they’re not already there).
    Writes a Lockfile in the root of the project directory.
    Invoke “dep status”.
	`,
}

func determineProjectRoot(path string) (string, error) {
	gopath := os.Getenv("GOPATH")
	for _, gp := range filepath.SplitList(gopath) {
		srcprefix := filepath.Join(gp, "src") + string(filepath.Separator)
		if strings.HasPrefix(path, srcprefix) {
			// filepath.ToSlash because we're dealing with an import path now,
			// not an fs path
			return filepath.ToSlash(strings.TrimPrefix(path, srcprefix)), nil
		}
	}
	return "", fmt.Errorf("%s not in any $GOPATH", path)
}

// TODO: Error when there is a lockfile, but no manifest?
func runInit(args []string) error {
	if len(args) > 1 {
		return fmt.Errorf("Too many args: %d", len(args))
	}
	var p string
	var err error
	if len(args) == 0 {
		p, err = os.Getwd()
		if err != nil {
			return errors.Wrap(err, "os.Getwd")
		}
	} else {
		p = args[0]
	}

	mf := filepath.Join(p, manifestName)

	// TODO: Lstat ? Do we care?
	_, err = os.Stat(mf)
	if err == nil {
		return fmt.Errorf("Manifest file '%s' already exists", mf)
	}
	if os.IsNotExist(err) {
		pr, err := determineProjectRoot(p)
		if err != nil {
			return errors.Wrap(err, "determineProjectRoot")
		}
		pkgT, err := gps.ListPackages(p, pr)
		if err != nil {
			return errors.Wrap(err, "gps.ListPackages")
		}
		sm, err := getSourceManager()
		if err != nil {
			return errors.Wrap(err, "getSourceManager")
		}
		defer sm.Release()
		m := newRawManifest()
		for _, v := range pkgT.Packages {
			// TODO: Some errors maybe should not be skipped ;-)
			if v.Err != nil {
				continue
			}

			for _, i := range v.P.Imports {
				if isStdLib(i) { // TODO: Replace with non stubbed version
					continue
				}
				pr, err := sm.DeduceProjectRoot(i)
				if err != nil {
					return errors.Wrap(err, "sm.DeduceProjectRoot") // TODO: Skip and report ?
				}
				// TODO: This is just wrong, need to figure out manifest file structure
				m.Dependencies[string(pr)] = possibleProps{}
			}
		}
		return errors.Wrap(writeManifest(mf, m), "writeManifest")
	}
	return errors.Wrap(err, "runInit fall through")
}

func isStdLib(i string) bool {
	switch i {
	case "bytes", "encoding/hex", "errors", "sort", "encoding/json", "flag", "fmt", "io", "os", "path/filepath", "strings", "text/tabwriter":
		return true
	}
	return false
}

func writeManifest(path string, m rawManifest) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	e := json.NewEncoder(f)
	return e.Encode(m)
}

func createManifest(path string) error {
	return writeManifest(path, newRawManifest())
}
<commit_msg>dep: write a basically correct manifest on init<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
	"github.com/sdboyer/gps"
)

var initCmd = &command{
	fn:   runInit,
	name: "init",
	short: `
	Write Manifest file in the root of the project directory.
	`,
	long: `
	Populates Manifest file with current deps of this project.
	The specified version of each dependent repository is the version
	available in the user's workspaces (as specified by GOPATH).
	If the dependency is not present in any workspaces it is not be
	included in the Manifest.
	Writes Lock file(?)
	Creates vendor/ directory(?)

    Notes from DOC:
    Reads existing dependency information written by other tools.
    Noting any information that is lost (unsupported features, etc).
    This functionality will be removed after a transition period (1 year?).
    Write Manifest file in the root of the project directory.
    * Populates Manifest file with current deps of this project.
    The specified version of each dependent repository is the version available in the user's workspaces (including vendor/ directories, if present).
    If the dependency is not present in any workspaces it will not be included in the Manifest. A warning will be issued for these dependencies.
    Creates vendor/ directory (if it does not exist)
    Copies the project’s dependencies from the workspace to the vendor/ directory (if they’re not already there).
    Writes a Lockfile in the root of the project directory.
    Invoke “dep status”.
	`,
}

func determineProjectRoot(path string) (string, error) {
	gopath := os.Getenv("GOPATH")
	for _, gp := range filepath.SplitList(gopath) {
		srcprefix := filepath.Join(gp, "src") + string(filepath.Separator)
		if strings.HasPrefix(path, srcprefix) {
			// filepath.ToSlash because we're dealing with an import path now,
			// not an fs path
			return filepath.ToSlash(strings.TrimPrefix(path, srcprefix)), nil
		}
	}
	return "", fmt.Errorf("%s not in any $GOPATH", path)
}

// TODO: Error when there is a lockfile, but no manifest?
func runInit(args []string) error {
	if len(args) > 1 {
		return fmt.Errorf("Too many args: %d", len(args))
	}
	var p string
	var err error
	if len(args) == 0 {
		p, err = os.Getwd()
		if err != nil {
			return errors.Wrap(err, "os.Getwd")
		}
	} else {
		p = args[0]
	}

	mf := filepath.Join(p, manifestName)

	// TODO: Lstat ? Do we care?
	_, err = os.Stat(mf)
	if err == nil {
		return fmt.Errorf("Manifest file '%s' already exists", mf)
	}
	if os.IsNotExist(err) {
		pr, err := determineProjectRoot(p)
		if err != nil {
			return errors.Wrap(err, "determineProjectRoot")
		}
		pkgT, err := gps.ListPackages(p, pr)
		if err != nil {
			return errors.Wrap(err, "gps.ListPackages")
		}
		sm, err := getSourceManager()
		if err != nil {
			return errors.Wrap(err, "getSourceManager")
		}
		defer sm.Release()

		// TODO: This is just wrong, need to figure out manifest file structure
		m := manifest{
			Dependencies: make(gps.ProjectConstraints),
		}

		processed := make(map[gps.ProjectRoot]bool)
		ondisk := make(map[gps.ProjectRoot]gps.Version)
		for _, v := range pkgT.Packages {
			// TODO: Some errors maybe should not be skipped ;-)
			if v.Err != nil {
				continue
			}

			for _, i := range v.P.Imports {
				if isStdLib(i) { // TODO: Replace with non stubbed version
					continue
				}
				pr, err := sm.DeduceProjectRoot(i)
				if err != nil {
					return errors.Wrap(err, "sm.DeduceProjectRoot") // TODO: Skip and report ?
				}

				if processed[pr] {
					continue
				}
				processed[pr] = true

				v, err := whatVersionIsOnDiskForThisThing(pr)
				if err != nil {
					fmt.Printf("Could not determine version for %q, omitting from generated manifest\n", pr)
					continue
				}

				ondisk[pr] = v
				pp := gps.ProjectProperties{}
				switch v.Type() {
				case "branch", "version", "rev":
					pp.Constraint = v
				case "semver":
					c, _ := gps.NewSemverConstraint("^" + v.String())
					pp.Constraint = c
				}

				m.Dependencies[pr] = pp
			}
		}

		return errors.Wrap(writeManifest(mf, &m), "writeManifest")
	}
	return errors.Wrap(err, "runInit fall through")
}

// TODO this is a stub, make it not a stub when gps gets its act together
func isStdLib(i string) bool {
	switch i {
	case "bytes", "encoding/hex", "errors", "sort", "encoding/json", "flag", "fmt", "io", "os", "path/filepath", "strings", "text/tabwriter":
		return true
	}
	return false
}

// TODO rename this to something not dumb when it becomes not a stub
func whatVersionIsOnDiskForThisThing(pr gps.ProjectRoot) (gps.Version, error) {
	switch pr {
	case "github.com/sdboyer/gps":
		return gps.NewVersion("v0.12.0").Is("9ca61cb4e9851c80bb537e7d8e1be56e18e03cc9"), nil
	case "github.com/Masterminds/semver":
		return gps.NewBranch("2.x").Is("b3ef6b1808e9889dfb8767ce7068db923a3d07de"), nil
	case "github.com/pkg/errors":
		return gps.NewVersion("v0.8.0").Is("645ef00459ed84a119197bfb8d8205042c6df63d"), nil
	}

	return nil, fmt.Errorf("unknown project")
}

func writeManifest(path string, m *manifest) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	b, err := m.MarshalJSON()
	if err != nil {
		return err
	}

	_, err = f.Write(b)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"net"
	"fmt"
	"syscall"
	//"golang.org/x/net/ipv4"
)

type IP_Conn struct {
	fd        int
	version   uint8
	dst, src  string
	headerLen uint16
	//len uint16
	//id uint16
	ttl      uint8
	protocol uint8
	//checksum int
	identifier uint16
}

func NewIP_Conn(dst string) (*IP_Conn, error) {
	//pc, err := net.ListenIP("ip4:17", &net.IPAddr{IP: net.ParseIP(dst)})
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
	if err != nil {
		fmt.Println("Failed to ListenIP")
		return nil, err
	}

	return &IP_Conn{
		fd:         fd,
		version:    4,
		headerLen:  20,
		dst:        dst,
		src:        "127.0.0.1",
		ttl:        8,
		protocol:   17,
		identifier: 20000,
	}, nil
}

func calcChecksum(head []byte, excludeChecksum bool) uint16 {
	totalSum := uint64(0)
	for ind, elem := range head {
		if (ind == 10 || ind == 11) && excludeChecksum { // Ignore the checksum in some situations
			continue
		}

		if ind%2 == 0 {
			totalSum += (uint64(elem) << 8)
		} else {
			totalSum += uint64(elem)
		}
	}
	fmt.Println("Checksum total: ", totalSum)

	for prefix := (totalSum >> 16); prefix != 0; prefix = (totalSum >> 16) {
		//        fmt.Println(prefix)
		//        fmt.Println(totalSum)
		//        fmt.Println(totalSum & 0xffff)
		totalSum = uint64(totalSum&0xffff) + prefix
	}
	fmt.Println("Checksum after carry: ", totalSum)

	carried := uint16(totalSum)

	return ^carried
}

func slicePacket(b []byte) (payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	fmt.Println("HdrLen: ", hdrLen)
	return b[hdrLen:]
}

func (ipc *IP_Conn) ReadFrom(b []byte) (payload []byte, e error) {
	n, err := syscall.Read(ipc.fd, b) // TODO: verify the checksum/other info
	b = b[:n]
	fmt.Println("Read Length: ", n)
	fmt.Println("Full Read Data (after trim): ", b)
	p := slicePacket(b)

	return p, err
}

func (ipc *IP_Conn) WriteTo(p []byte) error {
	totalLen := uint16(ipc.headerLen) + uint16(len(p))
	fmt.Println("Total Len: ", totalLen)
	packet := make([]byte, ipc.headerLen)
	packet[0] = (byte)((ipc.version << 4) + (uint8)(ipc.headerLen/4)) // Version, IHL
	packet[1] = 0
	packet[2] = (byte)(totalLen >> 8) // Total Len
	packet[3] = (byte)(totalLen)

	id := ipc.identifier
	packet[4] = byte(id >> 8) // Identification
	packet[5] = byte(id)
	ipc.identifier++

	packet[6] = byte(1 << 6)         // Flags: Don't fragment
	packet[7] = 0                    // Fragment Offset
	packet[8] = (byte)(ipc.ttl)      // Time to Live
	packet[9] = (byte)(ipc.protocol) // Protocol

	// Src and Dst IPs
	srcIP := net.ParseIP(ipc.src)
	fmt.Println(srcIP)
	//    fmt.Println(srcIP[12])
	//    fmt.Println(srcIP[13])
	//    fmt.Println(srcIP[14])
	//    fmt.Println(srcIP[15])
	dstIP := net.ParseIP(ipc.dst)
	fmt.Println(dstIP)
	packet[12] = srcIP[12]
	packet[13] = srcIP[13]
	packet[14] = srcIP[14]
	packet[15] = srcIP[15]
	packet[16] = dstIP[12]
	packet[17] = dstIP[13]
	packet[18] = dstIP[14]
	packet[19] = dstIP[15]

	// IPv4 header test (before checksum)
	fmt.Println("Packet before checksum: ", packet)

	// Checksum
	checksum := calcChecksum(packet[:20], true)
	packet[10] = byte(checksum >> 8)
	packet[11] = byte(checksum)

	// Payload
	packet = append(packet, p...)
	fmt.Println("Full Packet:  ", packet)

	dstIPAddr, err := net.ResolveIPAddr("ip", ipc.dst)
	if err != nil {
		//        fmt.Println(err)
		return err
	}
	fmt.Println("Full Address: ", dstIPAddr)

	//ipc.pc.WriteMsgIP(packet, nil, dstIPAddr)

	addr := syscall.SockaddrInet4{
		Port: 0,
		//Addr: [4]byte{127, 0, 0, 1},
        Addr: [4]byte{
            dstIPAddr.IP[12],
            dstIPAddr.IP[13],
            dstIPAddr.IP[14],
            dstIPAddr.IP[15],
        },
	}
	syscall.Sendto(ipc.fd, packet, 0, &addr)
	return err
}

func (ipc *IP_Conn) Close() error {
	return nil
    // TODO: actually close the fd socket
	//return ipc.pc.Close()
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<commit_msg>Closed socket<commit_after>package main

import (
	"fmt"
	"net"
	"syscall"
	//"golang.org/x/net/ipv4"
)

type IP_Conn struct {
	fd        int
	version   uint8
	dst, src  string
	headerLen uint16
	//len uint16
	//id uint16
	ttl      uint8
	protocol uint8
	//checksum int
	identifier uint16
}

func NewIP_Conn(dst string) (*IP_Conn, error) {
	//pc, err := net.ListenIP("ip4:17", &net.IPAddr{IP: net.ParseIP(dst)})
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
	if err != nil {
		fmt.Println("Failed to ListenIP")
		return nil, err
	}

	return &IP_Conn{
		fd:         fd,
		version:    4,
		headerLen:  20,
		dst:        dst,
		src:        "127.0.0.1",
		ttl:        8,
		protocol:   17,
		identifier: 20000,
	}, nil
}

func calcChecksum(head []byte, excludeChecksum bool) uint16 {
	totalSum := uint64(0)
	for ind, elem := range head {
		if (ind == 10 || ind == 11) && excludeChecksum { // Ignore the checksum in some situations
			continue
		}

		if ind%2 == 0 {
			totalSum += (uint64(elem) << 8)
		} else {
			totalSum += uint64(elem)
		}
	}
	fmt.Println("Checksum total: ", totalSum)

	for prefix := (totalSum >> 16); prefix != 0; prefix = (totalSum >> 16) {
		//        fmt.Println(prefix)
		//        fmt.Println(totalSum)
		//        fmt.Println(totalSum & 0xffff)
		totalSum = uint64(totalSum&0xffff) + prefix
	}
	fmt.Println("Checksum after carry: ", totalSum)

	carried := uint16(totalSum)

	return ^carried
}

func slicePacket(b []byte) (payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	fmt.Println("HdrLen: ", hdrLen)
	return b[hdrLen:]
}

func (ipc *IP_Conn) ReadFrom(b []byte) (payload []byte, e error) {
	n, err := syscall.Read(ipc.fd, b) // TODO: verify the checksum/other info
	b = b[:n]
	fmt.Println("Read Length: ", n)
	fmt.Println("Full Read Data (after trim): ", b)
	p := slicePacket(b)

	return p, err
}

func (ipc *IP_Conn) WriteTo(p []byte) error {
	totalLen := uint16(ipc.headerLen) + uint16(len(p))
	fmt.Println("Total Len: ", totalLen)
	packet := make([]byte, ipc.headerLen)
	packet[0] = (byte)((ipc.version << 4) + (uint8)(ipc.headerLen/4)) // Version, IHL
	packet[1] = 0
	packet[2] = (byte)(totalLen >> 8) // Total Len
	packet[3] = (byte)(totalLen)

	id := ipc.identifier
	packet[4] = byte(id >> 8) // Identification
	packet[5] = byte(id)
	ipc.identifier++

	packet[6] = byte(1 << 6)         // Flags: Don't fragment
	packet[7] = 0                    // Fragment Offset
	packet[8] = (byte)(ipc.ttl)      // Time to Live
	packet[9] = (byte)(ipc.protocol) // Protocol

	// Src and Dst IPs
	srcIP := net.ParseIP(ipc.src)
	fmt.Println(srcIP)
	//    fmt.Println(srcIP[12])
	//    fmt.Println(srcIP[13])
	//    fmt.Println(srcIP[14])
	//    fmt.Println(srcIP[15])
	dstIP := net.ParseIP(ipc.dst)
	fmt.Println(dstIP)
	packet[12] = srcIP[12]
	packet[13] = srcIP[13]
	packet[14] = srcIP[14]
	packet[15] = srcIP[15]
	packet[16] = dstIP[12]
	packet[17] = dstIP[13]
	packet[18] = dstIP[14]
	packet[19] = dstIP[15]

	// IPv4 header test (before checksum)
	fmt.Println("Packet before checksum: ", packet)

	// Checksum
	checksum := calcChecksum(packet[:20], true)
	packet[10] = byte(checksum >> 8)
	packet[11] = byte(checksum)

	// Payload
	packet = append(packet, p...)
	fmt.Println("Full Packet:  ", packet)

	dstIPAddr, err := net.ResolveIPAddr("ip", ipc.dst)
	if err != nil {
		//        fmt.Println(err)
		return err
	}
	fmt.Println("Full Address: ", dstIPAddr)

	//ipc.pc.WriteMsgIP(packet, nil, dstIPAddr)

	addr := syscall.SockaddrInet4{
		Port: 0,
		//Addr: [4]byte{127, 0, 0, 1},
		Addr: [4]byte{
			dstIPAddr.IP[12],
			dstIPAddr.IP[13],
			dstIPAddr.IP[14],
			dstIPAddr.IP[15],
		},
	}
	syscall.Sendto(ipc.fd, packet, 0, &addr)
	return err
}

func (ipc *IP_Conn) Close() error {
	return syscall.Close(ipc.fd)
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<|endoftext|>


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

// Changes copyright ©2012 The bíogo.bam 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 egzip implements reading and writing of gzip format compressed files,
// as specified in RFC 1952, changing some behaviours implemented by the Go core
// library while maintaining conformance with the specification.
package egzip

import (
	"code.google.com/p/biogo.bam/bgzf/bufio"
	"compress/flate"
	"compress/gzip"
	"errors"
	"hash"
	"hash/crc32"
	"io"
	"time"
)

const (
	gzipID1     = 0x1f
	gzipID2     = 0x8b
	gzipDeflate = 8
	flagText    = 1 << 0
	flagHdrCrc  = 1 << 1
	flagExtra   = 1 << 2
	flagName    = 1 << 3
	flagComment = 1 << 4
)

var (
	ErrNotASeeker = errors.New("egzip: not a seeker")
	NewBlock      = errors.New("egzip: new block")
)

type reader interface {
	flate.Reader
	Reset(io.Reader)
}

func makeReader(r io.Reader) reader {
	if rr, ok := r.(reader); ok {
		return rr
	}
	return bufio.NewReader(r)
}

// A Reader is an io.Reader that can be read to retrieve
// uncompressed data from a gzip-format compressed file.
//
// In general, a gzip file can be a concatenation of gzip files,
// each with its own header.  Reads from the Reader
// return the concatenation of the uncompressed data of each.
// Only the first header is recorded in the Reader fields.
//
// Gzip files store a length and checksum of the uncompressed data.
// The Reader will return a ErrChecksum when Read
// reaches the end of the uncompressed data if it does not
// have the expected length or checksum.  Clients should treat data
// returned by Read as tentative until they receive the io.EOF
// marking the end of the data.
type Reader struct {
	BlockLimited bool // Stop reading at the end of a member and return NewBlock.
	*gzip.Header
	r            reader
	s            io.ReadSeeker
	decompressor io.ReadCloser
	digest       hash.Hash32
	size         uint32
	flg          byte
	buf          [512]byte
	err          error
}

// NewReader creates a new Reader reading the given reader.
// The implementation buffers input and may read more data than necessary from r.
// It is the caller's responsibility to call Close on the Reader when done.
func NewReader(r io.Reader, h *gzip.Header) (*Reader, error) {
	z := new(Reader)
	z.Header = h
	z.r = makeReader(r)
	z.digest = crc32.NewIEEE()
	z.s, _ = r.(io.ReadSeeker)
	if err := z.readHeader(); err != nil {
		return nil, err
	}
	return z, nil
}

// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
func get4(p []byte) uint32 {
	return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
}

func (z *Reader) readString() (string, error) {
	var err error
	needconv := false
	for i := 0; ; i++ {
		if i >= len(z.buf) {
			return "", gzip.ErrHeader
		}
		z.buf[i], err = z.r.ReadByte()
		if err != nil {
			return "", err
		}
		if z.buf[i] > 0x7f {
			needconv = true
		}
		if z.buf[i] == 0 {
			// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
			if needconv {
				s := make([]rune, 0, i)
				for _, v := range z.buf[0:i] {
					s = append(s, rune(v))
				}
				return string(s), nil
			}
			return string(z.buf[0:i]), nil
		}
	}
	panic("not reached")
}

func (z *Reader) read2() (uint32, error) {
	_, err := io.ReadFull(z.r, z.buf[0:2])
	if err != nil {
		return 0, err
	}
	return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
}

func (z *Reader) readHeader() error {
	_, err := io.ReadFull(z.r, z.buf[0:10])
	if err != nil {
		return err
	}
	if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
		return gzip.ErrHeader
	}
	z.flg = z.buf[3]
	z.ModTime = time.Unix(int64(get4(z.buf[4:8])), 0)
	// z.buf[8] is xfl, ignored
	z.OS = z.buf[9]
	z.digest.Reset()
	z.digest.Write(z.buf[0:10])

	if z.flg&flagExtra != 0 {
		n, err := z.read2()
		if err != nil {
			return err
		}
		data := make([]byte, n)
		if _, err = io.ReadFull(z.r, data); err != nil {
			return err
		}
		z.Extra = data
	}

	var s string
	if z.flg&flagName != 0 {
		if s, err = z.readString(); err != nil {
			return err
		}
		z.Name = s
	}

	if z.flg&flagComment != 0 {
		if s, err = z.readString(); err != nil {
			return err
		}
		z.Comment = s
	}

	if z.flg&flagHdrCrc != 0 {
		n, err := z.read2()
		if err != nil {
			return err
		}
		sum := z.digest.Sum32() & 0xFFFF
		if n != sum {
			return gzip.ErrHeader
		}
	}

	z.digest.Reset()
	z.decompressor = flate.NewReader(z.r)
	return nil
}

func (z *Reader) Seek(offset int64, whence int) error {
	if z.s == nil {
		z.err = ErrNotASeeker
		return z.err
	}

	_, z.err = z.s.Seek(offset, whence)
	if z.err != nil {
		return z.err
	}
	z.r.Reset(z.s)

	err := z.readHeader()
	if err != nil {
		return err
	}

	z.err = nil
	z.digest.Reset()
	z.size = 0
	return nil
}

func (z *Reader) Read(p []byte) (n int, err error) {
	if z.err != nil {
		return 0, z.err
	}
	if len(p) == 0 {
		return 0, nil
	}

	n, err = z.decompressor.Read(p)
	z.digest.Write(p[0:n])
	z.size += uint32(n)
	if n != 0 || err != io.EOF {
		z.err = err
		return
	}

	// Finished file; check checksum + size.
	if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil {
		z.err = err
		return 0, err
	}
	crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
	sum := z.digest.Sum32()
	if sum != crc32 || isize != z.size {
		z.err = gzip.ErrChecksum
		return 0, z.err
	}

	// File is ok; is there another?
	if err = z.readHeader(); err != nil {
		z.err = err
		return
	}

	// Yes. Reset and read from it if not block limited.
	z.digest.Reset()
	z.size = 0
	if z.BlockLimited {
		err = NewBlock
		return
	}
	return z.Read(p)
}

// Close closes the Reader. It does not close the underlying io.Reader.
func (z *Reader) Close() error { return z.decompressor.Close() }
<commit_msg>Remove unreachable code<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the Go LICENSE file.

// Changes copyright ©2012 The bíogo.bam 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 egzip implements reading and writing of gzip format compressed files,
// as specified in RFC 1952, changing some behaviours implemented by the Go core
// library while maintaining conformance with the specification.
package egzip

import (
	"code.google.com/p/biogo.bam/bgzf/bufio"
	"compress/flate"
	"compress/gzip"
	"errors"
	"hash"
	"hash/crc32"
	"io"
	"time"
)

const (
	gzipID1     = 0x1f
	gzipID2     = 0x8b
	gzipDeflate = 8
	flagText    = 1 << 0
	flagHdrCrc  = 1 << 1
	flagExtra   = 1 << 2
	flagName    = 1 << 3
	flagComment = 1 << 4
)

var (
	ErrNotASeeker = errors.New("egzip: not a seeker")
	NewBlock      = errors.New("egzip: new block")
)

type reader interface {
	flate.Reader
	Reset(io.Reader)
}

func makeReader(r io.Reader) reader {
	if rr, ok := r.(reader); ok {
		return rr
	}
	return bufio.NewReader(r)
}

// A Reader is an io.Reader that can be read to retrieve
// uncompressed data from a gzip-format compressed file.
//
// In general, a gzip file can be a concatenation of gzip files,
// each with its own header.  Reads from the Reader
// return the concatenation of the uncompressed data of each.
// Only the first header is recorded in the Reader fields.
//
// Gzip files store a length and checksum of the uncompressed data.
// The Reader will return a ErrChecksum when Read
// reaches the end of the uncompressed data if it does not
// have the expected length or checksum.  Clients should treat data
// returned by Read as tentative until they receive the io.EOF
// marking the end of the data.
type Reader struct {
	BlockLimited bool // Stop reading at the end of a member and return NewBlock.
	*gzip.Header
	r            reader
	s            io.ReadSeeker
	decompressor io.ReadCloser
	digest       hash.Hash32
	size         uint32
	flg          byte
	buf          [512]byte
	err          error
}

// NewReader creates a new Reader reading the given reader.
// The implementation buffers input and may read more data than necessary from r.
// It is the caller's responsibility to call Close on the Reader when done.
func NewReader(r io.Reader, h *gzip.Header) (*Reader, error) {
	z := new(Reader)
	z.Header = h
	z.r = makeReader(r)
	z.digest = crc32.NewIEEE()
	z.s, _ = r.(io.ReadSeeker)
	if err := z.readHeader(); err != nil {
		return nil, err
	}
	return z, nil
}

// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
func get4(p []byte) uint32 {
	return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
}

func (z *Reader) readString() (string, error) {
	var err error
	needconv := false
	for i := 0; ; i++ {
		if i >= len(z.buf) {
			return "", gzip.ErrHeader
		}
		z.buf[i], err = z.r.ReadByte()
		if err != nil {
			return "", err
		}
		if z.buf[i] > 0x7f {
			needconv = true
		}
		if z.buf[i] == 0 {
			// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
			if needconv {
				s := make([]rune, 0, i)
				for _, v := range z.buf[0:i] {
					s = append(s, rune(v))
				}
				return string(s), nil
			}
			return string(z.buf[0:i]), nil
		}
	}
}

func (z *Reader) read2() (uint32, error) {
	_, err := io.ReadFull(z.r, z.buf[0:2])
	if err != nil {
		return 0, err
	}
	return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
}

func (z *Reader) readHeader() error {
	_, err := io.ReadFull(z.r, z.buf[0:10])
	if err != nil {
		return err
	}
	if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
		return gzip.ErrHeader
	}
	z.flg = z.buf[3]
	z.ModTime = time.Unix(int64(get4(z.buf[4:8])), 0)
	// z.buf[8] is xfl, ignored
	z.OS = z.buf[9]
	z.digest.Reset()
	z.digest.Write(z.buf[0:10])

	if z.flg&flagExtra != 0 {
		n, err := z.read2()
		if err != nil {
			return err
		}
		data := make([]byte, n)
		if _, err = io.ReadFull(z.r, data); err != nil {
			return err
		}
		z.Extra = data
	}

	var s string
	if z.flg&flagName != 0 {
		if s, err = z.readString(); err != nil {
			return err
		}
		z.Name = s
	}

	if z.flg&flagComment != 0 {
		if s, err = z.readString(); err != nil {
			return err
		}
		z.Comment = s
	}

	if z.flg&flagHdrCrc != 0 {
		n, err := z.read2()
		if err != nil {
			return err
		}
		sum := z.digest.Sum32() & 0xFFFF
		if n != sum {
			return gzip.ErrHeader
		}
	}

	z.digest.Reset()
	z.decompressor = flate.NewReader(z.r)
	return nil
}

func (z *Reader) Seek(offset int64, whence int) error {
	if z.s == nil {
		z.err = ErrNotASeeker
		return z.err
	}

	_, z.err = z.s.Seek(offset, whence)
	if z.err != nil {
		return z.err
	}
	z.r.Reset(z.s)

	err := z.readHeader()
	if err != nil {
		return err
	}

	z.err = nil
	z.digest.Reset()
	z.size = 0
	return nil
}

func (z *Reader) Read(p []byte) (n int, err error) {
	if z.err != nil {
		return 0, z.err
	}
	if len(p) == 0 {
		return 0, nil
	}

	n, err = z.decompressor.Read(p)
	z.digest.Write(p[0:n])
	z.size += uint32(n)
	if n != 0 || err != io.EOF {
		z.err = err
		return
	}

	// Finished file; check checksum + size.
	if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil {
		z.err = err
		return 0, err
	}
	crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
	sum := z.digest.Sum32()
	if sum != crc32 || isize != z.size {
		z.err = gzip.ErrChecksum
		return 0, z.err
	}

	// File is ok; is there another?
	if err = z.readHeader(); err != nil {
		z.err = err
		return
	}

	// Yes. Reset and read from it if not block limited.
	z.digest.Reset()
	z.size = 0
	if z.BlockLimited {
		err = NewBlock
		return
	}
	return z.Read(p)
}

// Close closes the Reader. It does not close the underlying io.Reader.
func (z *Reader) Close() error { return z.decompressor.Close() }
<|endoftext|>


<commit_before>package query

import (
	"database/sql"
	"fmt"
	ggproto "github.com/gogo/protobuf/proto"
	pb "github.com/mediachain/concat/proto"
	"strings"
)

// A RowSelector extracts the next value from an sql result set
type RowSelector interface {
	Scan(src RowScanner) (interface{}, error)
}

// Common Scan interface between sql.Row and sql.Rows
type RowScanner interface {
	Scan(res ...interface{}) error
}

type QueryCompileError string

func (e QueryCompileError) Error() string {
	return string(e)
}

// CompileQuery compiles a query to sql.
// Returns the compiled sql query and a selector for extracting
// values from an sql result set
// Note: The row selector should be used in single-threaded context
func CompileQuery(q *Query) (string, RowSelector, error) {
	var sqlq string
	switch {
	case isStatementQuery(q):
		sqlq = "SELECT %s FROM Statement"
	case isEnvelopeQuery(q):
		sqlq = "SELECT %s FROM Envelope"
	default:
		sqlq = "SELECT %s FROM Statement JOIN Envelope ON Statement.id = Envelope.id"
	}

	cols, err := compileQueryColumns(q)
	if err != nil {
		return "", nil, err
	}
	sqlq = fmt.Sprintf(sqlq, cols)

	crit, err := compileQueryCriteria(q)
	if err != nil {
		return "", nil, err
	}
	if crit != "" {
		sqlq = fmt.Sprintf("%s WHERE %s", sqlq, crit)
	}

	if q.limit > 0 {
		sqlq = fmt.Sprintf("%s LIMIT %d", sqlq, q.limit)
	}

	rsel, err := compileQueryRowSelector(q)
	if err != nil {
		return "", nil, err
	}

	return sqlq, rsel, nil
}

func compileQueryColumns(q *Query) (string, error) {
	switch sel := q.selector.(type) {
	case SimpleSelector:
		return selectorColumn(sel, selectorColumnSimple), nil

	case CompoundSelector:
		if len(sel) == 1 {
			return selectorColumn(sel[0], selectorColumnSimple), nil
		}

		cols := make([]string, len(sel))
		for x := 0; x < len(sel); x++ {
			cols[x] = selectorColumn(sel[x], selectorColumnCompound)
		}
		return strings.Join(cols, ", "), nil

	case *FunctionSelector:
		col := selectorColumn(sel.sel, selectorColumnFun)
		return fmt.Sprintf("%s(%s)", sel.op, col), nil

	default:
		return "", QueryCompileError(fmt.Sprintf("Unexpected selector type: %T", sel))
	}
}

func selectorColumn(sel SimpleSelector, rename map[string]string) string {
	col, ok := rename[string(sel)]
	if !ok {
		col = string(sel)
	}
	return col
}

var selectorColumnSimple = map[string]string{
	"*":         "data",
	"body":      "data",
	"namespace": "DISTINCT namespace",
	"publisher": "DISTINCT publisher",
	"source":    "DISTINCT source"}

var selectorColumnCompound = map[string]string{
	"*":    "data",
	"body": "data"}

var selectorColumnFun = map[string]string{
	"*":         "*",
	"body":      "data",
	"namespace": "DISTINCT namespace",
	"publisher": "DISTINCT publisher",
	"source":    "DISTINCT source"}

func compileQueryCriteria(q *Query) (string, error) {
	nscrit := compileNamespaceCriteria(q.namespace)
	if q.criteria == nil {
		return nscrit, nil
	}

	scrit, err := compileSelectorCriteria(q.criteria)
	if err != nil {
		return "", err
	}

	if nscrit != "" {
		return fmt.Sprintf("%s AND %s", nscrit, scrit), nil
	}
	return scrit, nil
}

func compileNamespaceCriteria(ns string) string {
	switch {
	case ns == "*":
		return ""
	case ns[len(ns)-1] == '*':
		pre := ns[:len(ns)-2]
		return fmt.Sprintf("namespace LIKE '%s%%'", pre)
	default:
		return fmt.Sprintf("namespace = '%s'", ns)
	}
}

func compileSelectorCriteria(c QueryCriteria) (string, error) {
	switch c := c.(type) {
	case *ValueCriteria:
		return fmt.Sprintf("%s %s '%s'", c.sel, c.op, c.val), nil

	case *TimeCriteria:
		return fmt.Sprintf("timestamp %s %d", c.op, c.ts), nil

	case *CompoundCriteria:
		left, err := compileSelectorCriteria(c.left)
		if err != nil {
			return "", err
		}

		right, err := compileSelectorCriteria(c.right)
		if err != nil {
			return "", err
		}

		return fmt.Sprintf("(%s %s %s)", left, c.op, right), nil

	case *NegatedCriteria:
		expr, err := compileSelectorCriteria(c.e)
		if err != nil {
			return "", err
		}

		return fmt.Sprintf("NOT %s", expr), nil

	default:
		return "", QueryCompileError(fmt.Sprintf("Unexpected criteria type: %T", c))
	}
}

func compileQueryRowSelector(q *Query) (RowSelector, error) {
	switch sel := q.selector.(type) {
	case SimpleSelector:
		makef, ok := makeSimpleRowSelector[string(sel)]
		if !ok {
			return nil, QueryCompileError(fmt.Sprintf("Unexpected selector: %s", sel))
		}

		return makef(), nil

	case CompoundSelector:
		return nil, QueryCompileError("Implement me!")

	case *FunctionSelector:
		return nil, QueryCompileError("Implement me!")

	default:
		return nil, QueryCompileError(fmt.Sprintf("Unexpected selector type: %T", sel))
	}
}

type MakeSimpleRowSelector func() SimpleRowSelector

type SimpleRowSelector interface {
	RowSelector
	ptr() interface{}
	value() (interface{}, error)
}

type RowSelectStatement struct {
	val sql.RawBytes
}

func (rs *RowSelectStatement) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectStatement) value() (interface{}, error) {
	stmt := new(pb.Statement)
	err := ggproto.Unmarshal(rs.val, stmt)
	if err != nil {
		return nil, err
	}
	return stmt, nil
}

func (rs *RowSelectStatement) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.value()
}

type RowSelectBody struct {
	RowSelectStatement
}

func (rs *RowSelectBody) value() (interface{}, error) {
	stmt, err := rs.RowSelectStatement.value()
	if err != nil {
		return nil, err
	}

	return stmt.(*pb.Statement).Body, nil
}

func (rs *RowSelectBody) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.value()
}

type RowSelectString struct {
	val string
}

func (rs *RowSelectString) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectString) value() (interface{}, error) {
	return rs.val, nil
}

func (rs *RowSelectString) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.val, nil
}

type RowSelectInt64 struct {
	val int64
}

func (rs *RowSelectInt64) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectInt64) value() (interface{}, error) {
	return rs.val, nil
}

func (rs *RowSelectInt64) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.val, nil
}

func makeRowSelectStatement() SimpleRowSelector {
	return &RowSelectStatement{}
}

func makeRowSelectBody() SimpleRowSelector {
	return &RowSelectBody{}
}

func makeRowSelectString() SimpleRowSelector {
	return &RowSelectString{}
}

func makeRowSelectInt64() SimpleRowSelector {
	return &RowSelectInt64{}
}

var makeSimpleRowSelector = map[string]MakeSimpleRowSelector{
	"*":         makeRowSelectStatement,
	"body":      makeRowSelectBody,
	"id":        makeRowSelectString,
	"namespace": makeRowSelectString,
	"publisher": makeRowSelectString,
	"source":    makeRowSelectString,
	"timestamp": makeRowSelectInt64}

func isStatementQuery(q *Query) bool {
	// namespace = * and only has statement selector (*, id, body) and id criteria
	// id acts as statement column
	return q.namespace == "*" &&
		isStatementSelector(q.selector) &&
		(q.criteria == nil || isStatementCriteria(q.criteria))
}

func isEnvelopeQuery(q *Query) bool {
	// namespace != * or envelope selector or any criteria
	// id acts as envelope column
	return q.namespace != "*" ||
		q.criteria != nil ||
		isEnvelopeSelector(q.selector)
}

var statementSelectorp = map[string]bool{
	"*":    true,
	"body": true,
	"id":   true}

var envelopeSelectorp = map[string]bool{
	"id":        true,
	"publisher": true,
	"namespace": true,
	"source":    true,
	"timestamp": true}

func selectorp(sel QuerySelector, tbl map[string]bool) bool {
	switch sel := sel.(type) {
	case SimpleSelector:
		return tbl[string(sel)]

	case CompoundSelector:
		for _, ssel := range sel {
			if tbl[string(ssel)] {
				return true
			}
		}
		return false

	case *FunctionSelector:
		return tbl[string(sel.sel)]

	default:
		return false
	}
}

func isStatementSelector(sel QuerySelector) bool {
	return selectorp(sel, statementSelectorp)
}

func isEnvelopeSelector(sel QuerySelector) bool {
	return selectorp(sel, envelopeSelectorp)
}

func isStatementCriteria(c QueryCriteria) bool {
	switch c := c.(type) {
	case *ValueCriteria:
		return c.sel == "id"

	case *TimeCriteria:
		return false

	case *CompoundCriteria:
		return isStatementCriteria(c.left) && isStatementCriteria(c.right)

	case *NegatedCriteria:
		return isStatementCriteria(c.e)

	default:
		return false
	}
}
<commit_msg>query compile: compound row selectors<commit_after>package query

import (
	"database/sql"
	"fmt"
	ggproto "github.com/gogo/protobuf/proto"
	pb "github.com/mediachain/concat/proto"
	"strings"
)

// A RowSelector extracts the next value from an sql result set
type RowSelector interface {
	Scan(src RowScanner) (interface{}, error)
}

// Common Scan interface between sql.Row and sql.Rows
type RowScanner interface {
	Scan(res ...interface{}) error
}

type QueryCompileError string

func (e QueryCompileError) Error() string {
	return string(e)
}

// CompileQuery compiles a query to sql.
// Returns the compiled sql query and a selector for extracting
// values from an sql result set
// Note: The row selector should be used in single-threaded context
func CompileQuery(q *Query) (string, RowSelector, error) {
	var sqlq string
	switch {
	case isStatementQuery(q):
		sqlq = "SELECT %s FROM Statement"
	case isEnvelopeQuery(q):
		sqlq = "SELECT %s FROM Envelope"
	default:
		sqlq = "SELECT %s FROM Statement JOIN Envelope ON Statement.id = Envelope.id"
	}

	cols, err := compileQueryColumns(q)
	if err != nil {
		return "", nil, err
	}
	sqlq = fmt.Sprintf(sqlq, cols)

	crit, err := compileQueryCriteria(q)
	if err != nil {
		return "", nil, err
	}
	if crit != "" {
		sqlq = fmt.Sprintf("%s WHERE %s", sqlq, crit)
	}

	if q.limit > 0 {
		sqlq = fmt.Sprintf("%s LIMIT %d", sqlq, q.limit)
	}

	rsel, err := compileQueryRowSelector(q)
	if err != nil {
		return "", nil, err
	}

	return sqlq, rsel, nil
}

func compileQueryColumns(q *Query) (string, error) {
	switch sel := q.selector.(type) {
	case SimpleSelector:
		return selectorColumn(sel, selectorColumnSimple), nil

	case CompoundSelector:
		if len(sel) == 1 {
			return selectorColumn(sel[0], selectorColumnSimple), nil
		}

		cols := make([]string, len(sel))
		for x := 0; x < len(sel); x++ {
			cols[x] = selectorColumn(sel[x], selectorColumnCompound)
		}
		return strings.Join(cols, ", "), nil

	case *FunctionSelector:
		col := selectorColumn(sel.sel, selectorColumnFun)
		return fmt.Sprintf("%s(%s)", sel.op, col), nil

	default:
		return "", QueryCompileError(fmt.Sprintf("Unexpected selector type: %T", sel))
	}
}

func selectorColumn(sel SimpleSelector, rename map[string]string) string {
	col, ok := rename[string(sel)]
	if !ok {
		col = string(sel)
	}
	return col
}

var selectorColumnSimple = map[string]string{
	"*":         "data",
	"body":      "data",
	"namespace": "DISTINCT namespace",
	"publisher": "DISTINCT publisher",
	"source":    "DISTINCT source"}

var selectorColumnCompound = map[string]string{
	"*":    "data",
	"body": "data"}

var selectorColumnFun = map[string]string{
	"*":         "*",
	"body":      "data",
	"namespace": "DISTINCT namespace",
	"publisher": "DISTINCT publisher",
	"source":    "DISTINCT source"}

func compileQueryCriteria(q *Query) (string, error) {
	nscrit := compileNamespaceCriteria(q.namespace)
	if q.criteria == nil {
		return nscrit, nil
	}

	scrit, err := compileSelectorCriteria(q.criteria)
	if err != nil {
		return "", err
	}

	if nscrit != "" {
		return fmt.Sprintf("%s AND %s", nscrit, scrit), nil
	}
	return scrit, nil
}

func compileNamespaceCriteria(ns string) string {
	switch {
	case ns == "*":
		return ""
	case ns[len(ns)-1] == '*':
		pre := ns[:len(ns)-2]
		return fmt.Sprintf("namespace LIKE '%s%%'", pre)
	default:
		return fmt.Sprintf("namespace = '%s'", ns)
	}
}

func compileSelectorCriteria(c QueryCriteria) (string, error) {
	switch c := c.(type) {
	case *ValueCriteria:
		return fmt.Sprintf("%s %s '%s'", c.sel, c.op, c.val), nil

	case *TimeCriteria:
		return fmt.Sprintf("timestamp %s %d", c.op, c.ts), nil

	case *CompoundCriteria:
		left, err := compileSelectorCriteria(c.left)
		if err != nil {
			return "", err
		}

		right, err := compileSelectorCriteria(c.right)
		if err != nil {
			return "", err
		}

		return fmt.Sprintf("(%s %s %s)", left, c.op, right), nil

	case *NegatedCriteria:
		expr, err := compileSelectorCriteria(c.e)
		if err != nil {
			return "", err
		}

		return fmt.Sprintf("NOT %s", expr), nil

	default:
		return "", QueryCompileError(fmt.Sprintf("Unexpected criteria type: %T", c))
	}
}

func compileQueryRowSelector(q *Query) (RowSelector, error) {
	switch sel := q.selector.(type) {
	case SimpleSelector:
		makef, ok := makeSimpleRowSelector[string(sel)]
		if !ok {
			return nil, QueryCompileError(fmt.Sprintf("Unexpected selector: %s", sel))
		}

		return makef(), nil

	case CompoundSelector:
		srs := make([]SimpleRowSelector, len(sel))
		ptrs := make([]interface{}, len(sel))
		for x, ssel := range sel {
			makef, ok := makeSimpleRowSelector[string(ssel)]
			if !ok {
				return nil, QueryCompileError(fmt.Sprintf("Unexpected selector: %s", sel))
			}
			srs[x] = makef()
			ptrs[x] = srs[x].ptr()
		}

		return &RowSelectCompound{sel, srs, ptrs}, nil

	case *FunctionSelector:
		return nil, QueryCompileError("Implement me!")

	default:
		return nil, QueryCompileError(fmt.Sprintf("Unexpected selector type: %T", sel))
	}
}

type MakeSimpleRowSelector func() SimpleRowSelector

type SimpleRowSelector interface {
	RowSelector
	ptr() interface{}
	value() (interface{}, error)
}

type RowSelectCompound struct {
	sel  []SimpleSelector
	srs  []SimpleRowSelector
	ptrs []interface{}
}

func (rs *RowSelectCompound) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(rs.ptrs...)
	if err != nil {
		return nil, err
	}

	obj := make(map[string]interface{})
	for x, sel := range rs.sel {
		val, err := rs.srs[x].value()
		if err != nil {
			return nil, err
		}
		obj[string(sel)] = val
	}

	return obj, nil
}

type RowSelectStatement struct {
	val sql.RawBytes
}

func (rs *RowSelectStatement) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectStatement) value() (interface{}, error) {
	stmt := new(pb.Statement)
	err := ggproto.Unmarshal(rs.val, stmt)
	if err != nil {
		return nil, err
	}
	return stmt, nil
}

func (rs *RowSelectStatement) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.value()
}

type RowSelectBody struct {
	RowSelectStatement
}

func (rs *RowSelectBody) value() (interface{}, error) {
	stmt, err := rs.RowSelectStatement.value()
	if err != nil {
		return nil, err
	}

	return stmt.(*pb.Statement).Body, nil
}

func (rs *RowSelectBody) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.value()
}

type RowSelectString struct {
	val string
}

func (rs *RowSelectString) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectString) value() (interface{}, error) {
	return rs.val, nil
}

func (rs *RowSelectString) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.val, nil
}

type RowSelectInt64 struct {
	val int64
}

func (rs *RowSelectInt64) ptr() interface{} {
	return &rs.val
}

func (rs *RowSelectInt64) value() (interface{}, error) {
	return rs.val, nil
}

func (rs *RowSelectInt64) Scan(src RowScanner) (interface{}, error) {
	err := src.Scan(&rs.val)
	if err != nil {
		return nil, err
	}
	return rs.val, nil
}

func makeRowSelectStatement() SimpleRowSelector {
	return &RowSelectStatement{}
}

func makeRowSelectBody() SimpleRowSelector {
	return &RowSelectBody{}
}

func makeRowSelectString() SimpleRowSelector {
	return &RowSelectString{}
}

func makeRowSelectInt64() SimpleRowSelector {
	return &RowSelectInt64{}
}

var makeSimpleRowSelector = map[string]MakeSimpleRowSelector{
	"*":         makeRowSelectStatement,
	"body":      makeRowSelectBody,
	"id":        makeRowSelectString,
	"namespace": makeRowSelectString,
	"publisher": makeRowSelectString,
	"source":    makeRowSelectString,
	"timestamp": makeRowSelectInt64}

func isStatementQuery(q *Query) bool {
	// namespace = * and only has statement selector (*, id, body) and id criteria
	// id acts as statement column
	return q.namespace == "*" &&
		isStatementSelector(q.selector) &&
		(q.criteria == nil || isStatementCriteria(q.criteria))
}

func isEnvelopeQuery(q *Query) bool {
	// namespace != * or envelope selector or any criteria
	// id acts as envelope column
	return q.namespace != "*" ||
		q.criteria != nil ||
		isEnvelopeSelector(q.selector)
}

var statementSelectorp = map[string]bool{
	"*":    true,
	"body": true,
	"id":   true}

var envelopeSelectorp = map[string]bool{
	"id":        true,
	"publisher": true,
	"namespace": true,
	"source":    true,
	"timestamp": true}

func selectorp(sel QuerySelector, tbl map[string]bool) bool {
	switch sel := sel.(type) {
	case SimpleSelector:
		return tbl[string(sel)]

	case CompoundSelector:
		for _, ssel := range sel {
			if tbl[string(ssel)] {
				return true
			}
		}
		return false

	case *FunctionSelector:
		return tbl[string(sel.sel)]

	default:
		return false
	}
}

func isStatementSelector(sel QuerySelector) bool {
	return selectorp(sel, statementSelectorp)
}

func isEnvelopeSelector(sel QuerySelector) bool {
	return selectorp(sel, envelopeSelectorp)
}

func isStatementCriteria(c QueryCriteria) bool {
	switch c := c.(type) {
	case *ValueCriteria:
		return c.sel == "id"

	case *TimeCriteria:
		return false

	case *CompoundCriteria:
		return isStatementCriteria(c.left) && isStatementCriteria(c.right)

	case *NegatedCriteria:
		return isStatementCriteria(c.e)

	default:
		return false
	}
}
<|endoftext|>


<commit_before>package sdm630

import (
	"fmt"
	"log"
	"sort"
	"sync"
	"time"

	. "github.com/gonium/gosdm630/internal/meters"
)

type MeasurementCache struct {
	in      QuerySnipChannel
	items   map[uint8]MeasurementCacheItem
	maxAge  time.Duration
	verbose bool
}

type MeasurementCacheItem struct {
	meter    *Meter
	readings *MeterReadings
}

func NewMeasurementCache(
	meters map[uint8]*Meter,
	inChannel QuerySnipChannel,
	scheduler *MeterScheduler,
	maxAge time.Duration,
	isVerbose bool,
) *MeasurementCache {
	items := make(map[uint8]MeasurementCacheItem)

	for _, meter := range meters {
		items[meter.DeviceId] = MeasurementCacheItem{
			meter:    meter,
			readings: NewMeterReadings(meter.DeviceId, maxAge),
		}
	}

	cache := &MeasurementCache{
		in:      inChannel,
		items:   items,
		maxAge:  maxAge,
		verbose: isVerbose,
	}

	scheduler.SetCache(cache)
	return cache
}

func (mc *MeasurementCache) Consume() {
	for {
		snip := <-mc.in
		devid := snip.DeviceId
		// Search corresponding meter
		if item, ok := mc.items[devid]; ok {
			// add the snip to the cache
			item.readings.AddSnip(snip)
			if mc.verbose {
				log.Printf("%s\r\n", item.readings.Current)
			}
		} else {
			log.Fatal("Snip for unknown meter received - this should not happen.")
		}
	}
}

func (mc *MeasurementCache) Purge(deviceId byte) error {
	if item, ok := mc.items[deviceId]; ok {
		item.readings.Purge(deviceId)
		return nil
	}

	return fmt.Errorf("No device with id %d available.", deviceId)
}

func (mc *MeasurementCache) GetSortedIDs() []byte {
	var keys ByteSlice
	for k, _ := range mc.items {
		keys = append(keys, k)
	}
	sort.Sort(keys)
	return keys
}

func (mc *MeasurementCache) GetCurrent(deviceId byte) (*Readings, error) {
	if item, ok := mc.items[deviceId]; ok {
		if item.meter.GetState() == AVAILABLE {
			return &item.readings.Current, nil
		} else {
			return nil, fmt.Errorf("Meter %d is not available.", deviceId)
		}
	} else {
		return nil, fmt.Errorf("No device with id %d available.", deviceId)
	}
}

func average(readings ReadingSlice) (*Readings, error) {
	var avg *Readings
	var err error

	for idx, r := range readings {
		if idx == 0 {
			// This is the first element - initialize our accumulator
			avg = &r
		} else {
			avg, err = r.add(avg)
			if err != nil {
				return nil, err
			}
		}
	}

	res := avg.divide(float64(len(readings)))
	return res, nil
}

func (mc *MeasurementCache) GetMinuteAvg(deviceId byte) (*Readings, error) {
	if item, ok := mc.items[deviceId]; ok {
		if item.meter.GetState() == AVAILABLE {
			measurements := item.readings.Historic
			lastminute := measurements.NotOlderThan(time.Now().Add(-1 * time.Minute))

			res, err := average(lastminute)
			if err != nil {
				return nil, err
			}

			if mc.verbose {
				log.Printf("Averaging over %d measurements:\r\n%s\r\n",
					len(measurements), res.String())
			}
			return res, nil
		}
		return nil, fmt.Errorf("Meter %d is not available.", deviceId)
	} else {
		return nil, fmt.Errorf("No device with id %d available.", deviceId)
	}
}

// ByteSlice attaches the methods of sort.Interface to []byte, sorting in increasing order.
type ByteSlice []byte

func (s ByteSlice) Len() int           { return len(s) }
func (s ByteSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s ByteSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

type MeterReadings struct {
	Historic ReadingSlice
	Current  Readings
	mux      sync.Mutex
}

func NewMeterReadings(devid uint8, maxAge time.Duration) *MeterReadings {
	res := &MeterReadings{
		Historic: ReadingSlice{},
		Current: Readings{
			UniqueId: fmt.Sprintf(UniqueIdFormat, devid),
			DeviceId: devid,
		},
	}
	go func(mr *MeterReadings) {
		for {
			time.Sleep(maxAge)
			mr.mux.Lock()
			mr.Historic = mr.Historic.NotOlderThan(time.Now().Add(-1 * maxAge))
			mr.mux.Unlock()
		}
	}(res)
	return res
}

func (mr *MeterReadings) Purge(devid uint8) {
	mr.mux.Lock()
	defer mr.mux.Unlock()

	mr.Historic = ReadingSlice{}
	mr.Current = Readings{
		UniqueId: fmt.Sprintf(UniqueIdFormat, devid),
		DeviceId: devid,
	}
}

func (mr *MeterReadings) AddSnip(snip QuerySnip) {
	mr.mux.Lock()
	defer mr.mux.Unlock()

	// 1. Merge the snip to the last values.
	reading := mr.Current
	reading.MergeSnip(snip)

	// 2. store it
	mr.Current = reading
	mr.Historic = append(mr.Historic, reading)
}
<commit_msg>Embed MeasurementCache<commit_after>package sdm630

import (
	"fmt"
	"log"
	"sort"
	"sync"
	"time"

	. "github.com/gonium/gosdm630/internal/meters"
)

type MeasurementCache struct {
	in      QuerySnipChannel
	meters  map[uint8]MeasurementCacheItem
	maxAge  time.Duration
	verbose bool
}

type MeasurementCacheItem struct {
	*Meter
	*MeterReadings
}

func NewMeasurementCache(
	meters map[uint8]*Meter,
	inChannel QuerySnipChannel,
	scheduler *MeterScheduler,
	maxAge time.Duration,
	isVerbose bool,
) *MeasurementCache {
	items := make(map[uint8]MeasurementCacheItem)

	for _, meter := range meters {
		items[meter.DeviceId] = MeasurementCacheItem{
			meter,
			NewMeterReadings(meter.DeviceId, maxAge),
		}
	}

	cache := &MeasurementCache{
		in:      inChannel,
		meters:  items,
		maxAge:  maxAge,
		verbose: isVerbose,
	}

	scheduler.SetCache(cache)
	return cache
}

func (mc *MeasurementCache) Consume() {
	for {
		snip := <-mc.in
		devid := snip.DeviceId
		// Search corresponding meter
		if meter, ok := mc.meters[devid]; ok {
			// add the snip to the cache
			meter.AddSnip(snip)
			if mc.verbose {
				log.Printf("%s\r\n", meter.Current)
			}
		} else {
			log.Fatal("Snip for unknown meter received - this should not happen.")
		}
	}
}

// Purge removes accumulated data for specified device
func (mc *MeasurementCache) Purge(deviceId byte) error {
	if meter, ok := mc.meters[deviceId]; ok {
		meter.Purge(deviceId)
		return nil
	}

	return fmt.Errorf("No device with id %d available.", deviceId)
}

func (mc *MeasurementCache) GetSortedIDs() []byte {
	var keys ByteSlice
	for k, _ := range mc.meters {
		keys = append(keys, k)
	}
	sort.Sort(keys)
	return keys
}

func (mc *MeasurementCache) GetCurrent(deviceId byte) (*Readings, error) {
	if meter, ok := mc.meters[deviceId]; ok {
		if meter.GetState() == AVAILABLE {
			return &meter.Current, nil
		} else {
			return nil, fmt.Errorf("Meter %d is not available.", deviceId)
		}
	} else {
		return nil, fmt.Errorf("No device with id %d available.", deviceId)
	}
}

func average(readings ReadingSlice) (*Readings, error) {
	var avg *Readings
	var err error

	for idx, r := range readings {
		if idx == 0 {
			// This is the first element - initialize our accumulator
			avg = &r
		} else {
			avg, err = r.add(avg)
			if err != nil {
				return nil, err
			}
		}
	}

	res := avg.divide(float64(len(readings)))
	return res, nil
}

func (mc *MeasurementCache) GetMinuteAvg(deviceId byte) (*Readings, error) {
	if meter, ok := mc.meters[deviceId]; ok {
		if meter.GetState() == AVAILABLE {
			measurements := meter.Historic
			lastminute := measurements.NotOlderThan(time.Now().Add(-1 * time.Minute))

			res, err := average(lastminute)
			if err != nil {
				return nil, err
			}

			if mc.verbose {
				log.Printf("Averaging over %d measurements:\r\n%s\r\n",
					len(measurements), res.String())
			}
			return res, nil
		}
		return nil, fmt.Errorf("Meter %d is not available.", deviceId)
	} else {
		return nil, fmt.Errorf("No device with id %d available.", deviceId)
	}
}

// ByteSlice attaches the methods of sort.Interface to []byte, sorting in increasing order.
type ByteSlice []byte

func (s ByteSlice) Len() int           { return len(s) }
func (s ByteSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s ByteSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

type MeterReadings struct {
	Historic ReadingSlice
	Current  Readings
	mux      sync.Mutex
}

func NewMeterReadings(devid uint8, maxAge time.Duration) *MeterReadings {
	res := &MeterReadings{
		Historic: ReadingSlice{},
		Current: Readings{
			UniqueId: fmt.Sprintf(UniqueIdFormat, devid),
			DeviceId: devid,
		},
	}
	go func(mr *MeterReadings) {
		for {
			time.Sleep(maxAge)
			mr.mux.Lock()
			mr.Historic = mr.Historic.NotOlderThan(time.Now().Add(-1 * maxAge))
			mr.mux.Unlock()
		}
	}(res)
	return res
}

func (mr *MeterReadings) Purge(devid uint8) {
	mr.mux.Lock()
	defer mr.mux.Unlock()

	mr.Historic = ReadingSlice{}
	mr.Current = Readings{
		UniqueId: fmt.Sprintf(UniqueIdFormat, devid),
		DeviceId: devid,
	}
}

func (mr *MeterReadings) AddSnip(snip QuerySnip) {
	mr.mux.Lock()
	defer mr.mux.Unlock()

	// 1. Merge the snip to the last values.
	reading := mr.Current
	reading.MergeSnip(snip)

	// 2. store it
	mr.Current = reading
	mr.Historic = append(mr.Historic, reading)
}
<|endoftext|>


<commit_before>package uic

import (
	"time"
)

type User struct {
	Id      int64     `json:"id"`
	Name    string    `json:"name"`
	Cnname  string    `json:"cnname"`
	Passwd  string    `json:"-"`
	Email   string    `json:"email"`
	Phone   string    `json:"phone"`
	IM      string    `json:"im" orm:"column(im)"`
	QQ      string    `json:"qq" orm:"column(qq)"`
	Role    int       `json:"role"`
	Created time.Time `orm:"auto_now_add;type(datetime)"`
}

type Team struct {
	Id      int64     `json:"id"`
	Name    string    `json:"name"`
	Resume  string    `json:"resume"`
	Creator int64     `json:"creator"`
	Created time.Time `orm:"auto_now_add;type(datetime)"`
}

type RelTeamUser struct {
	Id  int64
	Tid int64
	Uid int64
}

type Session struct {
	Id      int64
	Uid     int64
	Sig     string
	Expired int
}
<commit_msg>Fix runtime error.<commit_after>package uic

import (
	"time"
)

type User struct {
	Id      int64     `json:"id"`
	Name    string    `json:"name"`
	Cnname  string    `json:"cnname"`
	Passwd  string    `json:"-"`
	Email   string    `json:"email"`
	Phone   string    `json:"phone"`
	IM      string    `json:"im" orm:"column(im)"`
	QQ      string    `json:"qq" orm:"column(qq)"`
	Role    int       `json:"role"`
	Created time.Time `json:"-" orm:"-"`
}

type Team struct {
	Id      int64     `json:"id"`
	Name    string    `json:"name"`
	Resume  string    `json:"resume"`
	Creator int64     `json:"creator"`
	Created time.Time `json:"-" orm:"-"`
}

type RelTeamUser struct {
	Id  int64
	Tid int64
	Uid int64
}

type Session struct {
	Id      int64
	Uid     int64
	Sig     string
	Expired int
}
<|endoftext|>


<commit_before>package models

import (
	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"

	u "github.com/eirka/eirka-get/utils"
)

// DirectoryModel holds the parameters from the request and also the key for the cache
type DirectoryModel struct {
	Ib     uint
	Result DirectoryType
}

// IndexType is the top level of the JSON response
type DirectoryType struct {
	Body []Directory `json:"directory"`
}

// Thread directory
type Directory struct {
	Id     uint   `json:"id"`
	Title  string `json:"title"`
	Closed bool   `json:"closed"`
	Sticky bool   `json:"sticky"`
	Posts  uint   `json:"postcount"`
	Pages  uint   `json:"pages"`
	Last   string `json:"last_post"`
	Images uint   `json:"images"`
}

// Get will gather the information from the database and return it as JSON serialized data
func (i *DirectoryModel) Get() (err error) {

	// Initialize response header
	response := DirectoryType{}

	// Get Database handle
	dbase, err := db.GetDb()
	if err != nil {
		return
	}

	rows, err := dbase.Query(`SELECT threads.thread_id,thread_title,thread_closed,thread_sticky,count(posts.post_id),count(image_id),thread_last_post
	FROM threads
	LEFT JOIN posts on threads.thread_id = posts.thread_id
	LEFT JOIN images on images.post_id = posts.post_id
	WHERE ib_id = ? AND thread_deleted != 1 AND post_deleted != 1
	GROUP BY threads.thread_id
	ORDER BY thread_sticky = 1 DESC, thread_last_post DESC`, i.Ib)
	if err != nil {
		return
	}
	defer rows.Close()

	threads := []Directory{}
	for rows.Next() {
		thread := Directory{}
		err := rows.Scan(&thread.Id, &thread.Title, &thread.Closed, &thread.Sticky, &thread.Posts, &thread.Images, &thread.Last)
		if err != nil {
			return err
		}

		// Get the number of pages in the thread
		postpages := u.PagedResponse{}
		postpages.Total = thread.Posts
		postpages.CurrentPage = 1
		postpages.PerPage = config.Settings.Limits.PostsPerPage
		postpages.Get()

		// set pages
		thread.Pages = postpages.Pages

		threads = append(threads, thread)
	}
	err = rows.Err()
	if err != nil {
		return
	}

	// Add pagedresponse to the response struct
	response.Body = threads

	// This is the data we will serialize
	i.Result = response

	return

}
<commit_msg>directory and tags page shouldnt return 404<commit_after>package models

import (
	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"

	u "github.com/eirka/eirka-get/utils"
)

// DirectoryModel holds the parameters from the request and also the key for the cache
type DirectoryModel struct {
	Ib     uint
	Result DirectoryType
}

// IndexType is the top level of the JSON response
type DirectoryType struct {
	Body []Directory `json:"directory"`
}

// Thread directory
type Directory struct {
	Id     uint   `json:"id"`
	Title  string `json:"title"`
	Closed bool   `json:"closed"`
	Sticky bool   `json:"sticky"`
	Posts  uint   `json:"postcount"`
	Pages  uint   `json:"pages"`
	Last   string `json:"last_post"`
	Images uint   `json:"images"`
}

// Get will gather the information from the database and return it as JSON serialized data
func (i *DirectoryModel) Get() (err error) {

	// Initialize response header
	response := DirectoryType{}

	// Get Database handle
	dbase, err := db.GetDb()
	if err != nil {
		return
	}

	rows, err := dbase.Query(`SELECT threads.thread_id,thread_title,thread_closed,thread_sticky,count(posts.post_id),count(image_id),thread_last_post
	FROM threads
	LEFT JOIN posts on threads.thread_id = posts.thread_id
	LEFT JOIN images on images.post_id = posts.post_id
	WHERE ib_id = ? AND thread_deleted != 1 AND post_deleted != 1
	GROUP BY threads.thread_id
	ORDER BY thread_sticky = 1 DESC, thread_last_post DESC`, i.Ib)
	if err != nil {
		return
	}
	defer rows.Close()

	threads := []Directory{}
	for rows.Next() {
		thread := Directory{}
		err := rows.Scan(&thread.Id, &thread.Title, &thread.Closed, &thread.Sticky, &thread.Posts, &thread.Images, &thread.Last)
		if err != nil {
			return err
		}

		// Get the number of pages in the thread
		postpages := u.PagedResponse{}
		postpages.Total = thread.Posts
		postpages.CurrentPage = 1
		postpages.PerPage = config.Settings.Limits.PostsPerPage
		postpages.Get()

		// set pages
		thread.Pages = postpages.Pages

		threads = append(threads, thread)
	}
	err = rows.Err()
	if err != nil {
		return
	}

	// Add pagedresponse to the response struct
	response.Body = threads

	// This is the data we will serialize
	i.Result = response

	return

}
<|endoftext|>


<commit_before>package net

import (
	"testing"

	"github.com/v2ray/v2ray-core/testing/unit"
)

func TestIPv4Address(t *testing.T) {
	assert := unit.Assert(t)

	ip := []byte{byte(1), byte(2), byte(3), byte(4)}
	port := uint16(80)
	addr := IPAddress(ip, port)

	assert.Byte(addr.Type).Equals(AddrTypeIP)
	assert.Bool(addr.IsIPv4()).IsTrue()
	assert.Bytes(addr.IP).Equals(ip)
	assert.Uint16(addr.Port).Equals(port)
}

func TestIPv6Address(t *testing.T) {
	assert := unit.Assert(t)

	ip := []byte{
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
	}
	port := uint16(443)
	addr := IPAddress(ip, port)

	assert.Byte(addr.Type).Equals(AddrTypeIP)
	assert.Bool(addr.IsIPv6()).IsTrue()
	assert.Bytes(addr.IP).Equals(ip)
	assert.Uint16(addr.Port).Equals(port)
}

func TestDomainAddress(t *testing.T) {
	assert := unit.Assert(t)

	domain := "v2ray.com"
	port := uint16(443)
	addr := DomainAddress(domain, port)

	assert.Byte(addr.Type).Equals(AddrTypeDomain)
	assert.Bool(addr.IsDomain()).IsTrue()
	assert.String(addr.Domain).Equals(domain)
	assert.Uint16(addr.Port).Equals(port)
}
<commit_msg>more tests on address<commit_after>package net

import (
	"testing"

	"github.com/v2ray/v2ray-core/testing/unit"
)

func TestIPv4Address(t *testing.T) {
	assert := unit.Assert(t)

	ip := []byte{byte(1), byte(2), byte(3), byte(4)}
	port := uint16(80)
	addr := IPAddress(ip, port)

	assert.Byte(addr.Type).Equals(AddrTypeIP)
	assert.Bool(addr.IsIPv4()).IsTrue()
	assert.Bytes(addr.IP).Equals(ip)
	assert.Uint16(addr.Port).Equals(port)
	assert.String(addr.String()).Equals("1.2.3.4:80")
}

func TestIPv6Address(t *testing.T) {
	assert := unit.Assert(t)

	ip := []byte{
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
		byte(1), byte(2), byte(3), byte(4),
	}
	port := uint16(443)
	addr := IPAddress(ip, port)

	assert.Byte(addr.Type).Equals(AddrTypeIP)
	assert.Bool(addr.IsIPv6()).IsTrue()
	assert.Bytes(addr.IP).Equals(ip)
	assert.Uint16(addr.Port).Equals(port)
	assert.String(addr.String()).Equals("[102:304:102:304:102:304:102:304]:443")
}

func TestDomainAddress(t *testing.T) {
	assert := unit.Assert(t)

	domain := "v2ray.com"
	port := uint16(443)
	addr := DomainAddress(domain, port)

	assert.Byte(addr.Type).Equals(AddrTypeDomain)
	assert.Bool(addr.IsDomain()).IsTrue()
	assert.String(addr.Domain).Equals(domain)
	assert.Uint16(addr.Port).Equals(port)
	assert.String(addr.String()).Equals("v2ray.com:443")
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

// +build js,wasm

package http

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"strconv"
	"syscall/js"
)

// RoundTrip implements the RoundTripper interface using the WHATWG Fetch API.
func (*Transport) RoundTrip(req *Request) (*Response, error) {
	if useFakeNetwork(req) {
		return t.roundTrip(req)
	}
	headers := js.Global.Get("Headers").New()
	for key, values := range req.Header {
		for _, value := range values {
			headers.Call("append", key, value)
		}
	}

	ac := js.Global.Get("AbortController")
	if ac != js.Undefined {
		// Some browsers that support WASM don't necessarily support
		// the AbortController. See
		// https://developer.mozilla.org/en-US/docs/Web/API/AbortController#Browser_compatibility.
		ac = ac.New()
	}

	opt := js.Global.Get("Object").New()
	// See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
	// for options available.
	opt.Set("headers", headers)
	opt.Set("method", req.Method)
	opt.Set("credentials", "same-origin")
	if ac != js.Undefined {
		opt.Set("signal", ac.Get("signal"))
	}

	if req.Body != nil {
		// TODO(johanbrandhorst): Stream request body when possible.
		// See https://bugs.chromium.org/p/chromium/issues/detail?id=688906 for Blink issue.
		// See https://bugzilla.mozilla.org/show_bug.cgi?id=1387483 for Firefox issue.
		// See https://github.com/web-platform-tests/wpt/issues/7693 for WHATWG tests issue.
		// See https://developer.mozilla.org/en-US/docs/Web/API/Streams_API for more details on the Streams API
		// and browser support.
		body, err := ioutil.ReadAll(req.Body)
		if err != nil {
			req.Body.Close() // RoundTrip must always close the body, including on errors.
			return nil, err
		}
		req.Body.Close()
		opt.Set("body", body)
	}
	respPromise := js.Global.Call("fetch", req.URL.String(), opt)
	var (
		respCh = make(chan *Response, 1)
		errCh  = make(chan error, 1)
	)
	success := js.NewCallback(func(args []js.Value) {
		result := args[0]
		header := Header{}
		// https://developer.mozilla.org/en-US/docs/Web/API/Headers/entries
		headersIt := result.Get("headers").Call("entries")
		for {
			n := headersIt.Call("next")
			if n.Get("done").Bool() {
				break
			}
			pair := n.Get("value")
			key, value := pair.Index(0).String(), pair.Index(1).String()
			ck := CanonicalHeaderKey(key)
			header[ck] = append(header[ck], value)
		}

		contentLength := int64(0)
		if cl, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64); err == nil {
			contentLength = cl
		}

		b := result.Get("body")
		var body io.ReadCloser
		if b != js.Undefined {
			body = &streamReader{stream: b.Call("getReader")}
		} else {
			// Fall back to using ArrayBuffer
			// https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer
			body = &arrayReader{arrayPromise: result.Call("arrayBuffer")}
		}

		select {
		case respCh <- &Response{
			Status:        result.Get("status").String() + " " + StatusText(result.Get("status").Int()),
			StatusCode:    result.Get("status").Int(),
			Header:        header,
			ContentLength: contentLength,
			Body:          body,
			Request:       req,
		}:
		case <-req.Context().Done():
		}
	})
	defer success.Close()
	failure := js.NewCallback(func(args []js.Value) {
		err := fmt.Errorf("net/http: fetch() failed: %s", args[0].String())
		select {
		case errCh <- err:
		case <-req.Context().Done():
		}
	})
	defer failure.Close()
	respPromise.Call("then", success, failure)
	select {
	case <-req.Context().Done():
		if ac != js.Undefined {
			// Abort the Fetch request
			ac.Call("abort")
		}
		return nil, req.Context().Err()
	case resp := <-respCh:
		return resp, nil
	case err := <-errCh:
		return nil, err
	}
}

// useFakeNetwork is used to determine whether the request is made
// by a test and should be made to use the fake in-memory network.
func useFakeNetwork(req *Request) bool {
	host, _, err := net.SplitHostPort(req.Host)
	if err != nil {
		host = req.Host
	}
	if ip := net.ParseIP(host); ip != nil {
		return ip.IsLoopback(ip)
	}
	return host == "localhost"
}

// streamReader implements an io.ReadCloser wrapper for ReadableStream.
// See https://fetch.spec.whatwg.org/#readablestream for more information.
type streamReader struct {
	pending []byte
	stream  js.Value
	err     error // sticky read error
}

func (r *streamReader) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	if len(r.pending) == 0 {
		var (
			bCh   = make(chan []byte, 1)
			errCh = make(chan error, 1)
		)
		success := js.NewCallback(func(args []js.Value) {
			result := args[0]
			if result.Get("done").Bool() {
				errCh <- io.EOF
				return
			}
			value := make([]byte, result.Get("value").Get("byteLength").Int())
			js.ValueOf(value).Call("set", result.Get("value"))
			bCh <- value
		})
		defer success.Close()
		failure := js.NewCallback(func(args []js.Value) {
			// Assumes it's a TypeError. See
			// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
			// for more information on this type. See
			// https://streams.spec.whatwg.org/#byob-reader-read for the spec on
			// the read method.
			errCh <- errors.New(args[0].Get("message").String())
		})
		defer failure.Close()
		r.stream.Call("read").Call("then", success, failure)
		select {
		case b := <-bCh:
			r.pending = b
		case err := <-errCh:
			r.err = err
			return 0, err
		}
	}
	n = copy(p, r.pending)
	r.pending = r.pending[n:]
	return n, nil
}

func (r *streamReader) Close() error {
	// This ignores any error returned from cancel method. So far, I did not encounter any concrete
	// situation where reporting the error is meaningful. Most users ignore error from resp.Body.Close().
	// If there's a need to report error here, it can be implemented and tested when that need comes up.
	r.stream.Call("cancel")
	if r.err == nil {
		r.err = errClosed
	}
	return nil
}

// arrayReader implements an io.ReadCloser wrapper for ArrayBuffer.
// https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer.
type arrayReader struct {
	arrayPromise js.Value
	pending      []byte
	read         bool
	err          error // sticky read error
}

func (r *arrayReader) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	if !r.read {
		r.read = true
		var (
			bCh   = make(chan []byte, 1)
			errCh = make(chan error, 1)
		)
		success := js.NewCallback(func(args []js.Value) {
			// Wrap the input ArrayBuffer with a Uint8Array
			uint8arrayWrapper := js.Global.Get("Uint8Array").New(args[0])
			value := make([]byte, uint8arrayWrapper.Get("byteLength").Int())
			js.ValueOf(value).Call("set", uint8arrayWrapper)
			bCh <- value
		})
		defer success.Close()
		failure := js.NewCallback(func(args []js.Value) {
			// Assumes it's a TypeError. See
			// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
			// for more information on this type.
			// See https://fetch.spec.whatwg.org/#concept-body-consume-body for reasons this might error.
			errCh <- errors.New(args[0].Get("message").String())
		})
		defer failure.Close()
		r.arrayPromise.Call("then", success, failure)
		select {
		case b := <-bCh:
			r.pending = b
		case err := <-errCh:
			return 0, err
		}
	}
	if len(r.pending) == 0 {
		return 0, io.EOF
	}
	n = copy(p, r.pending)
	r.pending = r.pending[n:]
	return n, nil
}

func (r *arrayReader) Close() error {
	if r.err == nil {
		r.err = errClosed
	}
	return nil
}
<commit_msg>net/http: use fake Transport network when running in Node<commit_after>// Copyright 2018 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.

// +build js,wasm

package http

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strconv"
	"syscall/js"
)

// RoundTrip implements the RoundTripper interface using the WHATWG Fetch API.
func (*Transport) RoundTrip(req *Request) (*Response, error) {
	if useFakeNetwork() {
		return t.roundTrip(req)
	}
	headers := js.Global.Get("Headers").New()
	for key, values := range req.Header {
		for _, value := range values {
			headers.Call("append", key, value)
		}
	}

	ac := js.Global.Get("AbortController")
	if ac != js.Undefined {
		// Some browsers that support WASM don't necessarily support
		// the AbortController. See
		// https://developer.mozilla.org/en-US/docs/Web/API/AbortController#Browser_compatibility.
		ac = ac.New()
	}

	opt := js.Global.Get("Object").New()
	// See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
	// for options available.
	opt.Set("headers", headers)
	opt.Set("method", req.Method)
	opt.Set("credentials", "same-origin")
	if ac != js.Undefined {
		opt.Set("signal", ac.Get("signal"))
	}

	if req.Body != nil {
		// TODO(johanbrandhorst): Stream request body when possible.
		// See https://bugs.chromium.org/p/chromium/issues/detail?id=688906 for Blink issue.
		// See https://bugzilla.mozilla.org/show_bug.cgi?id=1387483 for Firefox issue.
		// See https://github.com/web-platform-tests/wpt/issues/7693 for WHATWG tests issue.
		// See https://developer.mozilla.org/en-US/docs/Web/API/Streams_API for more details on the Streams API
		// and browser support.
		body, err := ioutil.ReadAll(req.Body)
		if err != nil {
			req.Body.Close() // RoundTrip must always close the body, including on errors.
			return nil, err
		}
		req.Body.Close()
		opt.Set("body", body)
	}
	respPromise := js.Global.Call("fetch", req.URL.String(), opt)
	var (
		respCh = make(chan *Response, 1)
		errCh  = make(chan error, 1)
	)
	success := js.NewCallback(func(args []js.Value) {
		result := args[0]
		header := Header{}
		// https://developer.mozilla.org/en-US/docs/Web/API/Headers/entries
		headersIt := result.Get("headers").Call("entries")
		for {
			n := headersIt.Call("next")
			if n.Get("done").Bool() {
				break
			}
			pair := n.Get("value")
			key, value := pair.Index(0).String(), pair.Index(1).String()
			ck := CanonicalHeaderKey(key)
			header[ck] = append(header[ck], value)
		}

		contentLength := int64(0)
		if cl, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64); err == nil {
			contentLength = cl
		}

		b := result.Get("body")
		var body io.ReadCloser
		if b != js.Undefined {
			body = &streamReader{stream: b.Call("getReader")}
		} else {
			// Fall back to using ArrayBuffer
			// https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer
			body = &arrayReader{arrayPromise: result.Call("arrayBuffer")}
		}

		select {
		case respCh <- &Response{
			Status:        result.Get("status").String() + " " + StatusText(result.Get("status").Int()),
			StatusCode:    result.Get("status").Int(),
			Header:        header,
			ContentLength: contentLength,
			Body:          body,
			Request:       req,
		}:
		case <-req.Context().Done():
		}
	})
	defer success.Close()
	failure := js.NewCallback(func(args []js.Value) {
		err := fmt.Errorf("net/http: fetch() failed: %s", args[0].String())
		select {
		case errCh <- err:
		case <-req.Context().Done():
		}
	})
	defer failure.Close()
	respPromise.Call("then", success, failure)
	select {
	case <-req.Context().Done():
		if ac != js.Undefined {
			// Abort the Fetch request
			ac.Call("abort")
		}
		return nil, req.Context().Err()
	case resp := <-respCh:
		return resp, nil
	case err := <-errCh:
		return nil, err
	}
}

// useFakeNetwork is used to determine whether the request is made
// by a test and should be made to use the fake in-memory network.
func useFakeNetwork() bool {
	return len(os.Args) > 0 && path.Base(os.Args[0]) == "node"
}

// streamReader implements an io.ReadCloser wrapper for ReadableStream.
// See https://fetch.spec.whatwg.org/#readablestream for more information.
type streamReader struct {
	pending []byte
	stream  js.Value
	err     error // sticky read error
}

func (r *streamReader) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	if len(r.pending) == 0 {
		var (
			bCh   = make(chan []byte, 1)
			errCh = make(chan error, 1)
		)
		success := js.NewCallback(func(args []js.Value) {
			result := args[0]
			if result.Get("done").Bool() {
				errCh <- io.EOF
				return
			}
			value := make([]byte, result.Get("value").Get("byteLength").Int())
			js.ValueOf(value).Call("set", result.Get("value"))
			bCh <- value
		})
		defer success.Close()
		failure := js.NewCallback(func(args []js.Value) {
			// Assumes it's a TypeError. See
			// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
			// for more information on this type. See
			// https://streams.spec.whatwg.org/#byob-reader-read for the spec on
			// the read method.
			errCh <- errors.New(args[0].Get("message").String())
		})
		defer failure.Close()
		r.stream.Call("read").Call("then", success, failure)
		select {
		case b := <-bCh:
			r.pending = b
		case err := <-errCh:
			r.err = err
			return 0, err
		}
	}
	n = copy(p, r.pending)
	r.pending = r.pending[n:]
	return n, nil
}

func (r *streamReader) Close() error {
	// This ignores any error returned from cancel method. So far, I did not encounter any concrete
	// situation where reporting the error is meaningful. Most users ignore error from resp.Body.Close().
	// If there's a need to report error here, it can be implemented and tested when that need comes up.
	r.stream.Call("cancel")
	if r.err == nil {
		r.err = errClosed
	}
	return nil
}

// arrayReader implements an io.ReadCloser wrapper for ArrayBuffer.
// https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer.
type arrayReader struct {
	arrayPromise js.Value
	pending      []byte
	read         bool
	err          error // sticky read error
}

func (r *arrayReader) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	if !r.read {
		r.read = true
		var (
			bCh   = make(chan []byte, 1)
			errCh = make(chan error, 1)
		)
		success := js.NewCallback(func(args []js.Value) {
			// Wrap the input ArrayBuffer with a Uint8Array
			uint8arrayWrapper := js.Global.Get("Uint8Array").New(args[0])
			value := make([]byte, uint8arrayWrapper.Get("byteLength").Int())
			js.ValueOf(value).Call("set", uint8arrayWrapper)
			bCh <- value
		})
		defer success.Close()
		failure := js.NewCallback(func(args []js.Value) {
			// Assumes it's a TypeError. See
			// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
			// for more information on this type.
			// See https://fetch.spec.whatwg.org/#concept-body-consume-body for reasons this might error.
			errCh <- errors.New(args[0].Get("message").String())
		})
		defer failure.Close()
		r.arrayPromise.Call("then", success, failure)
		select {
		case b := <-bCh:
			r.pending = b
		case err := <-errCh:
			return 0, err
		}
	}
	if len(r.pending) == 0 {
		return 0, io.EOF
	}
	n = copy(p, r.pending)
	r.pending = r.pending[n:]
	return n, nil
}

func (r *arrayReader) Close() error {
	if r.err == nil {
		r.err = errClosed
	}
	return nil
}
<|endoftext|>


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

package commands

import (
	"nvim-go/nvim"
	"nvim-go/nvim/buffer"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
)

func init() {
	plugin.HandleCommand("GoByteOffset",
		&plugin.CommandOptions{Range: "%", Eval: "expand('%:p')"},
		cmdByteOffset)
}

func cmdByteOffset(v *vim.Vim) error {
	offset, _ := buffer.ByteOffset(v, 0, 0)
	return nvim.Echomsg(v, offset)
}
<commit_msg>util: Add list of Buffer, Window, Tabpage debug command<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"nvim-go/nvim"
	"nvim-go/nvim/buffer"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
)

func init() {
	plugin.HandleCommand("GoByteOffset",
		&plugin.CommandOptions{Range: "%", Eval: "expand('%:p')"},
		cmdByteOffset)
	plugin.HandleCommand("GoBuffers", &plugin.CommandOptions{}, cmdBuffers)
	plugin.HandleCommand("GoWindows", &plugin.CommandOptions{}, cmdWindows)
	plugin.HandleCommand("GoTabpages", &plugin.CommandOptions{}, cmdTabpagas)
}

func cmdBuffers(v *vim.Vim) error {
	bufs, _ := v.Buffers()
	var b []string
	for _, buf := range bufs {
		b = append(b, buf.String())
	}
	return nvim.Echomsg(v, "Buffers:", b)
}

func cmdWindows(v *vim.Vim) error {
	wins, _ := v.Windows()
	var w []string
	for _, win := range wins {
		w = append(w, win.String())
	}
	return nvim.Echomsg(v, "Windows:", w)
}

func cmdTabpagas(v *vim.Vim) error {
	tabs, _ := v.Tabpages()
	var t []string
	for _, tab := range tabs {
		t = append(t, tab.String())
	}
	return nvim.Echomsg(v, "Tabpages:", t)
}

func cmdByteOffset(v *vim.Vim) error {
	offset, _ := buffer.ByteOffset(v, 0, 0)
	return nvim.Echomsg(v, offset)
}
<|endoftext|>


<commit_before>package variables

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/hashicorp/hcl"
)

// ParseInput parses a manually inputed variable to a richer value.
//
// This will turn raw input into rich types such as `[]` to a real list or
// `{}` to a real map. This function should be used to parse any manual untyped
// input for variables in order to provide a consistent experience.
func ParseInput(value string) (interface{}, error) {
	trimmed := strings.TrimSpace(value)

	// If the value is a simple number, don't parse it as hcl because the
	// variable type may actually be a string, and HCL will convert it to the
	// numberic value. We could check this in the validation later, but the
	// conversion may alter the string value.
	if _, err := strconv.ParseInt(trimmed, 10, 64); err == nil {
		return value, nil
	}
	if _, err := strconv.ParseFloat(trimmed, 64); err == nil {
		return value, nil
	}

	// HCL will also parse hex as a number
	if strings.HasPrefix(trimmed, "0x") {
		if _, err := strconv.ParseInt(trimmed[2:], 16, 64); err == nil {
			return value, nil
		}
	}

	// If the value is a boolean value, also convert it to a simple string
	// since Terraform core doesn't accept primitives as anything other
	// than string for now.
	if _, err := strconv.ParseBool(trimmed); err == nil {
		return value, nil
	}

	parsed, err := hcl.Parse(fmt.Sprintf("foo=%s", trimmed))
	if err != nil {
		// If it didn't parse as HCL, we check if it doesn't match our
		// whitelist of TF-accepted HCL types for inputs. If not, then
		// we let it through as a raw string.
		if !varFlagHCLRe.MatchString(trimmed) {
			return value, nil
		}

		// This covers flags of the form `foo=bar` which is not valid HCL
		// At this point, probablyName is actually the name, and the remainder
		// of the expression after the equals sign is the value.
		if regexp.MustCompile(`Unknown token: \d+:\d+ IDENT`).Match([]byte(err.Error())) {
			return value, nil
		}

		return nil, fmt.Errorf(
			"Cannot parse value for variable %s (%q) as valid HCL: %s",
			value, err)
	}

	var decoded map[string]interface{}
	if hcl.DecodeObject(&decoded, parsed); err != nil {
		return nil, fmt.Errorf(
			"Cannot parse value for variable %s (%q) as valid HCL: %s",
			value, err)
	}

	// Cover cases such as key=
	if len(decoded) == 0 {
		return "", nil
	}

	if len(decoded) > 1 {
		return nil, fmt.Errorf(
			"Cannot parse value for variable %s (%q) as valid HCL. "+
				"Only one value may be specified.",
			value)
	}

	err = flattenMultiMaps(decoded)
	if err != nil {
		return "", err
	}

	return decoded["foo"], nil
}

var (
	// This regular expression is how we check if a value for a variable
	// matches what we'd expect a rich HCL value to be. For example: {
	// definitely signals a map. If a value DOESN'T match this, we return
	// it as a raw string.
	varFlagHCLRe = regexp.MustCompile(`^["\[\{]`)
)

// Variables don't support any type that can be configured via multiple
// declarations of the same HCL map, so any instances of
// []map[string]interface{} are either a single map that can be flattened, or
// are invalid config.
func flattenMultiMaps(m map[string]interface{}) error {
	for k, v := range m {
		switch v := v.(type) {
		case []map[string]interface{}:
			switch {
			case len(v) > 1:
				return fmt.Errorf("multiple map declarations not supported for variables")
			case len(v) == 1:
				m[k] = v[0]
			}
		}
	}
	return nil
}
<commit_msg>helper/variables: address go vet<commit_after>package variables

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/hashicorp/hcl"
)

// ParseInput parses a manually inputed variable to a richer value.
//
// This will turn raw input into rich types such as `[]` to a real list or
// `{}` to a real map. This function should be used to parse any manual untyped
// input for variables in order to provide a consistent experience.
func ParseInput(value string) (interface{}, error) {
	trimmed := strings.TrimSpace(value)

	// If the value is a simple number, don't parse it as hcl because the
	// variable type may actually be a string, and HCL will convert it to the
	// numberic value. We could check this in the validation later, but the
	// conversion may alter the string value.
	if _, err := strconv.ParseInt(trimmed, 10, 64); err == nil {
		return value, nil
	}
	if _, err := strconv.ParseFloat(trimmed, 64); err == nil {
		return value, nil
	}

	// HCL will also parse hex as a number
	if strings.HasPrefix(trimmed, "0x") {
		if _, err := strconv.ParseInt(trimmed[2:], 16, 64); err == nil {
			return value, nil
		}
	}

	// If the value is a boolean value, also convert it to a simple string
	// since Terraform core doesn't accept primitives as anything other
	// than string for now.
	if _, err := strconv.ParseBool(trimmed); err == nil {
		return value, nil
	}

	parsed, err := hcl.Parse(fmt.Sprintf("foo=%s", trimmed))
	if err != nil {
		// If it didn't parse as HCL, we check if it doesn't match our
		// whitelist of TF-accepted HCL types for inputs. If not, then
		// we let it through as a raw string.
		if !varFlagHCLRe.MatchString(trimmed) {
			return value, nil
		}

		// This covers flags of the form `foo=bar` which is not valid HCL
		// At this point, probablyName is actually the name, and the remainder
		// of the expression after the equals sign is the value.
		if regexp.MustCompile(`Unknown token: \d+:\d+ IDENT`).Match([]byte(err.Error())) {
			return value, nil
		}

		return nil, fmt.Errorf(
			"Cannot parse value for variable (%q) as valid HCL: %s",
			value, err)
	}

	var decoded map[string]interface{}
	if hcl.DecodeObject(&decoded, parsed); err != nil {
		return nil, fmt.Errorf(
			"Cannot parse value for variable (%q) as valid HCL: %s",
			value, err)
	}

	// Cover cases such as key=
	if len(decoded) == 0 {
		return "", nil
	}

	if len(decoded) > 1 {
		return nil, fmt.Errorf(
			"Cannot parse value for variable (%q) as valid HCL. "+
				"Only one value may be specified.",
			value)
	}

	err = flattenMultiMaps(decoded)
	if err != nil {
		return "", err
	}

	return decoded["foo"], nil
}

var (
	// This regular expression is how we check if a value for a variable
	// matches what we'd expect a rich HCL value to be. For example: {
	// definitely signals a map. If a value DOESN'T match this, we return
	// it as a raw string.
	varFlagHCLRe = regexp.MustCompile(`^["\[\{]`)
)

// Variables don't support any type that can be configured via multiple
// declarations of the same HCL map, so any instances of
// []map[string]interface{} are either a single map that can be flattened, or
// are invalid config.
func flattenMultiMaps(m map[string]interface{}) error {
	for k, v := range m {
		switch v := v.(type) {
		case []map[string]interface{}:
			switch {
			case len(v) > 1:
				return fmt.Errorf("multiple map declarations not supported for variables")
			case len(v) == 1:
				m[k] = v[0]
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package xlsx

import (
	"bytes"
	"encoding/xml"
	. "gopkg.in/check.v1"
)

type WorksheetSuite struct{}

var _ = Suite(&WorksheetSuite{})

// Test we can succesfully unmarshal the sheetN.xml files within and
// XLSX file into an xlsxWorksheet struct (and it's related children).
func (w *WorksheetSuite) TestUnmarshallWorksheet(c *C) {
	var sheetxml = bytes.NewBufferString(
		`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
                   xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
          <sheetPr filterMode="false">
            <pageSetUpPr fitToPage="false"/>
          </sheetPr>
          <dimension ref="A1:B2"/>
          <sheetViews>
            <sheetView colorId="64"
                       defaultGridColor="true"
                       rightToLeft="false"
                       showFormulas="false"
                       showGridLines="true"
                       showOutlineSymbols="true"
                       showRowColHeaders="true"
                       showZeros="true"
                       tabSelected="true"
                       topLeftCell="A1"
                       view="normal"
                       windowProtection="false"
                       workbookViewId="0"
                       zoomScale="100"
                       zoomScaleNormal="100"
                       zoomScalePageLayoutView="100">
              <selection activeCell="B2"
                         activeCellId="0"
                         pane="topLeft"
                         sqref="B2"/>
            </sheetView>
          </sheetViews>
          <sheetFormatPr defaultRowHeight="15">
          </sheetFormatPr>
          <cols>
            <col collapsed="false"
                 hidden="false"
                 max="1025"
                 min="1"
                 style="0"
                 width="10.5748987854251"/>
          </cols>
          <sheetData>
            <row collapsed="false"
                 customFormat="false"
                 customHeight="false"
                 hidden="false"
                 ht="14.9"
                 outlineLevel="0"
                 r="1">
              <c r="A1"
                 s="1"
                 t="s">
                <v>0</v>
              </c>
              <c r="B1"
                 s="0"
                 t="s">
                <v>1</v>
              </c>
            </row>
            <row collapsed="false"
                 customFormat="false"
                 customHeight="false"
                 hidden="false"
                 ht="14.9"
                 outlineLevel="0"
                 r="2">
              <c r="A2"
                 s="0"
                 t="s">
                <v>2</v>
              </c>
              <c r="B2"
                 s="2"
                 t="s">
                <v>3</v>
              </c>
            </row>
          </sheetData>
          <printOptions headings="false"
                        gridLines="false"
                        gridLinesSet="true"
                        horizontalCentered="false"
                        verticalCentered="false"/>
          <pageMargins left="0.7"
                       right="0.7"
                       top="0.7875"
                       bottom="0.7875"
                       header="0.511805555555555"
                       footer="0.511805555555555"/>
          <pageSetup blackAndWhite="false"
                     cellComments="none"
                     copies="1"
                     draft="false"
                     firstPageNumber="0"
                     fitToHeight="1"
                     fitToWidth="1"
                     horizontalDpi="300"
                     orientation="portrait"
                     pageOrder="downThenOver"
                     paperSize="9"
                     scale="100"
                     useFirstPageNumber="false"
                     usePrinterDefaults="false"
                     verticalDpi="300"/>
          <headerFooter differentFirst="false"
                        differentOddEven="false">
            <oddHeader>
            </oddHeader>
            <oddFooter>
            </oddFooter>
          </headerFooter>
        </worksheet>`)
	worksheet := new(xlsxWorksheet)
	err := xml.NewDecoder(sheetxml).Decode(worksheet)
	c.Assert(err, IsNil)
	c.Assert(worksheet.Dimension.Ref, Equals, "A1:B2")
	c.Assert(worksheet.SheetData.Row, HasLen, 2)
	row := worksheet.SheetData.Row[0]
	c.Assert(row.R, Equals, 1)
	c.Assert(row.C, HasLen, 2)
	cell := row.C[0]
	c.Assert(cell.R, Equals, "A1")
	c.Assert(cell.T, Equals, "s")
	c.Assert(cell.V, Equals, "0")
}
<commit_msg>Test parsing of default row height and column width<commit_after>package xlsx

import (
	"bytes"
	"encoding/xml"
	. "gopkg.in/check.v1"
)

type WorksheetSuite struct{}

var _ = Suite(&WorksheetSuite{})

// Test we can succesfully unmarshal the sheetN.xml files within and
// XLSX file into an xlsxWorksheet struct (and it's related children).
func (w *WorksheetSuite) TestUnmarshallWorksheet(c *C) {
	var sheetxml = bytes.NewBufferString(
		`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
                   xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
          <sheetPr filterMode="false">
            <pageSetUpPr fitToPage="false"/>
          </sheetPr>
          <dimension ref="A1:B2"/>
          <sheetViews>
            <sheetView colorId="64"
                       defaultGridColor="true"
                       rightToLeft="false"
                       showFormulas="false"
                       showGridLines="true"
                       showOutlineSymbols="true"
                       showRowColHeaders="true"
                       showZeros="true"
                       tabSelected="true"
                       topLeftCell="A1"
                       view="normal"
                       windowProtection="false"
                       workbookViewId="0"
                       zoomScale="100"
                       zoomScaleNormal="100"
                       zoomScalePageLayoutView="100">
              <selection activeCell="B2"
                         activeCellId="0"
                         pane="topLeft"
                         sqref="B2"/>
            </sheetView>
          </sheetViews>
          <sheetFormatPr defaultRowHeight="15" defaultColWidth="8">
          </sheetFormatPr>
          <cols>
            <col collapsed="false"
                 hidden="false"
                 max="1025"
                 min="1"
                 style="0"
                 width="10.5748987854251"/>
          </cols>
          <sheetData>
            <row collapsed="false"
                 customFormat="false"
                 customHeight="false"
                 hidden="false"
                 ht="14.9"
                 outlineLevel="0"
                 r="1">
              <c r="A1"
                 s="1"
                 t="s">
                <v>0</v>
              </c>
              <c r="B1"
                 s="0"
                 t="s">
                <v>1</v>
              </c>
            </row>
            <row collapsed="false"
                 customFormat="false"
                 customHeight="false"
                 hidden="false"
                 ht="14.9"
                 outlineLevel="0"
                 r="2">
              <c r="A2"
                 s="0"
                 t="s">
                <v>2</v>
              </c>
              <c r="B2"
                 s="2"
                 t="s">
                <v>3</v>
              </c>
            </row>
          </sheetData>
          <printOptions headings="false"
                        gridLines="false"
                        gridLinesSet="true"
                        horizontalCentered="false"
                        verticalCentered="false"/>
          <pageMargins left="0.7"
                       right="0.7"
                       top="0.7875"
                       bottom="0.7875"
                       header="0.511805555555555"
                       footer="0.511805555555555"/>
          <pageSetup blackAndWhite="false"
                     cellComments="none"
                     copies="1"
                     draft="false"
                     firstPageNumber="0"
                     fitToHeight="1"
                     fitToWidth="1"
                     horizontalDpi="300"
                     orientation="portrait"
                     pageOrder="downThenOver"
                     paperSize="9"
                     scale="100"
                     useFirstPageNumber="false"
                     usePrinterDefaults="false"
                     verticalDpi="300"/>
          <headerFooter differentFirst="false"
                        differentOddEven="false">
            <oddHeader>
            </oddHeader>
            <oddFooter>
            </oddFooter>
          </headerFooter>
        </worksheet>`)
	worksheet := new(xlsxWorksheet)
	err := xml.NewDecoder(sheetxml).Decode(worksheet)
	c.Assert(err, IsNil)
	c.Assert(worksheet.Dimension.Ref, Equals, "A1:B2")
	c.Assert(worksheet.SheetData.Row, HasLen, 2)
	c.Assert(worksheet.SheetFormatPr.DefaultRowHeight, Equals, 15.0)
	c.Assert(worksheet.SheetFormatPr.DefaultColWidth, Equals, 8.0)
	row := worksheet.SheetData.Row[0]
	c.Assert(row.R, Equals, 1)
	c.Assert(row.C, HasLen, 2)
	cell := row.C[0]
	c.Assert(cell.R, Equals, "A1")
	c.Assert(cell.T, Equals, "s")
	c.Assert(cell.V, Equals, "0")
}
<|endoftext|>