]> Cypherpunks.ru repositories - netstring.git/blobdiff - cmd/netstring/main.go
Refactoring, io.Reader/Writer friendliness, performance optimization
[netstring.git] / cmd / netstring / main.go
diff --git a/cmd/netstring/main.go b/cmd/netstring/main.go
new file mode 100644 (file)
index 0000000..306f46e
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+netstring -- netstring format serialization library
+Copyright (C) 2015-2020 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+       "flag"
+       "fmt"
+       "io"
+       "os"
+       "strconv"
+
+       "go.cypherpunks.ru/netstring/v2"
+)
+
+func usage() {
+       fmt.Fprintf(os.Stderr, "ns -- Work with netstring encoded files\n\n")
+       fmt.Fprintf(os.Stderr, "Usage: %s list FILE\n", os.Args[0])
+       fmt.Fprintf(os.Stderr, "       %s read FILE CHUNK > data\n", os.Args[0])
+       fmt.Fprintf(os.Stderr, "       %s write FILE ... > data\n", os.Args[0])
+       os.Exit(1)
+}
+
+func main() {
+       flag.Usage = usage
+       flag.Parse()
+       if len(os.Args) < 3 {
+               usage()
+       }
+       switch os.Args[1] {
+       case "list":
+               fd, err := os.Open(os.Args[2])
+               if err != nil {
+                       panic(err)
+               }
+               r := netstring.NewReader(fd)
+               for i := 0; ; i++ {
+                       size, err := r.Next()
+                       if err == io.EOF {
+                               break
+                       }
+                       if err != nil {
+                               panic(err)
+                       }
+                       fmt.Printf("%d\t%d\n", i, size)
+                       r.Discard()
+               }
+       case "read":
+               if len(os.Args) != 4 {
+                       usage()
+               }
+               chunk, err := strconv.Atoi(os.Args[3])
+               if err != nil {
+                       panic(err)
+               }
+               fd, err := os.Open(os.Args[2])
+               if err != nil {
+                       panic(err)
+               }
+               r := netstring.NewReader(fd)
+               for i := 0; i < chunk; i++ {
+                       _, err = r.Next()
+                       if err != nil {
+                               panic(err)
+                       }
+                       r.Discard()
+               }
+               _, err = r.Next()
+               if err != nil {
+                       panic(err)
+               }
+               if _, err = io.Copy(os.Stdout, r); err != nil {
+                       panic(err)
+               }
+       case "write":
+               w := netstring.NewWriter(os.Stdout)
+               for i, fn := range os.Args[2:] {
+                       fd, err := os.Open(fn)
+                       if err != nil {
+                               panic(err)
+                       }
+                       fi, err := fd.Stat()
+                       if err != nil {
+                               panic(err)
+                       }
+                       size := uint64(fi.Size())
+                       if _, err = w.WriteSize(size); err != nil {
+                               panic(err)
+                       }
+                       if _, err = io.Copy(w, fd); err != nil {
+                               panic(err)
+                       }
+                       fmt.Fprintf(os.Stderr, "%d\t%d\t%s\n", i, size, fn)
+               }
+       }
+}