Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(551)

Unified Diff: service/rawdatastore/invertible.go

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: service/rawdatastore/invertible.go
diff --git a/service/rawdatastore/invertible.go b/service/rawdatastore/invertible.go
new file mode 100644
index 0000000000000000000000000000000000000000..c8b40b148596aeb8c4ed6d5667cc56a525401a79
--- /dev/null
+++ b/service/rawdatastore/invertible.go
@@ -0,0 +1,115 @@
+// Copyright 2015 The Chromium 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 rawdatastore
+
+import (
+ "bytes"
+)
+
+// Buffer is the interface which corresponds to the subset of *bytes.Buffer
+// that this package requires.
+type Buffer interface {
+ String() string
+ Grow(int)
+
+ Read([]byte) (int, error)
+ ReadByte() (byte, error)
+
+ Write([]byte) (int, error)
+ WriteByte(c byte) error
+ WriteString(s string) (int, error)
+}
+
+var _ Buffer = (*bytes.Buffer)(nil)
+
+// InvertibleBuffer is just like Buffer, except that it also has a stateful
+// Invert() method, which will cause all reads and writes to/from it to be
+// inverted (e.g. every byte XOR 0xFF).
+//
+// Implementing queries requires manipulating the index entries (e.g.
+// synthesizing them, parsing them, etc.). In particular, when you have
+// a reverse-sorted field (e.g. high to low instead of low to high), it's
+// achieved by having all the bits inverted.
+//
+// All the serialization formats include delimiter information, which the
+// parsers only know to parse non-inverted. If we don't have this buffer, we'd
+// basically have to invert every byte in the []byte array when we're trying to
+// decode a reverse-ordered field (including the bytes of all fields after the
+// one we intend to parse) so that the parser can consume as many bytes as it
+// needs (and it only knows the number of bytes it needs as it decodes them).
+// This InvertibleBuffer lets that happen on the fly without having to flip the
+// whole []byte.
+//
+// If you know you need it, you'll know it's the right thing. If you're not sure
+// then you definitely don't need it!
+type InvertibleBuffer interface {
+ Buffer
+ Invert()
+}
+
+type invertibleBuffer struct {
+ Buffer
+ invert bool
+}
+
+// Invertible returns an InvertibleBuffer based on the Buffer.
+func Invertible(b Buffer) InvertibleBuffer {
+ return &invertibleBuffer{b, false}
+}
+
+func (ib *invertibleBuffer) Read(bs []byte) (int, error) {
+ n, err := ib.Buffer.Read(bs)
+ if ib.invert {
+ for i, b := range bs {
+ bs[i] = b ^ 0xFF
+ }
+ }
+ return n, err
+}
+
+func (ib *invertibleBuffer) WriteString(s string) (int, error) {
+ if ib.invert {
+ ib.Grow(len(s))
+ for i := 0; i < len(s); i++ {
+ if err := ib.Buffer.WriteByte(s[i] ^ 0xFF); err != nil {
+ return i, err
+ }
+ }
+ return len(s), nil
+ }
+ return ib.Buffer.WriteString(s)
+}
+
+func (ib *invertibleBuffer) Write(bs []byte) (int, error) {
+ if ib.invert {
+ ib.Grow(len(bs))
+ for i, b := range bs {
+ if err := ib.Buffer.WriteByte(b ^ 0xFF); err != nil {
+ return i, err
+ }
+ }
+ return len(bs), nil
+ }
+ return ib.Buffer.Write(bs)
+}
+
+func (ib *invertibleBuffer) WriteByte(b byte) error {
+ if ib.invert {
+ b = b ^ 0xFF
+ }
+ return ib.Buffer.WriteByte(b)
+}
+
+func (ib *invertibleBuffer) ReadByte() (byte, error) {
+ ret, err := ib.Buffer.ReadByte()
+ if ib.invert {
+ ret = ret ^ 0xFF
+ }
+ return ret, err
+}
+
+func (ib *invertibleBuffer) Invert() {
+ ib.invert = !ib.invert
+}
« no previous file with comments | « service/rawdatastore/internal/protos/datastore/datastore_v3.pb.go ('k') | service/rawdatastore/invertible_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698