From 1a90fe806d0127f7d089e74c733fdf289344ccc0 Mon Sep 17 00:00:00 2001 From: mpl Date: Mon, 8 Feb 2016 21:29:48 +0100 Subject: [PATCH] vendor: update go4.org rev 40a0492aa096a3be30c750c4e2216de52a6cf2e3 adds writerutil package Change-Id: Ia771e38283afb9750a8dad0cd462ca12ce42dd15 --- vendor/go4.org/writerutil/writerutil.go | 105 +++++++++++++++++++ vendor/go4.org/writerutil/writerutil_test.go | 73 +++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 vendor/go4.org/writerutil/writerutil.go create mode 100644 vendor/go4.org/writerutil/writerutil_test.go diff --git a/vendor/go4.org/writerutil/writerutil.go b/vendor/go4.org/writerutil/writerutil.go new file mode 100644 index 000000000..5c209cc67 --- /dev/null +++ b/vendor/go4.org/writerutil/writerutil.go @@ -0,0 +1,105 @@ +/* +Copyright 2016 The go4 Authors + +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 writerutil contains io.Writer types. +package writerutil // import "go4.org/writerutil" + +import ( + "bytes" + "strconv" +) + +// PrefixSuffixSaver is an io.Writer which retains the first N bytes +// and the last N bytes written to it. The Bytes method reconstructs +// it with a pretty error message. +// It is copied from os/exec/exec.go of the Go stdlib. +type PrefixSuffixSaver struct { + N int // max size of prefix or suffix + prefix []byte + suffix []byte // ring buffer once len(suffix) == N + suffixOff int // offset to write into suffix + skipped int64 + + // TODO(bradfitz): we could keep one large []byte and use part of it for + // the prefix, reserve space for the '... Omitting N bytes ...' message, + // then the ring buffer suffix, and just rearrange the ring buffer + // suffix when Bytes() is called, but it doesn't seem worth it for + // now just for error messages. It's only ~64KB anyway. +} + +func (w *PrefixSuffixSaver) Write(p []byte) (n int, err error) { + lenp := len(p) + p = w.fill(&w.prefix, p) + + // Only keep the last w.N bytes of suffix data. + if overage := len(p) - w.N; overage > 0 { + p = p[overage:] + w.skipped += int64(overage) + } + p = w.fill(&w.suffix, p) + + // w.suffix is full now if p is non-empty. Overwrite it in a circle. + for len(p) > 0 { // 0, 1, or 2 iterations. + n := copy(w.suffix[w.suffixOff:], p) + p = p[n:] + w.skipped += int64(n) + w.suffixOff += n + if w.suffixOff == w.N { + w.suffixOff = 0 + } + } + return lenp, nil +} + +// fill appends up to len(p) bytes of p to *dst, such that *dst does not +// grow larger than w.N. It returns the un-appended suffix of p. +func (w *PrefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) { + if remain := w.N - len(*dst); remain > 0 { + add := minInt(len(p), remain) + *dst = append(*dst, p[:add]...) + p = p[add:] + } + return p +} + +// Bytes returns a slice of the bytes, or a copy of the bytes, retained by w. +// If more bytes than could be retained were written to w, it returns a +// concatenation of the N first bytes, a message for how many bytes were dropped, +// and the N last bytes. +func (w *PrefixSuffixSaver) Bytes() []byte { + if w.suffix == nil { + return w.prefix + } + if w.skipped == 0 { + return append(w.prefix, w.suffix...) + } + var buf bytes.Buffer + buf.Grow(len(w.prefix) + len(w.suffix) + 50) + buf.Write(w.prefix) + buf.WriteString("\n... omitting ") + buf.WriteString(strconv.FormatInt(w.skipped, 10)) + buf.WriteString(" bytes ...\n") + buf.Write(w.suffix[w.suffixOff:]) + buf.Write(w.suffix[:w.suffixOff]) + return buf.Bytes() +} + +func minInt(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/vendor/go4.org/writerutil/writerutil_test.go b/vendor/go4.org/writerutil/writerutil_test.go new file mode 100644 index 000000000..fae647a32 --- /dev/null +++ b/vendor/go4.org/writerutil/writerutil_test.go @@ -0,0 +1,73 @@ +/* +Copyright 2016 The go4 Authors + +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 writerutil + +import ( + "io" + "testing" +) + +func TestPrefixSuffixSaver(t *testing.T) { + tests := []struct { + N int + writes []string + want string + }{ + { + N: 2, + writes: nil, + want: "", + }, + { + N: 2, + writes: []string{"a"}, + want: "a", + }, + { + N: 2, + writes: []string{"abc", "d"}, + want: "abcd", + }, + { + N: 2, + writes: []string{"abc", "d", "e"}, + want: "ab\n... omitting 1 bytes ...\nde", + }, + { + N: 2, + writes: []string{"ab______________________yz"}, + want: "ab\n... omitting 22 bytes ...\nyz", + }, + { + N: 2, + writes: []string{"ab_______________________y", "z"}, + want: "ab\n... omitting 23 bytes ...\nyz", + }, + } + for i, tt := range tests { + w := &PrefixSuffixSaver{N: tt.N} + for _, s := range tt.writes { + n, err := io.WriteString(w, s) + if err != nil || n != len(s) { + t.Errorf("%d. WriteString(%q) = %v, %v; want %v, %v", i, s, n, err, len(s), nil) + } + } + if got := string(w.Bytes()); got != tt.want { + t.Errorf("%d. Bytes = %q; want %q", i, got, tt.want) + } + } +}