summaryrefslogtreecommitdiff
path: root/vendor/github.com/getlantern/errors/hide.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/getlantern/errors/hide.go')
-rw-r--r--vendor/github.com/getlantern/errors/hide.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/vendor/github.com/getlantern/errors/hide.go b/vendor/github.com/getlantern/errors/hide.go
new file mode 100644
index 0000000..f10d863
--- /dev/null
+++ b/vendor/github.com/getlantern/errors/hide.go
@@ -0,0 +1,50 @@
+package errors
+
+import (
+ "encoding/binary"
+ "sync"
+
+ "github.com/getlantern/hidden"
+)
+
+var (
+ hiddenErrors = make([]*structured, 100)
+ nextID = uint64(0)
+ hiddenMutex sync.RWMutex
+)
+
+// This trick saves the error to a ring buffer and embeds a non-printing
+// hiddenID in the error's description, so that if the errors is later wrapped
+// by a standard error using something like
+// fmt.Errorf("An error occurred: %v", thisError), we can subsequently extract
+// the error simply using the hiddenID in the string.
+func (e *structured) save() {
+ hiddenMutex.Lock()
+ b := make([]byte, 8)
+ binary.BigEndian.PutUint64(b, nextID)
+ e.id = nextID
+ e.hiddenID = hidden.ToString(b)
+ hiddenErrors[idxForID(nextID)] = e
+ nextID++
+ hiddenMutex.Unlock()
+}
+
+func get(hiddenID []byte) Error {
+ if len(hiddenID) != 8 {
+ return nil
+ }
+ id := binary.BigEndian.Uint64(hiddenID)
+ hiddenMutex.RLock()
+ err := hiddenErrors[idxForID(id)]
+ hiddenMutex.RUnlock()
+ if err != nil && err.id == id {
+ // Found it!
+ return err
+ }
+ // buffer has rolled over
+ return nil
+}
+
+func idxForID(id uint64) int {
+ return int(id % uint64(len(hiddenErrors)))
+}