-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathfile_callbacks.go
More file actions
132 lines (109 loc) · 3.83 KB
/
file_callbacks.go
File metadata and controls
132 lines (109 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) 2026 Couchbase, Inc.
//
// 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 zap
import (
"fmt"
index "github.com/blevesearch/bleve_index_api"
)
// This file provides a mechanism for users of zap to provide callbacks
// that can process data before it is written to disk, and after it is read
// from disk. This can be used for things like encryption, compression, etc.
// The user is responsible for ensuring that the writer and reader callbacks
// are compatible with each other, and that any state needed by the callbacks
// is managed appropriately. For example, if the writer callback uses a
// unique key or nonce per write, the reader callback must be able to
// determine the correct key or nonce to use for each read.
// The callbacks are identified by an id string, which is returned by the
// WriterCallbackGetter. The same id string is passed to the ReaderCallbackGetter
// when creating a reader. This allows the reader to determine which
// callback to use for a given file.
// An example implementation using AES-GCM encryption is provided in
// file_callbacks_test.go within initFileCallbacks().
// the default id to use for file callbacks that indicates a no op
const DefaultFileCallbackId = ""
// FileWriter wraps a CountHashWriter and applies a user provided
// writer callback to the data being written.
type FileWriter struct {
id string
c *CountHashWriter
processor func(data []byte) []byte
}
// creates an empty FileWriter with no callback. Used
// when we are writing data that is not going to be persisted
func NewFileWriterEmpty(c *CountHashWriter) *FileWriter {
rv := &FileWriter{
c: c,
}
return rv
}
// NewFileWriter creates a FileWriter with the provided CountHashWriter and applies
// the writer callback identified by the context.
func NewFileWriter(c *CountHashWriter, context []byte) (*FileWriter, error) {
rv := &FileWriter{
c: c,
}
if index.WriterHook != nil {
var err error
rv.id, rv.processor, err = index.WriterHook(context)
if err != nil {
return nil, err
}
}
return rv, nil
}
func (w *FileWriter) Write(data []byte) (int, error) {
return w.c.Write(data)
}
// process applies the writer callback to the data, if one is set
func (w *FileWriter) process(data []byte) []byte {
if w.processor != nil {
return w.processor(data)
}
return data
}
func (w *FileWriter) Count() int {
return w.c.Count()
}
func (w *FileWriter) Sum32() uint32 {
return w.c.Sum32()
}
// FileReader wraps a reader callback to be applied to data read from a file.
type FileReader struct {
id string
processor func(data []byte) ([]byte, error)
}
// NewFileReader creates a FileReader with the reader callback identified by the context.
// The id is used to identify which callback to use when reading data.
func NewFileReader(id string, context []byte) (*FileReader, error) {
rv := &FileReader{
id: id,
}
if index.ReaderHook != nil {
var err error
rv.processor, err = index.ReaderHook(id, context)
if err != nil {
return nil, err
}
} else if id != DefaultFileCallbackId {
return nil, fmt.Errorf("reader callback id %s provided but no ReaderHook is set", id)
}
return rv, nil
}
// process applies the reader callback to the data, if one is set
func (r *FileReader) process(data []byte) ([]byte, error) {
if r.processor != nil {
return r.processor(data)
}
return data, nil
}