commit 4bb4f6e0973bc5eb45bd2d348013fd827aec189e Author: ehlxr Date: Wed Aug 1 11:18:23 2018 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca3d917 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +vendor + +hc* +hex-convert +.idea +dist \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bcc17e1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2018 ehlxr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d9fa103 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +.PHONY: default init build install release dep get_deps clean build_amd64 build_386 upx + +# https://golang.org/doc/install/source#environment +GOOS := $(shell go2 env | awk -F= '$$1=="GOOS" {print $$2}' | awk -F '"' '{print $$2}') # 此处 awk 需使用两个 $ +GOARCH := $(shell go2 env | awk -F= '$$1=="GOARCH" {print $$2}' | awk -F '"' '{print $$2}') +OSS = darwin dragonfly freebsd linux netbsd openbsd plan9 solaris windows +PKG = +# ifeq ($(strip $(GOOS)), windows) +# GOARCH := $(strip $(GOARCH)).exe +# endif + +default: + @echo "hc info: please choose a target for 'make'" + @echo "available target: build install release clean build_amd64 build_386 upx" + +build: + @ go2 build -ldflags "-s -w" -o dist/hc_$(strip $(GOOS))_$(strip $(if \ + $(findstring windows,$(GOOS)),\ + $(strip $(GOARCH)).exe,\ + $(strip $(GOARCH))\ + )) + +install: + go2 install -ldflags "-s -w" + +release: build_amd64 build_386 upx + +clean: + go2 clean -i + rm -rf dist/hc* hc* hex-convert + +build_amd64: + @ $(foreach OS,\ + $(OSS),\ + $(shell CGO_ENABLED=0 GOOS=$(OS) GOARCH=amd64 go2 build -ldflags "-s -w" -o dist/hc_$(OS)_amd64$(if $(findstring windows,$(OS)),.exe))) + @ echo done + +build_386: + @ $(foreach OS,\ + $(OSS),\ + $(shell CGO_ENABLED=0 GOOS=$(OS) GOARCH=386 go2 build -ldflags "-s -w" -o dist/hc_$(OS)_386$(if $(findstring windows,$(OS)),.exe))) + @ echo done + +# 压缩。需要安装 https://github.com/upx/upx +upx: + upx $(if $(PKG),$(PKG),dist/hc*) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..33363c8 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# hex-convert + +``` +支持 76 位以内的任意进制相互转换 + +Usage: + hc [command] + +Available Commands: + b 转换为二进制 + d 转换为十进制 + h 转换为十六进制 + help Help about any command + o 转换为八进制 + server 启动 HTTP Server + +Flags: + -d, --data string 要转换数值 + -h, --help help for hc + -s, --scale int 要转换的进制 + -v, --version show version of the hc. +``` \ No newline at end of file diff --git a/assets/index.tpl b/assets/index.tpl new file mode 100644 index 0000000..7b60d60 --- /dev/null +++ b/assets/index.tpl @@ -0,0 +1,13 @@ +

转换十进制

+
+
+ + +
+ +

转换二进制

+
+
+ + +
\ No newline at end of file diff --git a/cmd/binary.go b/cmd/binary.go new file mode 100644 index 0000000..57a2796 --- /dev/null +++ b/cmd/binary.go @@ -0,0 +1,52 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/ehlxr/hex-convert/converter" + "github.com/spf13/cobra" +) + +// binaryCmd represents the binary command +var binaryCmd = &cobra.Command{ + Use: "b", + Short: "转换为二进制", + Long: `转换为二进制:包括 76 位以内的任意进制转换为二进制`, + Run: func(cmd *cobra.Command, args []string) { + scale, _ := strconv.Atoi(rootCmd.PersistentFlags().Lookup("scale").Value.String()) + data := rootCmd.LocalFlags().Lookup("data").Value.String() + + result, err := converter.ToBinary(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println(result) + }, +} + +func init() { + rootCmd.AddCommand(binaryCmd) +} diff --git a/cmd/decimal.go b/cmd/decimal.go new file mode 100644 index 0000000..1bef921 --- /dev/null +++ b/cmd/decimal.go @@ -0,0 +1,52 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/ehlxr/hex-convert/converter" + "github.com/spf13/cobra" +) + +// decimalCmd represents the decimal command +var decimalCmd = &cobra.Command{ + Use: "d", + Short: "转换为十进制", + Long: `转换为十进制:包括 76 位以内的任意进制转换为十进制`, + Run: func(cmd *cobra.Command, args []string) { + scale, _ := strconv.Atoi(rootCmd.PersistentFlags().Lookup("scale").Value.String()) + data := rootCmd.LocalFlags().Lookup("data").Value.String() + + result, err := converter.ToDecimal(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println(result) + }, +} + +func init() { + rootCmd.AddCommand(decimalCmd) +} diff --git a/cmd/hexadecimal.go b/cmd/hexadecimal.go new file mode 100644 index 0000000..2d5722a --- /dev/null +++ b/cmd/hexadecimal.go @@ -0,0 +1,53 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/ehlxr/hex-convert/converter" + + "github.com/spf13/cobra" +) + +// hexadecimalCmd represents the hexadecimal command +var hexadecimalCmd = &cobra.Command{ + Use: "h", + Short: "转换为十六进制", + Long: `转换为十六进制:包括 76 位以内的任意进制转换为十六进制`, + Run: func(cmd *cobra.Command, args []string) { + scale, _ := strconv.Atoi(rootCmd.PersistentFlags().Lookup("scale").Value.String()) + data := rootCmd.LocalFlags().Lookup("data").Value.String() + + result, err := converter.ToHex(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println(result) + }, +} + +func init() { + rootCmd.AddCommand(hexadecimalCmd) +} diff --git a/cmd/octal.go b/cmd/octal.go new file mode 100644 index 0000000..ba75695 --- /dev/null +++ b/cmd/octal.go @@ -0,0 +1,52 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/ehlxr/hex-convert/converter" + "github.com/spf13/cobra" +) + +// octalCmd represents the octal command +var octalCmd = &cobra.Command{ + Use: "o", + Short: "转换为八进制", + Long: `转换为八进制:包括 76 位以内的任意进制转换为八进制`, + Run: func(cmd *cobra.Command, args []string) { + scale, _ := strconv.Atoi(rootCmd.PersistentFlags().Lookup("scale").Value.String()) + data := rootCmd.LocalFlags().Lookup("data").Value.String() + + result, err := converter.ToOctal(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println(result) + }, +} + +func init() { + rootCmd.AddCommand(octalCmd) +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..b1fe9b3 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,83 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + + "github.com/ehlxr/hex-convert/metadata" + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var cfgFile string + +var rootCmd = &cobra.Command{ + Use: "hc", + Short: "进制转换", + Long: `支持 76 位以内的任意进制相互转换`, + Version: metadata.VERSION, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + + rootCmd.Flags().BoolP("version", "v", false, "show version of the hc.") + rootCmd.PersistentFlags().IntP("scale", "s", 0, "要转换的进制") + rootCmd.PersistentFlags().StringP("data", "d", "", "要转换数值") +} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".hex-convert" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".hex-convert") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 0000000..6ba5778 --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,54 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/ehlxr/hex-convert/server" + "github.com/spf13/cobra" +) + +// serverCmd represents the server command +var serverCmd = &cobra.Command{ + Use: "server", + Short: "启动 HTTP Server", + Long: ` +启动一个简单的 http server 用于提供页面访问`, + Run: func(cmd *cobra.Command, args []string) { + + host := cmd.LocalFlags().Lookup("host").Value.String() + port, _ := strconv.Atoi(cmd.LocalFlags().Lookup("port").Value.String()) + + if err := server.Start(host, port); err != nil { + fmt.Println(err) + os.Exit(1) + } + }, +} + +func init() { + rootCmd.AddCommand(serverCmd) + serverCmd.Flags().IntP("port", "p", 8080, "bind port of the server.") + serverCmd.Flags().StringP("host", "a", "0.0.0.0", "bind TCP address of the server.") +} diff --git a/converter/converter.go b/converter/converter.go new file mode 100644 index 0000000..353e530 --- /dev/null +++ b/converter/converter.go @@ -0,0 +1,100 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package converter + +import ( + "math" + "strconv" + "strings" + + "github.com/ehlxr/hex-convert/metadata" +) + +func ToDecimal(scale int, data string) (int, error) { + var new_num float64 + new_num = 0.0 + nNum := len(strings.Split(data, "")) - 1 + for _, value := range strings.Split(data, "") { + tmp := float64(findkey(value)) + if tmp != -1 { + new_num = new_num + tmp*math.Pow(float64(scale), float64(nNum)) + nNum = nNum - 1 + } else { + break + } + } + return int(new_num), nil +} + +func ToBinary(scale int, data string) (string, error) { + result, err := ToDecimal(scale, data) + if err != nil { + return "", err + } + + return fromDecimal(2, result) +} + +func ToHex(scale int, data string) (string, error) { + result, err := ToDecimal(scale, data) + if err != nil { + return "", err + } + + return fromDecimal(16, result) +} + +func ToOctal(scale int, data string) (string, error) { + result, err := ToDecimal(scale, data) + if err != nil { + return "", err + } + + return fromDecimal(8, result) +} + +func findkey(in string) int { + result := -1 + for k, v := range metadata.TEN_TO_ANY { + if in == v { + result = k + } + } + return result +} + +func fromDecimal(scale, data int) (string, error) { + new_num_str := "" + var remainder int + var remainder_string string + for data != 0 { + remainder = data % scale + if 76 > remainder && remainder > 9 { + remainder_string = metadata.TEN_TO_ANY[remainder] + } else { + remainder_string = strconv.Itoa(remainder) + } + new_num_str = remainder_string + new_num_str + data = data / scale + } + + return new_num_str, nil +} diff --git a/gen/assets_generate.go b/gen/assets_generate.go new file mode 100644 index 0000000..f2da43d --- /dev/null +++ b/gen/assets_generate.go @@ -0,0 +1,44 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +build ignore +//go:generate go run assets_generate.go + +package main + +import ( + "log" + "net/http" + + "github.com/shurcooL/vfsgen" +) + +func main() { + var fs http.FileSystem = http.Dir("../assets") + + err := vfsgen.Generate(fs, vfsgen.Options{ + Filename: "assets_vfsdata.go", + PackageName: "gen", + VariableName: "Assets", + }) + if err != nil { + log.Fatalln(err) + } +} diff --git a/gen/assets_vfsdata.go b/gen/assets_vfsdata.go new file mode 100644 index 0000000..22487b1 --- /dev/null +++ b/gen/assets_vfsdata.go @@ -0,0 +1,184 @@ +// Code generated by vfsgen; DO NOT EDIT. + +package gen + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + pathpkg "path" + "time" +) + +// Assets statically implements the virtual filesystem provided to vfsgen. +var Assets = func() http.FileSystem { + fs := vfsgen۰FS{ + "/": &vfsgen۰DirInfo{ + name: "/", + modTime: time.Date(2018, 8, 2, 2, 1, 27, 751097893, time.UTC), + }, + "/index.tpl": &vfsgen۰CompressedFileInfo{ + name: "index.tpl", + modTime: time.Date(2018, 8, 2, 2, 1, 27, 751448710, time.UTC), + uncompressedSize: 563, + + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\xd0\xbd\x4e\xc3\x30\x10\x07\xf0\x3d\x4f\x71\xba\xa5\x20\xa1\x5a\xdd\x6d\x4f\x3c\x06\x8b\x93\x1c\x38\x22\xfe\x90\x7d\x46\x74\x83\x8d\x81\x8e\x9d\xd8\x98\x19\x3a\x31\x20\x10\x2f\x43\xa2\x3e\x06\x2a\x19\x22\x21\x10\x0f\xc0\x66\x59\xf7\xf1\xbf\x9f\xb4\x2b\xbd\x7f\x7b\x1a\x37\x8f\xc3\xe6\x76\xff\xfe\x30\xdc\x3d\x4b\x61\x57\xba\x92\xe7\x21\x39\x30\x0d\x77\xc1\x2b\x6c\x11\x1c\xb1\x0d\xad\xc2\x18\x32\xa3\xae\x00\x00\x64\xe7\x63\x61\xe0\x75\x24\x85\x4c\xd7\x8c\xe0\x8d\x23\x85\xb9\x31\x3d\x21\x04\x7f\x49\xeb\x12\x15\xb2\xed\xf2\xf2\xca\xf4\x85\xd4\xfc\x5c\x26\x8a\xbd\x69\xe8\x48\x9c\x9d\x8a\x8b\x93\xc5\xe2\x18\xe1\xeb\xc3\x86\xbe\xa5\xa4\x70\x8a\x33\x6e\x77\x28\xb4\xac\xd3\x1f\x3b\x5b\xc3\xe6\xdb\x80\x71\xbb\x1b\x6e\x5e\x51\xfc\xd0\x99\x4b\xed\x3a\x46\x98\x42\xe1\x44\x70\xa8\x94\xe2\x70\xb8\xae\xaa\x59\xe6\xe3\xe5\xfe\x77\x99\xfa\x7f\xc8\xc0\x4c\xf3\x19\x00\x00\xff\xff\xac\x32\x6c\x93\x33\x02\x00\x00"), + }, + } + fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ + fs["/index.tpl"].(os.FileInfo), + } + + return fs +}() + +type vfsgen۰FS map[string]interface{} + +func (fs vfsgen۰FS) Open(path string) (http.File, error) { + path = pathpkg.Clean("/" + path) + f, ok := fs[path] + if !ok { + return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist} + } + + switch f := f.(type) { + case *vfsgen۰CompressedFileInfo: + gr, err := gzip.NewReader(bytes.NewReader(f.compressedContent)) + if err != nil { + // This should never happen because we generate the gzip bytes such that they are always valid. + panic("unexpected error reading own gzip compressed bytes: " + err.Error()) + } + return &vfsgen۰CompressedFile{ + vfsgen۰CompressedFileInfo: f, + gr: gr, + }, nil + case *vfsgen۰DirInfo: + return &vfsgen۰Dir{ + vfsgen۰DirInfo: f, + }, nil + default: + // This should never happen because we generate only the above types. + panic(fmt.Sprintf("unexpected type %T", f)) + } +} + +// vfsgen۰CompressedFileInfo is a static definition of a gzip compressed file. +type vfsgen۰CompressedFileInfo struct { + name string + modTime time.Time + compressedContent []byte + uncompressedSize int64 +} + +func (f *vfsgen۰CompressedFileInfo) Readdir(count int) ([]os.FileInfo, error) { + return nil, fmt.Errorf("cannot Readdir from file %s", f.name) +} +func (f *vfsgen۰CompressedFileInfo) Stat() (os.FileInfo, error) { return f, nil } + +func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte { + return f.compressedContent +} + +func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name } +func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize } +func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 } +func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime } +func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false } +func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil } + +// vfsgen۰CompressedFile is an opened compressedFile instance. +type vfsgen۰CompressedFile struct { + *vfsgen۰CompressedFileInfo + gr *gzip.Reader + grPos int64 // Actual gr uncompressed position. + seekPos int64 // Seek uncompressed position. +} + +func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { + if f.grPos > f.seekPos { + // Rewind to beginning. + err = f.gr.Reset(bytes.NewReader(f.compressedContent)) + if err != nil { + return 0, err + } + f.grPos = 0 + } + if f.grPos < f.seekPos { + // Fast-forward. + _, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos) + if err != nil { + return 0, err + } + f.grPos = f.seekPos + } + n, err = f.gr.Read(p) + f.grPos += int64(n) + f.seekPos = f.grPos + return n, err +} +func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { + switch whence { + case io.SeekStart: + f.seekPos = 0 + offset + case io.SeekCurrent: + f.seekPos += offset + case io.SeekEnd: + f.seekPos = f.uncompressedSize + offset + default: + panic(fmt.Errorf("invalid whence value: %v", whence)) + } + return f.seekPos, nil +} +func (f *vfsgen۰CompressedFile) Close() error { + return f.gr.Close() +} + +// vfsgen۰DirInfo is a static definition of a directory. +type vfsgen۰DirInfo struct { + name string + modTime time.Time + entries []os.FileInfo +} + +func (d *vfsgen۰DirInfo) Read([]byte) (int, error) { + return 0, fmt.Errorf("cannot Read from directory %s", d.name) +} +func (d *vfsgen۰DirInfo) Close() error { return nil } +func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil } + +func (d *vfsgen۰DirInfo) Name() string { return d.name } +func (d *vfsgen۰DirInfo) Size() int64 { return 0 } +func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } +func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime } +func (d *vfsgen۰DirInfo) IsDir() bool { return true } +func (d *vfsgen۰DirInfo) Sys() interface{} { return nil } + +// vfsgen۰Dir is an opened dir instance. +type vfsgen۰Dir struct { + *vfsgen۰DirInfo + pos int // Position within entries for Seek and Readdir. +} + +func (d *vfsgen۰Dir) Seek(offset int64, whence int) (int64, error) { + if offset == 0 && whence == io.SeekStart { + d.pos = 0 + return 0, nil + } + return 0, fmt.Errorf("unsupported Seek in directory %s", d.name) +} + +func (d *vfsgen۰Dir) Readdir(count int) ([]os.FileInfo, error) { + if d.pos >= len(d.entries) && count > 0 { + return nil, io.EOF + } + if count <= 0 || count > len(d.entries)-d.pos { + count = len(d.entries) - d.pos + } + e := d.entries[d.pos : d.pos+count] + d.pos += count + return e, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c2a4217 --- /dev/null +++ b/go.mod @@ -0,0 +1,24 @@ +module github.com/ehlxr/hex-convert + +require ( + github.com/BurntSushi/toml v0.3.0 // indirect + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/fsnotify/fsnotify v1.4.7 // indirect + github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/magiconair/properties v1.8.0 // indirect + github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 + github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/afero v1.1.1 // indirect + github.com/spf13/cast v1.2.0 // indirect + github.com/spf13/cobra v0.0.3 + github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec // indirect + github.com/spf13/pflag v1.0.1 // indirect + github.com/spf13/viper v1.0.2 + github.com/stretchr/testify v1.2.2 // indirect + golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e // indirect + golang.org/x/text v0.3.0 // indirect + gopkg.in/yaml.v2 v2.2.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ce92fa5 --- /dev/null +++ b/go.sum @@ -0,0 +1,42 @@ +github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY= +github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 h1:Y94YB7jrsihrbGSqRNMwRWJ2/dCxr0hdC2oPRohkx0A= +github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699 h1:KXZJFdun9knAVAR8tg/aHJEr5DgtcbqyvzacK+CDCaI= +github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I= +github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= +github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e h1:3dQ4fR8k5KugjVKO0oqSd1odxuk2yaE2CIfxWP2WarQ= +golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go new file mode 100644 index 0000000..183e88c --- /dev/null +++ b/main.go @@ -0,0 +1,27 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package main // import "github.com/ehlxr/hex-convert" + +import "github.com/ehlxr/hex-convert/cmd" + +func main() { + cmd.Execute() +} diff --git a/metadata/metadata.go b/metadata/metadata.go new file mode 100644 index 0000000..d7a387c --- /dev/null +++ b/metadata/metadata.go @@ -0,0 +1,25 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package metadata + +const VERSION = "v0.0.1" + +var TEN_TO_ANY map[int]string = map[int]string{0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9", 10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f", 16: "g", 17: "h", 18: "i", 19: "j", 20: "k", 21: "l", 22: "m", 23: "n", 24: "o", 25: "p", 26: "q", 27: "r", 28: "s", 29: "t", 30: "u", 31: "v", 32: "w", 33: "x", 34: "y", 35: "z", 36: ":", 37: ";", 38: "<", 39: "=", 40: ">", 41: "?", 42: "@", 43: "[", 44: "]", 45: "^", 46: "_", 47: "{", 48: "|", 49: "}", 50: "A", 51: "B", 52: "C", 53: "D", 54: "E", 55: "F", 56: "G", 57: "H", 58: "I", 59: "J", 60: "K", 61: "L", 62: "M", 63: "N", 64: "O", 65: "P", 66: "Q", 67: "R", 68: "S", 69: "T", 70: "U", 71: "V", 72: "W", 73: "X", 74: "Y", 75: "Z"} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..4c980dd --- /dev/null +++ b/server/server.go @@ -0,0 +1,96 @@ +// Copyright © 2018 ehlxr +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package server + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strconv" + "strings" + + "github.com/ehlxr/hex-convert/gen" + + "github.com/ehlxr/hex-convert/converter" +) + +func decimal(w http.ResponseWriter, req *http.Request) { + scale, _ := strconv.Atoi(req.FormValue("scale")) + data := req.FormValue("data") + + result, err := converter.ToDecimal(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + log.Println(result) + fmt.Fprintf(w, "首页
%s", strconv.Itoa(result)) +} + +func binary(w http.ResponseWriter, req *http.Request) { + scale, _ := strconv.Atoi(req.FormValue("scale")) + data := req.FormValue("data") + + result, err := converter.ToBinary(scale, data) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + log.Println(result) + fmt.Fprintf(w, "首页
%s", result) +} + +func index(w http.ResponseWriter, r *http.Request) { + f, err := gen.Assets.Open("/index.tpl") + if err != nil { + log.Fatalln(err) + } + defer f.Close() + + fd, err := ioutil.ReadAll(f) + if err != nil { + panic(err) + } + + fmt.Fprintf(w, string(fd)) +} + +func Start(host string, port int) error { + http.HandleFunc("/", index) + http.HandleFunc("/d", decimal) + http.HandleFunc("/b", binary) + + addr := fmt.Sprintf("%s:%d", host, port) + if strings.Contains(addr, "0.0.0.0") { + addr = strings.Replace(addr, "0.0.0.0", "", 1) + host = strings.Replace(host, "0.0.0.0", "127.0.0.1", 1) + } + fmt.Printf("server start on: %s", fmt.Sprintf("http://%s:%d", host, port)) + + if err := http.ListenAndServe(addr, nil); err != nil { + return fmt.Errorf("ListenAndServe: : %v", err) + } + return nil +}