<commit_before>package wipro

import (
	"fmt"
	"io"

	"h12.me/gengo"
)

func (t GoTypes) GoFuncs(w io.Writer) {
	fpl(w, "package proto")
	fpl(w, "import (")
	fpl(w, `"hash/crc32"`)
	fpl(w, ")")
	for _, decl := range t.TypeDecls {
		genMarshalFunc(w, decl)
		fpl(w, "")
		genUnmarshalFunc(w, decl)
		fpl(w, "")
	}
}

func genMarshalFunc(w io.Writer, decl *gengo.TypeDecl) {
	t := &decl.Type
	if t.Kind == gengo.IdentKind && t.Ident == "M" {
		return
	}
	fpl(w, "func (t *%s) Marshal(w *Writer) {", decl.Name)
	switch t.Kind {
	case gengo.StructKind:
		if f0 := t.Fields[0]; f0.Name == "Size" || f0.Name == "CRC" {
			fpl(w, "offset := len(w.B)")
			marshalField(w, t.Fields[0])
			fpl(w, "start := len(w.B)")
			for _, field := range t.Fields[1:] {
				marshalField(w, field)
			}
			switch f0.Name {
			case "Size":
				fpl(w, "w.SetInt32(offset, int32(len(w.B)-start))")
			case "CRC":
				fpl(w, "w.SetUint32(offset, crc32.ChecksumIEEE(w.B[start:]))")
			}
		} else {
			for _, f := range t.Fields {
				marshalField(w, f)
			}
		}
	case gengo.ArrayKind:
		marshalValue(w, "(*t)", t, t.Ident)
	case gengo.IdentKind:
		marshalValue(w, "(*t)", t, decl.Name)
	default:
		fpl(w, "// type %s, %v", decl.Name, decl.Type)
	}
	fpl(w, "}")
}

func genUnmarshalFunc(w io.Writer, decl *gengo.TypeDecl) {
	t := &decl.Type
	if t.Kind == gengo.IdentKind && t.Ident == "M" {
		return
	}
	fpl(w, "func (t *%s) Unmarshal(r *Reader) {", decl.Name)
	switch t.Kind {
	case gengo.StructKind:
		if f0 := t.Fields[0]; f0.Name == "Size" || f0.Name == "CRC" {
			unmarshalField(w, t.Fields[0])
			fpl(w, "start := r.Offset")
			for _, field := range t.Fields[1:] {
				unmarshalField(w, field)
			}
			switch f0.Name {
			case "Size":
				fpl(w, "if r.Err == nil && int(t.Size) != r.Offset-start {")
				fpl(w, `r.Err = ErrSizeMismatch`)
				fpl(w, "}")
			case "CRC":
				fpl(w, "if r.Err == nil && t.CRC != crc32.ChecksumIEEE(r.B[start:r.Offset]) {")
				fpl(w, `r.Err = ErrCRCMismatch`)
				fpl(w, "}")
			}
		} else {
			for _, f := range t.Fields {
				unmarshalField(w, f)
			}
		}
	case gengo.ArrayKind:
		unmarshalValue(w, "(*t)", t, t.Ident)
	case gengo.IdentKind:
		unmarshalValue(w, "(*t)", t, decl.Name)
	default:
		fpl(w, "// type %s, %v", decl.Name, decl.Type)
	}
	fpl(w, "}")
}

func marshalField(w io.Writer, f *gengo.Field) {
	fName := "t." + f.Name
	if f.Name == "" {
		fName = "t." + f.Type.Ident
	}
	marshalValue(w, fName, &f.Type, f.Type.Ident)
}

func unmarshalField(w io.Writer, f *gengo.Field) {
	fName := "t." + f.Name
	if f.Name == "" {
		fName = "t." + f.Type.Ident
	}
	unmarshalValue(w, fName, &f.Type, f.Type.Ident)
}

func marshalValue(w io.Writer, name string, typ *gengo.Type, declType string) {
	switch typ.Kind {
	case gengo.IdentKind:
		conv := ""
		if typ.Ident != declType {
			conv = declType
		}
		switch typ.Ident {
		case "int64":
			marshalInt(w, name, 64, conv)
		case "int32":
			marshalInt(w, name, 32, conv)
		case "int16":
			marshalInt(w, name, 16, conv)
		case "int8":
			marshalInt(w, name, 8, conv)
		case "uint64":
			marshalUint(w, name, 64, conv)
		case "uint32":
			marshalUint(w, name, 32, conv)
		case "uint16":
			marshalUint(w, name, 16, conv)
		case "uint8":
			marshalUint(w, name, 8, conv)
		case "string":
			marshalString(w, name, conv)
		case "[]byte":
			fpl(w, "w.WriteBytes(%s)", name)
		default:
			marshalMarshaler(w, name)
		}
	case gengo.ArrayKind:
		switch typ.Get("array_prefix").(string) {
		case "length":
			marshalLengthArray(w, name, typ)
		case "size":
			marshalSizeArray(w, name, typ)
		}
	default:
		fpl(w, "// value %s %v", name, typ.Kind)
	}
}

func unmarshalValue(w io.Writer, name string, typ *gengo.Type, declType string) {
	switch typ.Kind {
	case gengo.IdentKind:
		conv := ""
		if typ.Ident != declType {
			conv = declType
		}
		switch typ.Ident {
		case "int64":
			unmarshalInt(w, name, 64, conv)
		case "int32":
			unmarshalInt(w, name, 32, conv)
		case "int16":
			unmarshalInt(w, name, 16, conv)
		case "int8":
			unmarshalInt(w, name, 8, conv)
		case "uint64":
			unmarshalUint(w, name, 64, conv)
		case "uint32":
			unmarshalUint(w, name, 32, conv)
		case "uint16":
			unmarshalUint(w, name, 16, conv)
		case "uint8":
			unmarshalUint(w, name, 8, conv)
		case "string":
			unmarshalString(w, name, conv)
		case "[]byte":
			fpl(w, "%s = r.ReadBytes()", name)
		default:
			unmarshalUnmarshaler(w, name, typ.Ident)
		}
	case gengo.ArrayKind:
		switch typ.Get("array_prefix").(string) {
		case "length":
			unmarshalLengthArray(w, name, typ)
		case "size":
			unmarshalSizeArray(w, name, typ)
		}
	default:
		fpl(w, "// value %s %v", name, typ.Kind)
	}
}

func marshalLengthArray(w io.Writer, name string, typ *gengo.Type) {
	marshalInt(w, fmt.Sprintf("int32(len(%s))", name), 32, "")
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		marshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		marshalMarshaler(w, name+"[i]")
	}
	fpl(w, "}")
}

func unmarshalLengthArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "%s = make([]%s, int(r.ReadInt32()))", name, typ.Ident)
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		unmarshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		unmarshalUnmarshaler(w, name+"[i]", typ.Ident)
	}
	fpl(w, "}")
}

func marshalSizeArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "offset := len(w.B)")
	fpl(w, "w.WriteInt32(0)")
	fpl(w, "start := len(w.B)")
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		marshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		marshalMarshaler(w, name+"[i]")
	}
	fpl(w, "}")
	fpl(w, "w.SetInt32(offset, int32(len(w.B)-start))")
}

func unmarshalSizeArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "size := int(r.ReadInt32())")
	fpl(w, "start := r.Offset")
	fpl(w, "for r.Offset-start < size {")
	fpl(w, "var m %s", typ.Ident)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		unmarshalValue(w, "m", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		unmarshalUnmarshaler(w, "m", typ.Ident)
	}
	// NOTE: server optimization, ignore err for sized array element and quit silently
	fpl(w, "if r.Err != nil {")
	fpl(w, "r.Err = nil")
	fpl(w, "r.Offset = len(r.B)")
	fpl(w, "return")
	fpl(w, "}")
	fpl(w, "*t = append(*t, m)")
	fpl(w, "}")
}

func marshalMarshaler(w io.Writer, marshaler string) {
	fpl(w, "%s.Marshal(w)", marshaler)
}

func unmarshalUnmarshaler(w io.Writer, unmarshaler, typ string) {
	fpl(w, "%s.Unmarshal(r)", unmarshaler)
}

func marshalInt(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "w.WriteInt%d(int%d(%s))", bit, bit, name)
		return
	}
	fpl(w, "w.WriteInt%d(%s)", bit, name)
}

func unmarshalInt(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "%s=%s(r.ReadInt%d())", name, convType, bit)
		return
	}
	fpl(w, "%s=r.ReadInt%d()", name, bit)
}

func marshalUint(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "w.WriteUint%d(uint%d(%s))", bit, bit, name)
		return
	}
	fpl(w, "w.WriteUint%d(%s)", bit, name)
}

func unmarshalUint(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "%s=%s(r.ReadUint%d())", name, convType, bit)
		return
	}
	fpl(w, "%s=r.ReadUint%d()", name, bit)
}

func marshalString(w io.Writer, name string, convType string) {
	if convType != "" {
		fpl(w, "w.WriteString(string(%s))", name)
		return
	}
	fpl(w, "w.WriteString(%s)", name)
}

func unmarshalString(w io.Writer, name string, convType string) {
	if convType != "" {
		fpl(w, "%s = %s(r.ReadString())", name, convType)
		return
	}
	fpl(w, name+" = r.ReadString()")
}
<commit_msg>skip if no fields<commit_after>package wipro

import (
	"fmt"
	"io"

	"h12.me/gengo"
)

func (t GoTypes) GoFuncs(w io.Writer) {
	fpl(w, "package proto")
	fpl(w, "import (")
	fpl(w, `"hash/crc32"`)
	fpl(w, ")")
	for _, decl := range t.TypeDecls {
		genMarshalFunc(w, decl)
		fpl(w, "")
		genUnmarshalFunc(w, decl)
		fpl(w, "")
	}
}

func genMarshalFunc(w io.Writer, decl *gengo.TypeDecl) {
	t := &decl.Type
	if t.Kind == gengo.IdentKind && t.Ident == "M" {
		return
	}
	fpl(w, "func (t *%s) Marshal(w *Writer) {", decl.Name)
	switch t.Kind {
	case gengo.StructKind:
		if len(t.Fields) > 0 {
			if f0 := t.Fields[0]; f0.Name == "Size" || f0.Name == "CRC" {
				fpl(w, "offset := len(w.B)")
				marshalField(w, t.Fields[0])
				fpl(w, "start := len(w.B)")
				for _, field := range t.Fields[1:] {
					marshalField(w, field)
				}
				switch f0.Name {
				case "Size":
					fpl(w, "w.SetInt32(offset, int32(len(w.B)-start))")
				case "CRC":
					fpl(w, "w.SetUint32(offset, crc32.ChecksumIEEE(w.B[start:]))")
				}
			} else {
				for _, f := range t.Fields {
					marshalField(w, f)
				}
			}
		} else {
			fpl(w, "// no fields for type %s, %v", decl.Name, decl.Type)
		}
	case gengo.ArrayKind:
		marshalValue(w, "(*t)", t, t.Ident)
	case gengo.IdentKind:
		marshalValue(w, "(*t)", t, decl.Name)
	default:
		fpl(w, "// type %s, %v", decl.Name, decl.Type)
	}
	fpl(w, "}")
}

func genUnmarshalFunc(w io.Writer, decl *gengo.TypeDecl) {
	t := &decl.Type
	if t.Kind == gengo.IdentKind && t.Ident == "M" {
		return
	}
	fpl(w, "func (t *%s) Unmarshal(r *Reader) {", decl.Name)
	switch t.Kind {
	case gengo.StructKind:
		if len(t.Fields) > 0 {
			if f0 := t.Fields[0]; f0.Name == "Size" || f0.Name == "CRC" {
				unmarshalField(w, t.Fields[0])
				fpl(w, "start := r.Offset")
				for _, field := range t.Fields[1:] {
					unmarshalField(w, field)
				}
				switch f0.Name {
				case "Size":
					fpl(w, "if r.Err == nil && int(t.Size) != r.Offset-start {")
					fpl(w, `r.Err = ErrSizeMismatch`)
					fpl(w, "}")
				case "CRC":
					fpl(w, "if r.Err == nil && t.CRC != crc32.ChecksumIEEE(r.B[start:r.Offset]) {")
					fpl(w, `r.Err = ErrCRCMismatch`)
					fpl(w, "}")
				}
			} else {
				for _, f := range t.Fields {
					unmarshalField(w, f)
				}
			}
		} else {
			fpl(w, "// no fields for type %s, %v", decl.Name, decl.Type)
		}
	case gengo.ArrayKind:
		unmarshalValue(w, "(*t)", t, t.Ident)
	case gengo.IdentKind:
		unmarshalValue(w, "(*t)", t, decl.Name)
	default:
		fpl(w, "// type %s, %v", decl.Name, decl.Type)
	}
	fpl(w, "}")
}

func marshalField(w io.Writer, f *gengo.Field) {
	fName := "t." + f.Name
	if f.Name == "" {
		fName = "t." + f.Type.Ident
	}
	marshalValue(w, fName, &f.Type, f.Type.Ident)
}

func unmarshalField(w io.Writer, f *gengo.Field) {
	fName := "t." + f.Name
	if f.Name == "" {
		fName = "t." + f.Type.Ident
	}
	unmarshalValue(w, fName, &f.Type, f.Type.Ident)
}

func marshalValue(w io.Writer, name string, typ *gengo.Type, declType string) {
	switch typ.Kind {
	case gengo.IdentKind:
		conv := ""
		if typ.Ident != declType {
			conv = declType
		}
		switch typ.Ident {
		case "int64":
			marshalInt(w, name, 64, conv)
		case "int32":
			marshalInt(w, name, 32, conv)
		case "int16":
			marshalInt(w, name, 16, conv)
		case "int8":
			marshalInt(w, name, 8, conv)
		case "uint64":
			marshalUint(w, name, 64, conv)
		case "uint32":
			marshalUint(w, name, 32, conv)
		case "uint16":
			marshalUint(w, name, 16, conv)
		case "uint8":
			marshalUint(w, name, 8, conv)
		case "string":
			marshalString(w, name, conv)
		case "[]byte":
			fpl(w, "w.WriteBytes(%s)", name)
		default:
			marshalMarshaler(w, name)
		}
	case gengo.ArrayKind:
		switch typ.Get("array_prefix").(string) {
		case "length":
			marshalLengthArray(w, name, typ)
		case "size":
			marshalSizeArray(w, name, typ)
		}
	default:
		fpl(w, "// value %s %v", name, typ.Kind)
	}
}

func unmarshalValue(w io.Writer, name string, typ *gengo.Type, declType string) {
	switch typ.Kind {
	case gengo.IdentKind:
		conv := ""
		if typ.Ident != declType {
			conv = declType
		}
		switch typ.Ident {
		case "int64":
			unmarshalInt(w, name, 64, conv)
		case "int32":
			unmarshalInt(w, name, 32, conv)
		case "int16":
			unmarshalInt(w, name, 16, conv)
		case "int8":
			unmarshalInt(w, name, 8, conv)
		case "uint64":
			unmarshalUint(w, name, 64, conv)
		case "uint32":
			unmarshalUint(w, name, 32, conv)
		case "uint16":
			unmarshalUint(w, name, 16, conv)
		case "uint8":
			unmarshalUint(w, name, 8, conv)
		case "string":
			unmarshalString(w, name, conv)
		case "[]byte":
			fpl(w, "%s = r.ReadBytes()", name)
		default:
			unmarshalUnmarshaler(w, name, typ.Ident)
		}
	case gengo.ArrayKind:
		switch typ.Get("array_prefix").(string) {
		case "length":
			unmarshalLengthArray(w, name, typ)
		case "size":
			unmarshalSizeArray(w, name, typ)
		}
	default:
		fpl(w, "// value %s %v", name, typ.Kind)
	}
}

func marshalLengthArray(w io.Writer, name string, typ *gengo.Type) {
	marshalInt(w, fmt.Sprintf("int32(len(%s))", name), 32, "")
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		marshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		marshalMarshaler(w, name+"[i]")
	}
	fpl(w, "}")
}

func unmarshalLengthArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "%s = make([]%s, int(r.ReadInt32()))", name, typ.Ident)
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		unmarshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		unmarshalUnmarshaler(w, name+"[i]", typ.Ident)
	}
	fpl(w, "}")
}

func marshalSizeArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "offset := len(w.B)")
	fpl(w, "w.WriteInt32(0)")
	fpl(w, "start := len(w.B)")
	fpl(w, "for i := range %s {", name)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		marshalValue(w, name+"[i]", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		marshalMarshaler(w, name+"[i]")
	}
	fpl(w, "}")
	fpl(w, "w.SetInt32(offset, int32(len(w.B)-start))")
}

func unmarshalSizeArray(w io.Writer, name string, typ *gengo.Type) {
	fpl(w, "size := int(r.ReadInt32())")
	fpl(w, "start := r.Offset")
	fpl(w, "for r.Offset-start < size {")
	fpl(w, "var m %s", typ.Ident)
	switch typ.Ident {
	case "int8", "int16", "int32", "int64", "string":
		unmarshalValue(w, "m", &gengo.Type{Kind: gengo.IdentKind, Ident: typ.Ident}, typ.Ident)
	default:
		unmarshalUnmarshaler(w, "m", typ.Ident)
	}
	// NOTE: server optimization, ignore err for sized array element and quit silently
	fpl(w, "if r.Err != nil {")
	fpl(w, "r.Err = nil")
	fpl(w, "r.Offset = len(r.B)")
	fpl(w, "return")
	fpl(w, "}")
	fpl(w, "*t = append(*t, m)")
	fpl(w, "}")
}

func marshalMarshaler(w io.Writer, marshaler string) {
	fpl(w, "%s.Marshal(w)", marshaler)
}

func unmarshalUnmarshaler(w io.Writer, unmarshaler, typ string) {
	fpl(w, "%s.Unmarshal(r)", unmarshaler)
}

func marshalInt(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "w.WriteInt%d(int%d(%s))", bit, bit, name)
		return
	}
	fpl(w, "w.WriteInt%d(%s)", bit, name)
}

func unmarshalInt(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "%s=%s(r.ReadInt%d())", name, convType, bit)
		return
	}
	fpl(w, "%s=r.ReadInt%d()", name, bit)
}

func marshalUint(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "w.WriteUint%d(uint%d(%s))", bit, bit, name)
		return
	}
	fpl(w, "w.WriteUint%d(%s)", bit, name)
}

func unmarshalUint(w io.Writer, name string, bit int, convType string) {
	if convType != "" {
		fpl(w, "%s=%s(r.ReadUint%d())", name, convType, bit)
		return
	}
	fpl(w, "%s=r.ReadUint%d()", name, bit)
}

func marshalString(w io.Writer, name string, convType string) {
	if convType != "" {
		fpl(w, "w.WriteString(string(%s))", name)
		return
	}
	fpl(w, "w.WriteString(%s)", name)
}

func unmarshalString(w io.Writer, name string, convType string) {
	if convType != "" {
		fpl(w, "%s = %s(r.ReadString())", name, convType)
		return
	}
	fpl(w, name+" = r.ReadString()")
}
<|endoftext|>


<commit_before>package internal

import (
	"fmt"
	"os"

	"github.com/google/cayley/graph"
	"github.com/google/cayley/exporter"
)

// Dump the content of the database into a file based
// on a few different formats
func Dump(qs graph.QuadStore, outFile, typ string) error {
	var f *os.File
	if outFile == "-" {
		f = os.Stdout
	} else {
		var err error
		f, err = os.Create(outFile)
		if err != nil {
			return fmt.Errorf("could not open file %q: %v", outFile, err)
		}
		defer f.Close()
		fmt.Printf("dumping db to file %q\n", outFile)
	}

	export := exporter.NewExporter(f, qs)
	if export.Err() != nil {
		return export.Err()
	}

	switch typ {
	case "nquad":
		export.ExportNquad()
	case "json":
		export.ExportJson()
	// gml/graphml experimental
	case "gml":
		export.ExportGml()
	case "graphml":
		export.ExportGraphml()
	default:
		return fmt.Errorf("unknown format %q", typ)
	}

	if export.Err() != nil {
		return export.Err()
	}

        if outFile != "-" {
		fmt.Printf("%d entries were written\n", export.Count())
	}
	return nil
}
<commit_msg>add gzip support<commit_after>package internal

import (
	"fmt"
	"os"
	"compress/gzip"
	"path/filepath"

	"github.com/google/cayley/graph"
	"github.com/google/cayley/exporter"
)

// Dump the content of the database into a file based
// on a few different formats
func Dump(qs graph.QuadStore, outFile, typ string) error {
	var f *os.File
	if outFile == "-" {
		f = os.Stdout
	} else {
		var err error
		f, err = os.Create(outFile)
		if err != nil {
			return fmt.Errorf("could not open file %q: %v", outFile, err)
		}
		defer f.Close()
		fmt.Printf("dumping db to file %q\n", outFile)
	}

	var export *exporter.Exporter
	if filepath.Ext(outFile) == ".gz" {
		gzip := gzip.NewWriter(f)
		defer gzip.Close()
		export = exporter.NewExporter(gzip, qs)
	} else {
		export = exporter.NewExporter(f, qs)
	}

	//TODO: add possible support for exporting specific queries only
	switch typ {
	case "nquad":
		export.ExportNquad()
	case "json":
		export.ExportJson()
	// gml/graphml experimental
	case "gml":
		export.ExportGml()
	case "graphml":
		export.ExportGraphml()
	default:
		return fmt.Errorf("unknown format %q", typ)
	}

	if export.Err() != nil {
		return export.Err()
	}

        if outFile != "-" {
		fmt.Printf("%d entries were written\n", export.Count())
	}
	return nil
}
<|endoftext|>


<commit_before>package nat

// nat is a convenience package for docker's manipulation of strings describing
// network ports.

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/docker/docker/pkg/parsers"
)

const (
	PortSpecTemplate       = "ip:hostPort:containerPort"
	PortSpecTemplateFormat = "ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort"
)

type PortBinding struct {
	HostIp   string
	HostPort string
}

type PortMap map[Port][]PortBinding

type PortSet map[Port]struct{}

// 80/tcp
type Port string

func NewPort(proto, port string) Port {
	return Port(fmt.Sprintf("%s/%s", port, proto))
}

func ParsePort(rawPort string) (int, error) {
	port, err := strconv.ParseUint(rawPort, 10, 16)
	if err != nil {
		return 0, err
	}
	return int(port), nil
}

func (p Port) Proto() string {
	parts := strings.Split(string(p), "/")
	if len(parts) == 1 {
		return "tcp"
	}
	return parts[1]
}

func (p Port) Port() string {
	return strings.Split(string(p), "/")[0]
}

func (p Port) Int() int {
	i, err := ParsePort(p.Port())
	if err != nil {
		panic(err)
	}
	return i
}

// Splits a port in the format of port/proto
func SplitProtoPort(rawPort string) (string, string) {
	parts := strings.Split(rawPort, "/")
	l := len(parts)
	if l == 0 {
		return "", ""
	}
	if l == 1 {
		return "tcp", rawPort
	}
	return parts[1], parts[0]
}

func validateProto(proto string) bool {
	for _, availableProto := range []string{"tcp", "udp"} {
		if availableProto == proto {
			return true
		}
	}
	return false
}

// We will receive port specs in the format of ip:public:private/proto and these need to be
// parsed in the internal types
func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
	var (
		exposedPorts = make(map[Port]struct{}, len(ports))
		bindings     = make(map[Port][]PortBinding)
	)

	for _, rawPort := range ports {
		proto := "tcp"

		if i := strings.LastIndex(rawPort, "/"); i != -1 {
			proto = rawPort[i+1:]
			rawPort = rawPort[:i]
		}
		if !strings.Contains(rawPort, ":") {
			rawPort = fmt.Sprintf("::%s", rawPort)
		} else if len(strings.Split(rawPort, ":")) == 2 {
			rawPort = fmt.Sprintf(":%s", rawPort)
		}

		parts, err := parsers.PartParser(PortSpecTemplate, rawPort)
		if err != nil {
			return nil, nil, err
		}

		var (
			containerPort = parts["containerPort"]
			rawIp         = parts["ip"]
			hostPort      = parts["hostPort"]
		)

		if containerPort == "" {
			return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
		}
		if _, err := strconv.ParseUint(containerPort, 10, 16); err != nil {
			return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
		}
		if _, err := strconv.ParseUint(hostPort, 10, 16); hostPort != "" && err != nil {
			return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
		}
		if !validateProto(proto) {
			return nil, nil, fmt.Errorf("Invalid proto: %s", proto)
		}

		port := NewPort(proto, containerPort)
		if _, exists := exposedPorts[port]; !exists {
			exposedPorts[port] = struct{}{}
		}

		binding := PortBinding{
			HostIp:   rawIp,
			HostPort: hostPort,
		}
		bslice, exists := bindings[port]
		if !exists {
			bslice = []PortBinding{}
		}
		bindings[port] = append(bslice, binding)
	}
	return exposedPorts, bindings, nil
}
<commit_msg>fix parsing of hostnames when we actually want IP addresses.<commit_after>package nat

// nat is a convenience package for docker's manipulation of strings describing
// network ports.

import (
	"fmt"
	"net"
	"strconv"
	"strings"

	"github.com/docker/docker/pkg/parsers"
)

const (
	PortSpecTemplate       = "ip:hostPort:containerPort"
	PortSpecTemplateFormat = "ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort"
)

type PortBinding struct {
	HostIp   string
	HostPort string
}

type PortMap map[Port][]PortBinding

type PortSet map[Port]struct{}

// 80/tcp
type Port string

func NewPort(proto, port string) Port {
	return Port(fmt.Sprintf("%s/%s", port, proto))
}

func ParsePort(rawPort string) (int, error) {
	port, err := strconv.ParseUint(rawPort, 10, 16)
	if err != nil {
		return 0, err
	}
	return int(port), nil
}

func (p Port) Proto() string {
	parts := strings.Split(string(p), "/")
	if len(parts) == 1 {
		return "tcp"
	}
	return parts[1]
}

func (p Port) Port() string {
	return strings.Split(string(p), "/")[0]
}

func (p Port) Int() int {
	i, err := ParsePort(p.Port())
	if err != nil {
		panic(err)
	}
	return i
}

// Splits a port in the format of port/proto
func SplitProtoPort(rawPort string) (string, string) {
	parts := strings.Split(rawPort, "/")
	l := len(parts)
	if l == 0 {
		return "", ""
	}
	if l == 1 {
		return "tcp", rawPort
	}
	return parts[1], parts[0]
}

func validateProto(proto string) bool {
	for _, availableProto := range []string{"tcp", "udp"} {
		if availableProto == proto {
			return true
		}
	}
	return false
}

// We will receive port specs in the format of ip:public:private/proto and these need to be
// parsed in the internal types
func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
	var (
		exposedPorts = make(map[Port]struct{}, len(ports))
		bindings     = make(map[Port][]PortBinding)
	)

	for _, rawPort := range ports {
		proto := "tcp"

		if i := strings.LastIndex(rawPort, "/"); i != -1 {
			proto = rawPort[i+1:]
			rawPort = rawPort[:i]
		}
		if !strings.Contains(rawPort, ":") {
			rawPort = fmt.Sprintf("::%s", rawPort)
		} else if len(strings.Split(rawPort, ":")) == 2 {
			rawPort = fmt.Sprintf(":%s", rawPort)
		}

		parts, err := parsers.PartParser(PortSpecTemplate, rawPort)
		if err != nil {
			return nil, nil, err
		}

		var (
			containerPort = parts["containerPort"]
			rawIp         = parts["ip"]
			hostPort      = parts["hostPort"]
		)

		if rawIp != "" && net.ParseIP(rawIp) == nil {
			return nil, nil, fmt.Errorf("Invalid ip address: %s", rawIp)
		}
		if containerPort == "" {
			return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
		}
		if _, err := strconv.ParseUint(containerPort, 10, 16); err != nil {
			return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
		}
		if _, err := strconv.ParseUint(hostPort, 10, 16); hostPort != "" && err != nil {
			return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
		}

		if !validateProto(proto) {
			return nil, nil, fmt.Errorf("Invalid proto: %s", proto)
		}

		port := NewPort(proto, containerPort)
		if _, exists := exposedPorts[port]; !exists {
			exposedPorts[port] = struct{}{}
		}

		binding := PortBinding{
			HostIp:   rawIp,
			HostPort: hostPort,
		}
		bslice, exists := bindings[port]
		if !exists {
			bslice = []PortBinding{}
		}
		bindings[port] = append(bslice, binding)
	}
	return exposedPorts, bindings, nil
}
<|endoftext|>


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

// Author: jsing@google.com (Joel Sing)

package ncc

// This file contains ARP related functions for the Seesaw Network Control
// component.

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"syscall"
	"unsafe"

	ncctypes "github.com/google/seesaw/ncc/types"

	log "github.com/golang/glog"
)

const (
	opARPRequest = 1
	opARPReply   = 2
)

var (
	ethernetBroadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

func htons(p uint16) uint16 {
	var b [2]byte
	binary.BigEndian.PutUint16(b[:], p)
	return *(*uint16)(unsafe.Pointer(&b))
}

// arpHeader specifies the header for an ARP message.
type arpHeader struct {
	hardwareType          uint16
	protocolType          uint16
	hardwareAddressLength uint8
	protocolAddressLength uint8
	opcode                uint16
}

// arpMessage represents an ARP message.
type arpMessage struct {
	arpHeader
	senderHardwareAddress []byte
	senderProtocolAddress []byte
	targetHardwareAddress []byte
	targetProtocolAddress []byte
}

// bytes returns the wire representation of the ARP message.
func (m *arpMessage) bytes() ([]byte, error) {
	buf := new(bytes.Buffer)

	if err := binary.Write(buf, binary.BigEndian, m.arpHeader); err != nil {
		return nil, fmt.Errorf("binary write failed: %v", err)
	}
	buf.Write(m.senderHardwareAddress)
	buf.Write(m.senderProtocolAddress)
	buf.Write(m.targetHardwareAddress)
	buf.Write(m.targetProtocolAddress)

	return buf.Bytes(), nil
}

// gratuitousARPReply returns an ARP message that contains a gratuitous ARP
// reply from the specified sender.
func gratuitousARPReply(ip net.IP, mac net.HardwareAddr) (*arpMessage, error) {
	if ip.To4() == nil {
		return nil, fmt.Errorf("%q is not an IPv4 address", ip)
	}
	if len(mac) != 6 {
		return nil, fmt.Errorf("%q is not an Ethernet MAC address", mac)
	}

	m := &arpMessage{
		arpHeader{
			6,           // IEEE 802
			0x0800,      // Ethernet
			6,           // 48-bit MAC Address
			net.IPv4len, // 32-bit IPv4 Address
			opARPReply,  // ARP Reply
		},
		mac,
		ip.To4(),
		ethernetBroadcast,
		net.IPv4bcast,
	}

	return m, nil
}

// sendARP sends the given ARP message via the specified interface.
func sendARP(iface *net.Interface, m *arpMessage) error {
	fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_DGRAM, int(htons(syscall.ETH_P_ARP)))
	if err != nil {
		return fmt.Errorf("failed to get raw socket: %v", err)
	}
	defer syscall.Close(fd)

	if err := syscall.BindToDevice(fd, iface.Name); err != nil {
		return fmt.Errorf("failed to bind to device: %v", err)
	}

	ll := syscall.SockaddrLinklayer{
		Protocol: htons(syscall.ETH_P_ARP),
		Ifindex:  iface.Index,
		Pkttype:  0, // syscall.PACKET_HOST
		Hatype:   m.hardwareType,
		Halen:    m.hardwareAddressLength,
	}
	target := ethernetBroadcast
	if m.opcode == opARPReply {
		target = m.targetHardwareAddress
	}
	for i := 0; i < len(target); i++ {
		ll.Addr[i] = target[i]
	}

	b, err := m.bytes()
	if err != nil {
		return fmt.Errorf("failed to convert ARP message: %v", err)
	}

	if err := syscall.Bind(fd, &ll); err != nil {
		return fmt.Errorf("failed to bind: %v", err)
	}
	if err := syscall.Sendto(fd, b, 0, &ll); err != nil {
		return fmt.Errorf("failed to send: %v", err)
	}

	return nil
}

// ARPSendGratuitous sends a gratuitous ARP message via the specified interface.
func (ncc *SeesawNCC) ARPSendGratuitous(arp *ncctypes.ARPGratuitous, out *int) error {
	iface, err := net.InterfaceByName(arp.IfaceName)
	if err != nil {
		return fmt.Errorf("failed to get interface %q: %v", arp.IfaceName, err)
	}
	log.V(2).Infof("Sending gratuitous ARP for %s (%s) via %s", arp.IP, iface.HardwareAddr, iface.Name)
	m, err := gratuitousARPReply(arp.IP, iface.HardwareAddr)
	if err != nil {
		return err
	}
	return sendARP(iface, m)
}
<commit_msg>Make the ARP messages reflect the Ethernet type. (#14)<commit_after>// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: jsing@google.com (Joel Sing)

package ncc

// This file contains ARP related functions for the Seesaw Network Control
// component.

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"syscall"
	"unsafe"

	ncctypes "github.com/google/seesaw/ncc/types"

	log "github.com/golang/glog"
)

const (
	opARPRequest = 1
	opARPReply   = 2
	hwLen        = 6
)

var (
	ethernetBroadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

func htons(p uint16) uint16 {
	var b [2]byte
	binary.BigEndian.PutUint16(b[:], p)
	return *(*uint16)(unsafe.Pointer(&b))
}

// arpHeader specifies the header for an ARP message.
type arpHeader struct {
	hardwareType          uint16
	protocolType          uint16
	hardwareAddressLength uint8
	protocolAddressLength uint8
	opcode                uint16
}

// arpMessage represents an ARP message.
type arpMessage struct {
	arpHeader
	senderHardwareAddress []byte
	senderProtocolAddress []byte
	targetHardwareAddress []byte
	targetProtocolAddress []byte
}

// bytes returns the wire representation of the ARP message.
func (m *arpMessage) bytes() ([]byte, error) {
	buf := new(bytes.Buffer)

	if err := binary.Write(buf, binary.BigEndian, m.arpHeader); err != nil {
		return nil, fmt.Errorf("binary write failed: %v", err)
	}
	buf.Write(m.senderHardwareAddress)
	buf.Write(m.senderProtocolAddress)
	buf.Write(m.targetHardwareAddress)
	buf.Write(m.targetProtocolAddress)

	return buf.Bytes(), nil
}

// gratuitousARPReply returns an ARP message that contains a gratuitous ARP
// reply from the specified sender.
func gratuitousARPReply(ip net.IP, mac net.HardwareAddr) (*arpMessage, error) {
	if ip.To4() == nil {
		return nil, fmt.Errorf("%q is not an IPv4 address", ip)
	}
	if len(mac) != hwLen {
		return nil, fmt.Errorf("%q is not an Ethernet MAC address", mac)
	}

	m := &arpMessage{
		arpHeader{
			1,           // Ethernet
			0x0800,      // IPv4
			hwLen,       // 48-bit MAC Address
			net.IPv4len, // 32-bit IPv4 Address
			opARPReply,  // ARP Reply
		},
		mac,
		ip.To4(),
		ethernetBroadcast,
		net.IPv4bcast,
	}

	return m, nil
}

// sendARP sends the given ARP message via the specified interface.
func sendARP(iface *net.Interface, m *arpMessage) error {
	fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_DGRAM, int(htons(syscall.ETH_P_ARP)))
	if err != nil {
		return fmt.Errorf("failed to get raw socket: %v", err)
	}
	defer syscall.Close(fd)

	if err := syscall.BindToDevice(fd, iface.Name); err != nil {
		return fmt.Errorf("failed to bind to device: %v", err)
	}

	ll := syscall.SockaddrLinklayer{
		Protocol: htons(syscall.ETH_P_ARP),
		Ifindex:  iface.Index,
		Pkttype:  0, // syscall.PACKET_HOST
		Hatype:   m.hardwareType,
		Halen:    m.hardwareAddressLength,
	}
	target := ethernetBroadcast
	if m.opcode == opARPReply {
		target = m.targetHardwareAddress
	}
	for i := 0; i < len(target); i++ {
		ll.Addr[i] = target[i]
	}

	b, err := m.bytes()
	if err != nil {
		return fmt.Errorf("failed to convert ARP message: %v", err)
	}

	if err := syscall.Bind(fd, &ll); err != nil {
		return fmt.Errorf("failed to bind: %v", err)
	}
	if err := syscall.Sendto(fd, b, 0, &ll); err != nil {
		return fmt.Errorf("failed to send: %v", err)
	}

	return nil
}

// ARPSendGratuitous sends a gratuitous ARP message via the specified interface.
func (ncc *SeesawNCC) ARPSendGratuitous(arp *ncctypes.ARPGratuitous, out *int) error {
	iface, err := net.InterfaceByName(arp.IfaceName)
	if err != nil {
		return fmt.Errorf("failed to get interface %q: %v", arp.IfaceName, err)
	}
	log.V(2).Infof("Sending gratuitous ARP for %s (%s) via %s", arp.IP, iface.HardwareAddr, iface.Name)
	m, err := gratuitousARPReply(arp.IP, iface.HardwareAddr)
	if err != nil {
		return err
	}
	return sendARP(iface, m)
}
<|endoftext|>


<commit_before>package util

import (
	"regexp"
)

func Contains(stringSlice []string, searchString string) bool {
	for _, value := range stringSlice {
		if value == searchString {
			return true
		}
	}
	return false
}

func ContainsRegex(regexs []string, searchString string) bool {
	for _, regex := range regexs {
		match, err := regexp.MatchString(regex, searchString)
		if match {
			return true
		}
		if err != nil {
			loggerUtilHTML.Errorf(err.Error())
		}
	}
	return false
}

func ContainsGetIndex(stringSlice []string, searchString string) int {
	for key, value := range stringSlice {
		if value == searchString {
			return key
		}
	}
	return -1
}
<commit_msg>Add regex for specific form inputs detection<commit_after>package util

import (
	"regexp"
)

func Contains(stringSlice []string, searchString string) bool {
	for _, regex := range stringSlice {
		match, err := regexp.MatchString(regex, searchString)
		if match {
			return true
		}
		if err != nil {
			loggerUtilHTML.Errorf(err.Error())
		}
	}
	return false
}

func ContainsRegex(regexs []string, searchString string) bool {
	for _, regex := range regexs {
		match, err := regexp.MatchString(regex, searchString)
		if match {
			return true
		}
		if err != nil {
			loggerUtilHTML.Errorf(err.Error())
		}
	}
	return false
}

func ContainsGetIndex(stringSlice []string, searchString string) int {
	for key, value := range stringSlice {
		if value == searchString {
			return key
		}
	}
	return -1
}
<|endoftext|>


<commit_before>// Package utils provides zmq connection pool
package utils

import (
	"container/list"
	"fmt"
	"sync"
	"time"

	zmq "github.com/pebbe/zmq4"
)

type Pool struct {
	// Stack of idleConn with most recently used at the front.
	pool list.List

	// mu protects fields defined below.
	mu     sync.Mutex
	cond   *sync.Cond
	closed bool

	// 获取新连接的方法
	New func() (*zmq.Socket, error)

	Max int

	Wait bool //当连接池满的时候是否等待

	Life time.Duration
}

type PooledSocket struct {
	Soc    *zmq.Socket
	expire time.Time
	inUse  bool
	pool   *Pool
	ele    *list.Element //在list中位置
}

/* {{{ func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
 * NewPool creates a new pool. This function is deprecated. Applications should
 * initialize the Pool fields directly as shown in example.
 */
func NewPool(newFn func() (*zmq.Socket, error), max int, life time.Duration) *Pool {
	return &Pool{New: newFn, Max: max, Life: life}
}

/* }}} */

/* {{{ func (p *Pool) Close()
 *
 */
func (p *Pool) Close() {
	p.mu.Lock()
	defer p.mu.Unlock()
	for e := p.pool.Front(); e != nil; e = e.Next() {
		e.Value.(*PooledSocket).Soc.Close()
	}
	p.pool.Init() // clear
	p.closed = true
	if p.cond != nil { //唤醒所有等待者
		p.cond.Broadcast()
	}
}

/* }}} */

/* {{{ func (p *Pool) Get() *Socket
 *
 */
func (p *Pool) Get() (*PooledSocket, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.closed {
		return nil, fmt.Errorf("pool closed")
	}

	for { //不get到誓不罢休
		// Get pooled item.
		if e := p.pool.Front(); e != nil { //如果存在未使用的item,第一个肯定是
			ps := e.Value.(*PooledSocket)
			if !ps.inUse {
				ps.inUse = true
				p.pool.MoveToBack(e) //移到最后
				return ps, nil
			}
		}

		if p.Max <= 0 || p.pool.Len() < p.Max { //池子无限制或者还没满
			// create new.
			if soc, err := p.New(); err != nil { //无法新建
				return nil, err
			} else {
				ps := &PooledSocket{
					Soc:    soc,
					expire: time.Now().Add(p.Life),
					inUse:  true,
					pool:   p,
				}
				ps.ele = p.pool.PushBack(ps)
				return ps, nil
			}
		}

		if !p.Wait { //不等就结束
			return nil, fmt.Errorf("Pool full at %d", p.Max)
		}

		//等待被唤醒
		if p.cond == nil {
			p.cond = sync.NewCond(&p.mu)
		}
		p.cond.Wait()
	}
}

/* }}} */

/* {{{ func (ps *PooledSocket) Close(destory ...bool)
 *
 */
func (ps *PooledSocket) Close(destory ...bool) {
	//归还, 保留销毁的选项,由客户端决定
	p := ps.pool
	p.mu.Lock()
	defer p.mu.Unlock()
	if len(destory) > 0 && destory[0] == true {
		//指示需要销毁
		ps.Soc.Close()
		p.pool.Remove(ps.ele)
	} else {
		ps.inUse = false
		ps.expire = time.Now().Add(p.Life) //过期时间延长
		p.pool.MoveToFront(ps.ele)         //放到最前
	}
	if p.cond != nil { //唤醒一个, 如果有的话
		p.cond.Signal()
	}
}

/* }}} */
<commit_msg>完善pool<commit_after>// Package utils provides zmq connection pool
package utils

import (
	"container/list"
	"fmt"
	"sync"
	"time"

	zmq "github.com/pebbe/zmq4"
)

type Pool struct {
	// Stack of idleConn with most recently used at the front.
	pool list.List

	// mu protects fields defined below.
	mu     sync.Mutex
	cond   *sync.Cond
	closed bool

	// 获取新连接的方法
	New func() (*zmq.Socket, error)

	Max int

	Wait bool //当连接池满的时候是否等待

	Life time.Duration
}

type PooledSocket struct {
	Soc    *zmq.Socket
	expire time.Time
	undone bool //未完成
	inUse  bool
	pool   *Pool
	ele    *list.Element //在list中位置
}

/* {{{ func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
 * NewPool creates a new pool. This function is deprecated. Applications should
 * initialize the Pool fields directly as shown in example.
 */
func NewPool(newFn func() (*zmq.Socket, error), max int, life time.Duration) *Pool {
	return &Pool{New: newFn, Max: max, Life: life}
}

/* }}} */

/* {{{ func (p *Pool) Close()
 *
 */
func (p *Pool) Close() {
	p.mu.Lock()
	defer p.mu.Unlock()
	for e := p.pool.Front(); e != nil; e = e.Next() {
		e.Value.(*PooledSocket).Soc.Close()
	}
	p.pool.Init() // clear
	p.closed = true
	if p.cond != nil { //唤醒所有等待者
		p.cond.Broadcast()
	}
}

/* }}} */

/* {{{ func (p *Pool) Get() *Socket
 *
 */
func (p *Pool) Get() (*PooledSocket, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.closed {
		return nil, fmt.Errorf("pool closed")
	}

	for { //不get到誓不罢休
		// Get pooled item.
		if e := p.pool.Front(); e != nil { //如果存在未使用的item,第一个肯定是
			ps := e.Value.(*PooledSocket)
			if !ps.inUse {
				ps.inUse = true
				p.pool.MoveToBack(e) //移到最后
				return ps, nil
			}
		}

		if p.Max <= 0 || p.pool.Len() < p.Max { //池子无限制或者还没满
			// create new.
			if soc, err := p.New(); err != nil { //无法新建
				return nil, err
			} else {
				ps := &PooledSocket{
					Soc:    soc,
					expire: time.Now().Add(p.Life),
					inUse:  true,
					pool:   p,
				}
				ps.ele = p.pool.PushBack(ps)
				return ps, nil
			}
		}

		if !p.Wait { //不等就结束
			return nil, fmt.Errorf("Pool full at %d", p.Max)
		}

		//等待被唤醒
		if p.cond == nil {
			p.cond = sync.NewCond(&p.mu)
		}
		p.cond.Wait()
	}
}

/* }}} */

/* {{{ func (ps *PooledSocket) Close()
 *
 */
func (ps *PooledSocket) Close() {
	p := ps.pool
	p.mu.Lock()
	defer p.mu.Unlock()
	if ps.undone == true {
		//指示需要销毁
		ps.Soc.Close()
		p.pool.Remove(ps.ele)
	} else {
		ps.inUse = false
		ps.expire = time.Now().Add(p.Life) //过期时间延长
		p.pool.MoveToFront(ps.ele)         //放到最前
	}
	if p.cond != nil { //唤醒一个, 如果有的话
		p.cond.Signal()
	}
}

/* }}} */

/* {{{ func (ps *PooledSocket) Do(timeout time.Duration, msg ...interface{}) (reply []string, err error)
 *
 */
func (ps *PooledSocket) Do(timeout time.Duration, msg ...interface{}) (reply []string, err error) {
	p := ps.pool
	p.mu.Lock()
	defer p.mu.Unlock()

	soc := ps.Soc
	poller := zmq.NewPoller()
	poller.Add(soc, zmq.POLLIN)

	// send
	if _, err := soc.SendMessage(msg...); err != nil {
		return nil, err
	}

	// recv
	if sockets, err := poller.Poll(timeout); err != nil {
		return nil, err
	} else if len(sockets) == 1 {
		return soc.RecvMessage(zmq.DONTWAIT)
	} else {
		return nil, fmt.Errorf("time out!")
	}

	return
}

/* }}} */
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"time"
)

const EscherDateFormat = "20060102T150405Z07"
const HTTPHeaderFormat = "Fri, 02 Jan 2006 15:04:05 MST"

var acceptedTimeFormats = []string{
	EscherDateFormat,
	"20060102T150405Z0700",
	"20060102T150405Z07:00",
	"20060102T150405Z070000",
	"20060102T150405Z07:00:00",
	HTTPHeaderFormat,
	time.ANSIC,
	time.UnixDate,
	time.RubyDate,
	time.RFC822,
	time.RFC822Z,
	time.RFC850,
	time.RFC1123,
	time.RFC1123Z,
	time.RFC3339,
	time.RFC3339Nano,
	time.Kitchen,
	time.Stamp,
	time.StampMilli,
	time.StampMicro,
	time.StampNano,
}

func ParseTime(timeStr string) (time.Time, error) {
	for _, layout := range acceptedTimeFormats {
		t, err := time.Parse(layout, timeStr)

		if err == nil {
			return t, err
		}
	}

	return time.Time{}, errors.New("no layout found for " + timeStr)
}
<commit_msg>[FIX] wrong date format<commit_after>package utils

import (
	"errors"
	"time"
)

const EscherDateFormat = "20060102T150405Z07"
const HTTPHeaderFormat = "Mon, 02 Jan 2006 15:04:05 MST"

var acceptedTimeFormats = []string{
	EscherDateFormat,
	"20060102T150405Z0700",
	"20060102T150405Z07:00",
	"20060102T150405Z070000",
	"20060102T150405Z07:00:00",
	HTTPHeaderFormat,
	time.ANSIC,
	time.UnixDate,
	time.RubyDate,
	time.RFC822,
	time.RFC822Z,
	time.RFC850,
	time.RFC1123,
	time.RFC1123Z,
	time.RFC3339,
	time.RFC3339Nano,
	time.Kitchen,
	time.Stamp,
	time.StampMilli,
	time.StampMicro,
	time.StampNano,
}

func ParseTime(timeStr string) (time.Time, error) {
	for _, layout := range acceptedTimeFormats {
		t, err := time.Parse(layout, timeStr)

		if err == nil {
			return t, err
		}
	}

	return time.Time{}, errors.New("no layout found for " + timeStr)
}
<|endoftext|>


<commit_before>package yiigo

import "testing"

func TestMD5(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "iiinsomnia"},
			want: "483367436bc9a6c5256bfc29a24f955e",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := MD5(tt.args.s); got != tt.want {
				t.Errorf("MD5() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestDate(t *testing.T) {
	type args struct {
		timestamp int64
		format    []string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{
				timestamp: 1458370999,
				format:    []string{"2006-01-02 15:04:05"},
			},
			want: "2016-03-19 15:03:19",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Date(tt.args.timestamp, tt.args.format...); got != tt.want {
				t.Errorf("Date() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestIP2long(t *testing.T) {
	type args struct {
		ip string
	}
	tests := []struct {
		name string
		args args
		want int64
	}{
		{
			name: "t1",
			args: args{ip: "192.0.34.166"},
			want: 3221234342,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := IP2long(tt.args.ip); got != tt.want {
				t.Errorf("IP2long() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestLong2IP(t *testing.T) {
	type args struct {
		ip int64
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{ip: 3221234342},
			want: "192.0.34.166",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Long2IP(tt.args.ip); got != tt.want {
				t.Errorf("Long2IP() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestAddSlashes(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "Is your name O'Reilly?"},
			want: `Is your name O\'Reilly?`,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := AddSlashes(tt.args.s); got != tt.want {
				t.Errorf("AddSlashes() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestStripSlashes(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: `Is your name O\'reilly?`},
			want: "Is your name O'reilly?",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := StripSlashes(tt.args.s); got != tt.want {
				t.Errorf("StripSlashes() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestQuoteMeta(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "Hello world. (can you hear me?)"},
			want: `Hello world\. \(can you hear me\?\)`,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := QuoteMeta(tt.args.s); got != tt.want {
				t.Errorf("QuoteMeta() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>update<commit_after>package yiigo

import "testing"

func TestMD5(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "iiinsomnia"},
			want: "483367436bc9a6c5256bfc29a24f955e",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := MD5(tt.args.s); got != tt.want {
				t.Errorf("MD5() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestDate(t *testing.T) {
	type args struct {
		timestamp int64
		format    []string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{
				timestamp: 1458370999,
				format:    []string{"2006-01-02 15:04:05"},
			},
			want: "2016-03-19 15:03:19",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Date(tt.args.timestamp, tt.args.format...); got != tt.want {
				t.Errorf("Date() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestIP2Long(t *testing.T) {
	type args struct {
		ip string
	}
	tests := []struct {
		name string
		args args
		want int64
	}{
		{
			name: "t1",
			args: args{ip: "192.0.34.166"},
			want: 3221234342,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := IP2Long(tt.args.ip); got != tt.want {
				t.Errorf("IP2Long() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestLong2IP(t *testing.T) {
	type args struct {
		ip int64
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{ip: 3221234342},
			want: "192.0.34.166",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Long2IP(tt.args.ip); got != tt.want {
				t.Errorf("Long2IP() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestAddSlashes(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "Is your name O'Reilly?"},
			want: `Is your name O\'Reilly?`,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := AddSlashes(tt.args.s); got != tt.want {
				t.Errorf("AddSlashes() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestStripSlashes(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: `Is your name O\'reilly?`},
			want: "Is your name O'reilly?",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := StripSlashes(tt.args.s); got != tt.want {
				t.Errorf("StripSlashes() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestQuoteMeta(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "t1",
			args: args{s: "Hello world. (can you hear me?)"},
			want: `Hello world\. \(can you hear me\?\)`,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := QuoteMeta(tt.args.s); got != tt.want {
				t.Errorf("QuoteMeta() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>


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

package main

import (
	"fmt"
	"net"

	hyper "github.com/clearcontainers/agent/api"
	"github.com/vishvananda/netlink"
)

func findLinkFromHwAddr(netHandle *netlink.Handle, hwAddr string) (netlink.Link, error) {
	links, err := netHandle.LinkList()
	if err != nil {
		return nil, err
	}

	for _, link := range links {
		lAttrs := link.Attrs()
		if lAttrs == nil {
			continue
		}

		if lAttrs.HardwareAddr.String() == hwAddr {
			return link, nil
		}
	}

	return nil, fmt.Errorf("Could not find the link corresponding to HwAddr %q", hwAddr)
}

func setupInterfaces(netHandle *netlink.Handle, ifaces []hyper.NetIface) error {
	for _, iface := range ifaces {
		var link netlink.Link
		if iface.HwAddr != "" {
			agentLog.Infof("Get the interface from its MAC address %q", iface.HwAddr)

			// Find the interface link from its hardware address
			var err error
			link, err = findLinkFromHwAddr(netHandle, iface.HwAddr)
			if err != nil {
				return err
			}

			agentLog.Infof("Link found %+v", link)

			// Rename it
			if err := netHandle.LinkSetName(link, iface.Name); err != nil {
				return err
			}
		} else {
			agentLog.Infof("Get the interface from its name %s", iface.Name)

			// Find the interface link from its name
			var err error
			link, err = netHandle.LinkByName(iface.Name)
			if err != nil {
				return err
			}
		}

		for _, ipAddress := range iface.IPAddresses {
			// Add an IP address
			addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%s", ipAddress.IPAddr, ipAddress.NetMask))
			if err != nil {
				return fmt.Errorf("Could not parse the IP address %s: %v", ipAddress.IPAddr, err)
			}
			if err := netHandle.AddrAdd(link, addr); err != nil {
				return err
			}
		}

		// Set the link up
		if err := netHandle.LinkSetUp(link); err != nil {
			return err
		}
	}

	return nil
}

func setupRoutes(netHandle *netlink.Handle, routes []hyper.Route) error {
	for _, route := range routes {
		var dst *net.IPNet
		var err error

		if route.Dest != "" && route.Dest != "default" {
			_, dst, err = net.ParseCIDR(route.Dest)
			if err != nil {
				return fmt.Errorf("Could not parse route destination %s: %v", route.Dest, err)
			}
		}

		// Find link index from route's device name
		link, err := netHandle.LinkByName(route.Device)
		if err != nil {
			return fmt.Errorf("Could not find link from device name %s: %v", route.Device, err)
		}

		linkAttrs := link.Attrs()
		if linkAttrs == nil {
			return fmt.Errorf("Could not find link index for device %v", route.Device)
		}

		netRoute := &netlink.Route{
			LinkIndex: linkAttrs.Index,
			Dst:       dst,
			Src:       net.ParseIP(route.Src),
			Gw:        net.ParseIP(route.Gateway),
		}

		if err := netHandle.RouteReplace(netRoute); err != nil {
			return fmt.Errorf("Could not add/replace route dest(%s)/src(%s)/gw(%s)/dev(%s): %v", route.Dest, route.Src, route.Gateway, route.Device, err)
		}
	}

	return nil
}

func setupDNS(netHandle *netlink.Handle, dns []string) error {
	return nil
}

func (p *pod) setupNetwork() error {
	netHandle, err := netlink.NewHandle()
	if err != nil {
		return err
	}
	defer netHandle.Delete()

	if err := setupInterfaces(netHandle, p.network.Interfaces); err != nil {
		return fmt.Errorf("Could not setup network interfaces: %v", err)
	}

	if err := setupRoutes(netHandle, p.network.Routes); err != nil {
		return fmt.Errorf("Could not setup network routes: %v", err)
	}

	if err := setupDNS(netHandle, p.network.DNS); err != nil {
		return fmt.Errorf("Could not setup network DNS: %v", err)
	}

	return nil
}

func removeInterfaces(netHandle *netlink.Handle, ifaces []hyper.NetIface) error {
	for _, iface := range ifaces {
		// Find the interface by name
		link, err := netHandle.LinkByName(iface.Name)
		if err != nil {
			return err
		}

		// Set the link down
		if err := netHandle.LinkSetDown(link); err != nil {
			return err
		}

		for _, ipAddress := range iface.IPAddresses {
			// Remove the IP address
			addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%s", ipAddress.IPAddr, ipAddress.NetMask))
			if err != nil {
				return fmt.Errorf("Could not parse the IP address %s: %v", ipAddress.IPAddr, err)
			}
			if err := netHandle.AddrDel(link, addr); err != nil {
				return err
			}
		}
	}

	return nil
}

func removeRoutes(netHandle *netlink.Handle, routes []hyper.Route) error {
	for _, route := range routes {
		_, dst, err := net.ParseCIDR(route.Dest)
		if err != nil {
			return fmt.Errorf("Could not parse route destination %s: %v", route.Dest, err)
		}

		netRoute := &netlink.Route{
			Dst: dst,
			Src: net.ParseIP(route.Src),
			Gw:  net.ParseIP(route.Gateway),
		}

		if err := netHandle.RouteDel(netRoute); err != nil {
			return fmt.Errorf("Could not remove route dest(%s)/src(%s)/gw(%s)/dev(%s): %v", route.Dest, route.Src, route.Gateway, route.Device, err)
		}
	}

	return nil
}

func removeDNS(netHandle *netlink.Handle, dns []string) error {
	return nil
}

func (p *pod) removeNetwork() error {
	netHandle, err := netlink.NewHandle()
	if err != nil {
		return err
	}
	defer netHandle.Delete()

	if err := removeInterfaces(netHandle, p.network.Interfaces); err != nil {
		return fmt.Errorf("Could not remove network interfaces: %v", err)
	}

	if err := removeRoutes(netHandle, p.network.Routes); err != nil {
		return fmt.Errorf("Could not remove network routes: %v", err)
	}

	if err := removeDNS(netHandle, p.network.DNS); err != nil {
		return fmt.Errorf("Could not remove network DNS: %v", err)
	}

	return nil
}
<commit_msg>network: Set the link down before its configuration<commit_after>//
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package main

import (
	"fmt"
	"net"

	hyper "github.com/clearcontainers/agent/api"
	"github.com/vishvananda/netlink"
)

func findLinkFromHwAddr(netHandle *netlink.Handle, hwAddr string) (netlink.Link, error) {
	links, err := netHandle.LinkList()
	if err != nil {
		return nil, err
	}

	for _, link := range links {
		lAttrs := link.Attrs()
		if lAttrs == nil {
			continue
		}

		if lAttrs.HardwareAddr.String() == hwAddr {
			return link, nil
		}
	}

	return nil, fmt.Errorf("Could not find the link corresponding to HwAddr %q", hwAddr)
}

func setupInterface(netHandle *netlink.Handle, iface hyper.NetIface, link netlink.Link) error {
	lAttrs := link.Attrs()
	if lAttrs != nil && (lAttrs.Flags&net.FlagUp) == net.FlagUp {
		// The link is up, makes sure we get it down before
		// doing any modification.
		if err := netHandle.LinkSetDown(link); err != nil {
			return err
		}
	}

	// Rename the link
	if iface.Name != "" {
		if err := netHandle.LinkSetName(link, iface.Name); err != nil {
			return err
		}
	}

	// Set MTU
	if iface.MTU > 0 {
		if err := netHandle.LinkSetMTU(link, iface.MTU); err != nil {
			return err
		}
	}

	for _, ipAddress := range iface.IPAddresses {
		// Add an IP address
		addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%s", ipAddress.IPAddr, ipAddress.NetMask))
		if err != nil {
			return fmt.Errorf("Could not parse the IP address %s: %v", ipAddress.IPAddr, err)
		}
		if err := netHandle.AddrAdd(link, addr); err != nil {
			return err
		}
	}

	// Set the link up
	return netHandle.LinkSetUp(link)
}

func setupInterfaces(netHandle *netlink.Handle, ifaces []hyper.NetIface) error {
	for _, iface := range ifaces {
		var link netlink.Link
		if iface.HwAddr != "" {
			agentLog.Infof("Get the interface from its MAC address %q", iface.HwAddr)

			// Find the interface link from its hardware address
			var err error
			link, err = findLinkFromHwAddr(netHandle, iface.HwAddr)
			if err != nil {
				return err
			}
		} else if iface.Name != "" {
			agentLog.Infof("Get the interface from its name %s", iface.Name)

			// Find the interface link from its name
			var err error
			link, err = netHandle.LinkByName(iface.Name)
			if err != nil {
				return err
			}
		} else {
			return fmt.Errorf("Interface HwAddr and Name are both empty")
		}

		agentLog.Infof("Link found %+v", link)

		if err := setupInterface(netHandle, iface, link); err != nil {
			return err
		}
	}

	return nil
}

func setupRoutes(netHandle *netlink.Handle, routes []hyper.Route) error {
	for _, route := range routes {
		var dst *net.IPNet
		var err error

		if route.Dest != "" && route.Dest != "default" {
			_, dst, err = net.ParseCIDR(route.Dest)
			if err != nil {
				return fmt.Errorf("Could not parse route destination %s: %v", route.Dest, err)
			}
		}

		// Find link index from route's device name
		link, err := netHandle.LinkByName(route.Device)
		if err != nil {
			return fmt.Errorf("Could not find link from device name %s: %v", route.Device, err)
		}

		linkAttrs := link.Attrs()
		if linkAttrs == nil {
			return fmt.Errorf("Could not find link index for device %v", route.Device)
		}

		netRoute := &netlink.Route{
			LinkIndex: linkAttrs.Index,
			Dst:       dst,
			Src:       net.ParseIP(route.Src),
			Gw:        net.ParseIP(route.Gateway),
		}

		if err := netHandle.RouteReplace(netRoute); err != nil {
			return fmt.Errorf("Could not add/replace route dest(%s)/src(%s)/gw(%s)/dev(%s): %v", route.Dest, route.Src, route.Gateway, route.Device, err)
		}
	}

	return nil
}

func setupDNS(netHandle *netlink.Handle, dns []string) error {
	return nil
}

func (p *pod) setupNetwork() error {
	netHandle, err := netlink.NewHandle()
	if err != nil {
		return err
	}
	defer netHandle.Delete()

	if err := setupInterfaces(netHandle, p.network.Interfaces); err != nil {
		return fmt.Errorf("Could not setup network interfaces: %v", err)
	}

	if err := setupRoutes(netHandle, p.network.Routes); err != nil {
		return fmt.Errorf("Could not setup network routes: %v", err)
	}

	if err := setupDNS(netHandle, p.network.DNS); err != nil {
		return fmt.Errorf("Could not setup network DNS: %v", err)
	}

	return nil
}

func removeInterfaces(netHandle *netlink.Handle, ifaces []hyper.NetIface) error {
	for _, iface := range ifaces {
		// Find the interface by name
		link, err := netHandle.LinkByName(iface.Name)
		if err != nil {
			return err
		}

		// Set the link down
		if err := netHandle.LinkSetDown(link); err != nil {
			return err
		}

		for _, ipAddress := range iface.IPAddresses {
			// Remove the IP address
			addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%s", ipAddress.IPAddr, ipAddress.NetMask))
			if err != nil {
				return fmt.Errorf("Could not parse the IP address %s: %v", ipAddress.IPAddr, err)
			}
			if err := netHandle.AddrDel(link, addr); err != nil {
				return err
			}
		}
	}

	return nil
}

func removeRoutes(netHandle *netlink.Handle, routes []hyper.Route) error {
	for _, route := range routes {
		_, dst, err := net.ParseCIDR(route.Dest)
		if err != nil {
			return fmt.Errorf("Could not parse route destination %s: %v", route.Dest, err)
		}

		netRoute := &netlink.Route{
			Dst: dst,
			Src: net.ParseIP(route.Src),
			Gw:  net.ParseIP(route.Gateway),
		}

		if err := netHandle.RouteDel(netRoute); err != nil {
			return fmt.Errorf("Could not remove route dest(%s)/src(%s)/gw(%s)/dev(%s): %v", route.Dest, route.Src, route.Gateway, route.Device, err)
		}
	}

	return nil
}

func removeDNS(netHandle *netlink.Handle, dns []string) error {
	return nil
}

func (p *pod) removeNetwork() error {
	netHandle, err := netlink.NewHandle()
	if err != nil {
		return err
	}
	defer netHandle.Delete()

	if err := removeInterfaces(netHandle, p.network.Interfaces); err != nil {
		return fmt.Errorf("Could not remove network interfaces: %v", err)
	}

	if err := removeRoutes(netHandle, p.network.Routes); err != nil {
		return fmt.Errorf("Could not remove network routes: %v", err)
	}

	if err := removeDNS(netHandle, p.network.DNS); err != nil {
		return fmt.Errorf("Could not remove network DNS: %v", err)
	}

	return nil
}
<|endoftext|>


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

// Command client performs authenticated requests against an Endpoints API server.
package main

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/oauth2/google"
	"golang.org/x/oauth2/jws"
)

var (
	host                = flag.String("host", "", "The API host. Required.")
	audience            = flag.String("audience", "", "The audience for the JWT. equired")
	serviceAccountFile  = flag.String("service-account-file", "", "Path to service account JSON file. Required.")
	serviceAccountEmail = flag.String("service-account-email", "", "Path email associated with the service account. Required.")
)

func main() {
	flag.Parse()

	if *audience == "" || *host == "" || *serviceAccountFile == "" || *serviceAccountEmail == "" {
		fmt.Println("requires: --host, --audience, --service-account-file, --service-account-email")
		os.Exit(1)
	}
	jwt, err := generateJWT(*serviceAccountFile, *serviceAccountEmail, *audience, 3600)
	if err != nil {
		log.Fatal(err)
	}
	resp, err := makeJWTRequest(jwt, *host)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s Response: %s", *host, resp)
}

// [START endpoints_generate_jwt_sa]

// generateJWT creates a signed JSON Web Token using a Google API Service Account.
func generateJWT(saKeyfile, saEmail, audience string, expiryLength int64) (string, error) {
	now := time.Now().Unix()

	// Build the JWT payload.
	jwt := &jws.ClaimSet{
		Iat: now,
		// expires after 'expiraryLength' seconds.
		Exp: now + expiryLength,
		// Iss must match 'issuer' in the security configuration in your
		// swagger spec (e.g. service account email). It can be any string.
		Iss: saEmail,
		// Aud must be either your Endpoints service name, or match the value
		// specified as the 'x-google-audience' in the OpenAPI document.
		Aud: audience,
		// Sub and Email should match the service account's email address.
		Sub:           saEmail,
		PrivateClaims: map[string]interface{}{"email": saEmail},
	}
	jwsHeader := &jws.Header{
		Algorithm: "RS256",
		Typ:       "JWT",
	}

	// Extract the RSA private key from the service account keyfile.
	sa, err := ioutil.ReadFile(saKeyfile)
	if err != nil {
		return "", fmt.Errorf("Could not read service account file: %v", err)
	}
	conf, err := google.JWTConfigFromJSON(sa)
	if err != nil {
		return "", fmt.Errorf("Could not parse service account JSON: %v", err)
	}
	block, _ := pem.Decode(conf.PrivateKey)
	parsedKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return "", fmt.Errorf("private key parse error: %v", err)
	}
	rsaKey, ok := parsedKey.(*rsa.PrivateKey)
	// Sign the JWT with the service account's private key.
	if !ok {
		return "", errors.New("private key failed rsa.PrivateKey type assertion")
	}
	return jws.Encode(jwsHeader, jwt, rsaKey)
}

// [END endpoints_generate_jwt_sa]

// [START endpoints_jwt_request]

// makeJWTRequest sends an authorized request to your deployed endpoint.
func makeJWTRequest(signedJWT, url string) (string, error) {
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", fmt.Errorf("failed to create HTTP request: %v", err)
	}
	req.Header.Add("Authorization", "Bearer "+signedJWT)
	req.Header.Add("content-type", "application/json")

	response, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("HTTP request failed: %v", err)
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", fmt.Errorf("failed to parse HTTP response: %v", err)
	}
	return string(responseData), nil
}

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

// Command client performs authenticated requests against an Endpoints API server.
package main

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/oauth2/google"
	"golang.org/x/oauth2/jws"
)

var (
	host                = flag.String("host", "", "The API host. Required.")
	audience            = flag.String("audience", "", "The audience for the JWT. equired")
	serviceAccountFile  = flag.String("service-account-file", "", "Path to service account JSON file. Required.")
	serviceAccountEmail = flag.String("service-account-email", "", "Path email associated with the service account. Required.")
)

func main() {
	flag.Parse()

	if *audience == "" || *host == "" || *serviceAccountFile == "" || *serviceAccountEmail == "" {
		fmt.Println("requires: --host, --audience, --service-account-file, --service-account-email")
		os.Exit(1)
	}
	jwt, err := generateJWT(*serviceAccountFile, *serviceAccountEmail, *audience, 3600)
	if err != nil {
		log.Fatal(err)
	}
	resp, err := makeJWTRequest(jwt, *host)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s Response: %s", *host, resp)
}

// [START endpoints_generate_jwt_sa]

// generateJWT creates a signed JSON Web Token using a Google API Service Account.
func generateJWT(saKeyfile, saEmail, audience string, expiryLength int64) (string, error) {
	now := time.Now().Unix()

	// Build the JWT payload.
	jwt := &jws.ClaimSet{
		Iat: now,
		// expires after 'expiryLength' seconds.
		Exp: now + expiryLength,
		// Iss must match 'issuer' in the security configuration in your
		// swagger spec (e.g. service account email). It can be any string.
		Iss: saEmail,
		// Aud must be either your Endpoints service name, or match the value
		// specified as the 'x-google-audience' in the OpenAPI document.
		Aud: audience,
		// Sub and Email should match the service account's email address.
		Sub:           saEmail,
		PrivateClaims: map[string]interface{}{"email": saEmail},
	}
	jwsHeader := &jws.Header{
		Algorithm: "RS256",
		Typ:       "JWT",
	}

	// Extract the RSA private key from the service account keyfile.
	sa, err := ioutil.ReadFile(saKeyfile)
	if err != nil {
		return "", fmt.Errorf("Could not read service account file: %v", err)
	}
	conf, err := google.JWTConfigFromJSON(sa)
	if err != nil {
		return "", fmt.Errorf("Could not parse service account JSON: %v", err)
	}
	block, _ := pem.Decode(conf.PrivateKey)
	parsedKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return "", fmt.Errorf("private key parse error: %v", err)
	}
	rsaKey, ok := parsedKey.(*rsa.PrivateKey)
	// Sign the JWT with the service account's private key.
	if !ok {
		return "", errors.New("private key failed rsa.PrivateKey type assertion")
	}
	return jws.Encode(jwsHeader, jwt, rsaKey)
}

// [END endpoints_generate_jwt_sa]

// [START endpoints_jwt_request]

// makeJWTRequest sends an authorized request to your deployed endpoint.
func makeJWTRequest(signedJWT, url string) (string, error) {
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", fmt.Errorf("failed to create HTTP request: %v", err)
	}
	req.Header.Add("Authorization", "Bearer "+signedJWT)
	req.Header.Add("content-type", "application/json")

	response, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("HTTP request failed: %v", err)
	}
	defer response.Body.Close()
	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", fmt.Errorf("failed to parse HTTP response: %v", err)
	}
	return string(responseData), nil
}

// [END endpoints_jwt_request]
<|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 LICENSE file.

package math

// The original C code, the long comment, and the constants
// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
// available from http://www.netlib.org/cephes/cmath.tgz.
// The go code is a simplified version of the original C.
//      tanh.c
//
//      Hyperbolic tangent
//
// SYNOPSIS:
//
// double x, y, tanh();
//
// y = tanh( x );
//
// DESCRIPTION:
//
// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
//      MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
//      MINLOG = -8.872283911167299960540e+01 = log(2**-128)
//
// A rational function is used for |x| < 0.625.  The form
// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
// Otherwise,
//      tanh(x) = sinh(x)/cosh(x) = 1  -  2/(exp(2x) + 1).
//
// ACCURACY:
//
//                      Relative error:
// arithmetic   domain     # trials      peak         rms
//    IEEE      -2,2        30000       2.5e-16     5.8e-17
//
// Cephes Math Library Release 2.8:  June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
//    Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
//   The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
//   Stephen L. Moshier
//   moshier@na-net.ornl.gov
//

var tanhP = [...]float64{
	-9.64399179425052238628E-1,
	-9.92877231001918586564E1,
	-1.61468768441708447952E3,
}
var tanhQ = [...]float64{
	1.12811678491632931402E2,
	2.23548839060100448583E3,
	4.84406305325125486048E3,
}

// Tanh computes the hyperbolic tangent of x.
//
// Special cases are:
//	Tanh(±0) = ±0
//	Tanh(±Inf) = ±1
//	Tanh(NaN) = NaN
func Tanh(x float64) float64 {
	const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
	z := Abs(x)
	switch {
	case z > 0.5*MAXLOG:
		if x < 0 {
			return -1
		}
		return 1
	case z >= 0.625:
		s := Exp(2 * z)
		z = 1 - 2/(s+1)
		if x < 0 {
			z = -z
		}
	default:
		if x == 0 {
			return x
		}
		s := x * x
		z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
	}
	return z
}
<commit_msg>math: modify a comment to the convention format.<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 LICENSE file.

package math

// The original C code, the long comment, and the constants
// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
// available from http://www.netlib.org/cephes/cmath.tgz.
// The go code is a simplified version of the original C.
//      tanh.c
//
//      Hyperbolic tangent
//
// SYNOPSIS:
//
// double x, y, tanh();
//
// y = tanh( x );
//
// DESCRIPTION:
//
// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
//      MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
//      MINLOG = -8.872283911167299960540e+01 = log(2**-128)
//
// A rational function is used for |x| < 0.625.  The form
// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
// Otherwise,
//      tanh(x) = sinh(x)/cosh(x) = 1  -  2/(exp(2x) + 1).
//
// ACCURACY:
//
//                      Relative error:
// arithmetic   domain     # trials      peak         rms
//    IEEE      -2,2        30000       2.5e-16     5.8e-17
//
// Cephes Math Library Release 2.8:  June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
//    Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
//   The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
//   Stephen L. Moshier
//   moshier@na-net.ornl.gov
//

var tanhP = [...]float64{
	-9.64399179425052238628E-1,
	-9.92877231001918586564E1,
	-1.61468768441708447952E3,
}
var tanhQ = [...]float64{
	1.12811678491632931402E2,
	2.23548839060100448583E3,
	4.84406305325125486048E3,
}

// Tanh returns the hyperbolic tangent of x.
//
// Special cases are:
//	Tanh(±0) = ±0
//	Tanh(±Inf) = ±1
//	Tanh(NaN) = NaN
func Tanh(x float64) float64 {
	const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
	z := Abs(x)
	switch {
	case z > 0.5*MAXLOG:
		if x < 0 {
			return -1
		}
		return 1
	case z >= 0.625:
		s := Exp(2 * z)
		z = 1 - 2/(s+1)
		if x < 0 {
			z = -z
		}
	default:
		if x == 0 {
			return x
		}
		s := x * x
		z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
	}
	return z
}
<|endoftext|>


<commit_before>package jsonmap

import (
	"encoding/json"
	"fmt"
	"math"
	"reflect"
	"regexp"
)

var uuidRegex = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)

type StringValidator struct {
	MinLen   int
	MaxLen   int
	RE       *regexp.Regexp
	REErrMsg string
}

func (v *StringValidator) ValidateString(s string) (string, error) {
	if len(s) < v.MinLen {
		return "", NewValidationError("too short, must be at least %d characters", v.MinLen)
	}

	if len(s) > v.MaxLen {
		return "", NewValidationError("too long, may not be more than %d characters", v.MaxLen)
	}

	if v.RE != nil && !v.RE.MatchString(s) {
		if v.REErrMsg != "" {
			return "", NewValidationError(v.REErrMsg)
		}

		return "", NewValidationError("must match regular expression: %s", v.RE.String())
	}
	return s, nil
}

func (v *StringValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}

	return v.ValidateString(s)
}

func (v *StringValidator) Regex(re *regexp.Regexp) *StringValidator {
	v.RE = re
	return v
}

func (v *StringValidator) RegexError(re *regexp.Regexp, errMsg string) *StringValidator {
	v.RE = re
	v.REErrMsg = errMsg
	return v
}

func String(minLen int, maxLen int) *StringValidator {
	return &StringValidator{
		MinLen: minLen,
		MaxLen: maxLen,
	}
}

type BooleanValidator struct{}

func (v *BooleanValidator) Validate(value interface{}) (interface{}, error) {
	b, ok := value.(bool)
	if !ok {
		return nil, NewValidationError("not a boolean")
	}
	return b, nil
}

func Boolean() Validator {
	return &BooleanValidator{}
}

// TODO: The spectrum of numeric types deserves more thought. Do we ship
// independent validators for each?
type IntegerValidator struct {
	MinVal int
	MaxVal int
}

func (v *IntegerValidator) Validate(value interface{}) (interface{}, error) {
	// Numeric values come in as a float64. This almost certainly has some weird
	// properties in extreme cases, but JSON probably isn't the right choice in
	// those cases.
	f, ok := value.(float64)
	if !ok || float64(int(f)) != f {
		return nil, NewValidationError("not an integer")
	}

	i := int(f)
	if i < v.MinVal {
		return nil, NewValidationError("too small, must be at least %d", v.MinVal)
	}

	if i > v.MaxVal {
		return nil, NewValidationError("too large, may not be larger than %d", v.MaxVal)
	}

	return i, nil
}

func Integer(minVal, maxVal int) Validator {
	return &IntegerValidator{
		MinVal: minVal,
		MaxVal: maxVal,
	}
}

type Uint32Validator struct {
	MinVal uint32
	MaxVal uint32
}

func (v *Uint32Validator) Validate(value interface{}) (interface{}, error) {
	// Numeric values come in as a float64. This almost certainly has some weird
	// properties in extreme cases, but JSON probably isn't the right choice in
	// those cases.
	f, ok := value.(float64)
	if !ok || float64(uint32(f)) != f {
		return nil, NewValidationError("not a uint32")
	}

	i := uint32(f)
	if i < v.MinVal {
		return nil, NewValidationError("too small, must be at least %d", v.MinVal)
	}

	if i > v.MaxVal {
		return nil, NewValidationError("too large, may not be larger than %d", v.MaxVal)
	}

	return i, nil
}

func UnsignedInteger(minVal, maxVal uint32) Validator {
	return &Uint32Validator{
		MinVal: minVal,
		MaxVal: maxVal,
	}
}

type InterfaceValidator struct{}

func (v *InterfaceValidator) Validate(value interface{}) (interface{}, error) {
	return value, nil
}

func Interface() *InterfaceValidator {
	return &InterfaceValidator{}
}

type LossyUint64Validator struct {
	MinVal uint64
	MaxVal uint64
}

func (v *LossyUint64Validator) Validate(value interface{}) (interface{}, error) {
	f, ok := value.(float64)
	if !ok || float64(uint64(f)) != f {
		return nil, NewValidationError("not an integer")
	}

	i := uint64(f)
	if i < v.MinVal {
		return nil, NewValidationError("too small, must be at least %d", v.MinVal)
	}

	if i > v.MaxVal {
		return nil, NewValidationError("too large, may not be larger than %d", v.MaxVal)
	}

	return i, nil
}

func (v *LossyUint64Validator) Min(min uint64) {
	v.MinVal = min
}

func (v *LossyUint64Validator) Max(max uint64) {
	v.MaxVal = max
}

// Validate numbers as a uint64. In this process they will be stored as a
// float64, which can lead to a loss of precision as high as 1024(?).
func LossyUint64() *LossyUint64Validator {
	return &LossyUint64Validator{
		MinVal: 0,
		MaxVal: math.MaxUint64,
	}
}

type UUIDStringValidator struct{}

func (v *UUIDStringValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}

	return v.ValidateString(s)
}

func (v *UUIDStringValidator) ValidateString(value string) (string, error) {
	if !uuidRegex.MatchString(value) {
		return "", NewValidationError("not a valid UUID")
	}

	return value, nil
}

func UUIDString() *UUIDStringValidator {
	return &UUIDStringValidator{}
}

type StringsSliceMapper struct {
	StringValidator *StringValidator
}

// Used for StringsArray, which has a "V" field containing []string.
// Optionally can take a string validator to apply to each entry.
func NewStringsSliceMapper(sv *StringValidator) TypeMap {
	return &StringsSliceMapper{StringValidator: sv}
}

func (ss *StringsSliceMapper) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	var err error
	v := dstValue.FieldByName("V")

	underlying := v.Interface()
	if _, ok := underlying.([]string); !ok {
		panic("target field V for NewStringsSliceMapper is not a []string")
	}

	if partial == nil {
		v.Set(reflect.ValueOf([]string{}))
		return nil
	}

	data, ok := partial.([]interface{})
	if !ok {
		return NewValidationError("expected a list")
	}

	rv := make([]string, len(data))

	for i, dv := range data {
		s, ok := dv.(string)
		if !ok {
			return fmt.Errorf("Error converting %#v to string", dv)
		}

		if ss.StringValidator != nil {
			s, err = ss.StringValidator.ValidateString(s)
			if err != nil {
				return err
			}
		}

		rv[i] = s
	}

	v.Set(reflect.ValueOf(rv))

	return nil
}

func (s *StringsSliceMapper) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	v := src.FieldByName("V")

	data, err := json.Marshal(v.Interface())
	if err != nil {
		return nil, err
	}

	return RawMessage{data}, nil
}

type EnumeratedValuesValidator struct {
	AllowedSlice  []string
	AllowedValues map[string]struct{}
}

func (v *EnumeratedValuesValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}
	_, ok = v.AllowedValues[s]

	if !ok {
		serialized, err := json.Marshal(v.AllowedSlice)
		if err != nil {
			// AllowedSlice should be a static value provided by the programmer,
			// so an error serializing it definitely represents a progrramming error.
			panic(err)
		}

		// If we want to use the invalid string value for error messages, return the string value instead of nil and in
		// the calling function, check if the return value is valid instead of checking if an error was returned, when
		// setting that value in the dest object (this valid check would handle if the input value is not a string)
		// return s, NewValidationError("Value must be one of: %s", string(serialized))
		return nil, NewValidationError("Value must be one of: %s", string(serialized))
	}

	return value, nil
}

func OneOf(allowed ...string) Validator {
	v := &EnumeratedValuesValidator{
		AllowedSlice:  allowed,
		AllowedValues: map[string]struct{}{},
	}

	for _, value := range allowed {
		v.AllowedValues[value] = struct{}{}
	}

	return v
}

func KeyFromVariableTypeMap(m map[string]TypeMap) Validator {
	keys := make([]string, 0, len(m))

	for key := range m {
		keys = append(keys, key)
	}

	return OneOf(keys...)
}
<commit_msg>integer uses int64 and remove unused unsigned integer<commit_after>package jsonmap

import (
	"encoding/json"
	"fmt"
	"math"
	"reflect"
	"regexp"
)

var uuidRegex = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)

type StringValidator struct {
	MinLen   int
	MaxLen   int
	RE       *regexp.Regexp
	REErrMsg string
}

func (v *StringValidator) ValidateString(s string) (string, error) {
	if len(s) < v.MinLen {
		return "", NewValidationError("too short, must be at least %d characters", v.MinLen)
	}

	if len(s) > v.MaxLen {
		return "", NewValidationError("too long, may not be more than %d characters", v.MaxLen)
	}

	if v.RE != nil && !v.RE.MatchString(s) {
		if v.REErrMsg != "" {
			return "", NewValidationError(v.REErrMsg)
		}

		return "", NewValidationError("must match regular expression: %s", v.RE.String())
	}
	return s, nil
}

func (v *StringValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}

	return v.ValidateString(s)
}

func (v *StringValidator) Regex(re *regexp.Regexp) *StringValidator {
	v.RE = re
	return v
}

func (v *StringValidator) RegexError(re *regexp.Regexp, errMsg string) *StringValidator {
	v.RE = re
	v.REErrMsg = errMsg
	return v
}

func String(minLen int, maxLen int) *StringValidator {
	return &StringValidator{
		MinLen: minLen,
		MaxLen: maxLen,
	}
}

type BooleanValidator struct{}

func (v *BooleanValidator) Validate(value interface{}) (interface{}, error) {
	b, ok := value.(bool)
	if !ok {
		return nil, NewValidationError("not a boolean")
	}
	return b, nil
}

func Boolean() Validator {
	return &BooleanValidator{}
}

// TODO: The spectrum of numeric types deserves more thought. Do we ship
// independent validators for each?
type IntegerValidator struct {
	MinVal int64
	MaxVal int64
}

func (v *IntegerValidator) Validate(value interface{}) (interface{}, error) {
	// Numeric values come in as a float64. This almost certainly has some weird
	// properties in extreme cases, but JSON probably isn't the right choice in
	// those cases.
	f, ok := value.(float64)
	if !ok || float64(int64(f)) != f {
		return nil, NewValidationError("not an integer")
	}

	i := int64(f)
	if i < v.MinVal {
		return nil, NewValidationError("too small, must be at least %d", v.MinVal)
	}

	if i > v.MaxVal {
		return nil, NewValidationError("too large, may not be larger than %d", v.MaxVal)
	}

	return i, nil
}

func Integer(minVal, maxVal int64) Validator {
	return &IntegerValidator{
		MinVal: minVal,
		MaxVal: maxVal,
	}
}

type InterfaceValidator struct{}

func (v *InterfaceValidator) Validate(value interface{}) (interface{}, error) {
	return value, nil
}

func Interface() *InterfaceValidator {
	return &InterfaceValidator{}
}

type LossyUint64Validator struct {
	MinVal uint64
	MaxVal uint64
}

func (v *LossyUint64Validator) Validate(value interface{}) (interface{}, error) {
	f, ok := value.(float64)
	if !ok || float64(uint64(f)) != f {
		return nil, NewValidationError("not an integer")
	}

	i := uint64(f)
	if i < v.MinVal {
		return nil, NewValidationError("too small, must be at least %d", v.MinVal)
	}

	if i > v.MaxVal {
		return nil, NewValidationError("too large, may not be larger than %d", v.MaxVal)
	}

	return i, nil
}

func (v *LossyUint64Validator) Min(min uint64) {
	v.MinVal = min
}

func (v *LossyUint64Validator) Max(max uint64) {
	v.MaxVal = max
}

// Validate numbers as a uint64. In this process they will be stored as a
// float64, which can lead to a loss of precision as high as 1024(?).
func LossyUint64() *LossyUint64Validator {
	return &LossyUint64Validator{
		MinVal: 0,
		MaxVal: math.MaxUint64,
	}
}

type UUIDStringValidator struct{}

func (v *UUIDStringValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}

	return v.ValidateString(s)
}

func (v *UUIDStringValidator) ValidateString(value string) (string, error) {
	if !uuidRegex.MatchString(value) {
		return "", NewValidationError("not a valid UUID")
	}

	return value, nil
}

func UUIDString() *UUIDStringValidator {
	return &UUIDStringValidator{}
}

type StringsSliceMapper struct {
	StringValidator *StringValidator
}

// Used for StringsArray, which has a "V" field containing []string.
// Optionally can take a string validator to apply to each entry.
func NewStringsSliceMapper(sv *StringValidator) TypeMap {
	return &StringsSliceMapper{StringValidator: sv}
}

func (ss *StringsSliceMapper) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	var err error
	v := dstValue.FieldByName("V")

	underlying := v.Interface()
	if _, ok := underlying.([]string); !ok {
		panic("target field V for NewStringsSliceMapper is not a []string")
	}

	if partial == nil {
		v.Set(reflect.ValueOf([]string{}))
		return nil
	}

	data, ok := partial.([]interface{})
	if !ok {
		return NewValidationError("expected a list")
	}

	rv := make([]string, len(data))

	for i, dv := range data {
		s, ok := dv.(string)
		if !ok {
			return fmt.Errorf("Error converting %#v to string", dv)
		}

		if ss.StringValidator != nil {
			s, err = ss.StringValidator.ValidateString(s)
			if err != nil {
				return err
			}
		}

		rv[i] = s
	}

	v.Set(reflect.ValueOf(rv))

	return nil
}

func (s *StringsSliceMapper) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	v := src.FieldByName("V")

	data, err := json.Marshal(v.Interface())
	if err != nil {
		return nil, err
	}

	return RawMessage{data}, nil
}

type EnumeratedValuesValidator struct {
	AllowedSlice  []string
	AllowedValues map[string]struct{}
}

func (v *EnumeratedValuesValidator) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		return nil, NewValidationError("not a string")
	}
	_, ok = v.AllowedValues[s]

	if !ok {
		serialized, err := json.Marshal(v.AllowedSlice)
		if err != nil {
			// AllowedSlice should be a static value provided by the programmer,
			// so an error serializing it definitely represents a progrramming error.
			panic(err)
		}

		// If we want to use the invalid string value for error messages, return the string value instead of nil and in
		// the calling function, check if the return value is valid instead of checking if an error was returned, when
		// setting that value in the dest object (this valid check would handle if the input value is not a string)
		// return s, NewValidationError("Value must be one of: %s", string(serialized))
		return nil, NewValidationError("Value must be one of: %s", string(serialized))
	}

	return value, nil
}

func OneOf(allowed ...string) Validator {
	v := &EnumeratedValuesValidator{
		AllowedSlice:  allowed,
		AllowedValues: map[string]struct{}{},
	}

	for _, value := range allowed {
		v.AllowedValues[value] = struct{}{}
	}

	return v
}

func KeyFromVariableTypeMap(m map[string]TypeMap) Validator {
	keys := make([]string, 0, len(m))

	for key := range m {
		keys = append(keys, key)
	}

	return OneOf(keys...)
}
<|endoftext|>