2 Copyright 2012 Google Inc.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
22 "github.com/golang/protobuf/proto"
25 // A Sink receives data from a Get call.
27 // Implementation of Getter must call exactly one of the Set methods
30 // SetString sets the value to s.
31 SetString(s string) error
33 // SetBytes sets the value to the contents of v.
34 // The caller retains ownership of v.
35 SetBytes(v []byte) error
37 // SetProto sets the value to the encoded version of m.
38 // The caller retains ownership of m.
39 SetProto(m proto.Message) error
41 // view returns a frozen view of the bytes for caching.
42 view() (ByteView, error)
45 func cloneBytes(b []byte) []byte {
46 c := make([]byte, len(b))
51 func setSinkView(s Sink, v ByteView) error {
52 // A viewSetter is a Sink that can also receive its value from
53 // a ByteView. This is a fast path to minimize copies when the
54 // item was already cached locally in memory (where it's
55 // cached as a ByteView)
56 type viewSetter interface {
57 setView(v ByteView) error
59 if vs, ok := s.(viewSetter); ok {
63 return s.SetBytes(v.b)
65 return s.SetString(v.s)
68 // StringSink returns a Sink that populates the provided string pointer.
69 func StringSink(sp *string) Sink {
70 return &stringSink{sp: sp}
73 type stringSink struct {
76 // TODO(bradfitz): track whether any Sets were called.
79 func (s *stringSink) view() (ByteView, error) {
80 // TODO(bradfitz): return an error if no Set was called
84 func (s *stringSink) SetString(v string) error {
91 func (s *stringSink) SetBytes(v []byte) error {
92 return s.SetString(string(v))
95 func (s *stringSink) SetProto(m proto.Message) error {
96 b, err := proto.Marshal(m)
105 // ByteViewSink returns a Sink that populates a ByteView.
106 func ByteViewSink(dst *ByteView) Sink {
110 return &byteViewSink{dst: dst}
113 type byteViewSink struct {
116 // if this code ever ends up tracking that at least one set*
117 // method was called, don't make it an error to call set
118 // methods multiple times. Lorry's payload.go does that, and
119 // it makes sense. The comment at the top of this file about
120 // "exactly one of the Set methods" is overly strict. We
121 // really care about at least once (in a handler), but if
122 // multiple handlers fail (or multiple functions in a program
123 // using a Sink), it's okay to re-use the same one.
126 func (s *byteViewSink) setView(v ByteView) error {
131 func (s *byteViewSink) view() (ByteView, error) {
135 func (s *byteViewSink) SetProto(m proto.Message) error {
136 b, err := proto.Marshal(m)
140 *s.dst = ByteView{b: b}
144 func (s *byteViewSink) SetBytes(b []byte) error {
145 *s.dst = ByteView{b: cloneBytes(b)}
149 func (s *byteViewSink) SetString(v string) error {
150 *s.dst = ByteView{s: v}
154 // ProtoSink returns a sink that unmarshals binary proto values into m.
155 func ProtoSink(m proto.Message) Sink {
161 type protoSink struct {
162 dst proto.Message // authorative value
165 v ByteView // encoded
168 func (s *protoSink) view() (ByteView, error) {
172 func (s *protoSink) SetBytes(b []byte) error {
173 err := proto.Unmarshal(b, s.dst)
177 s.v.b = cloneBytes(b)
182 func (s *protoSink) SetString(v string) error {
184 err := proto.Unmarshal(b, s.dst)
193 func (s *protoSink) SetProto(m proto.Message) error {
194 b, err := proto.Marshal(m)
198 // TODO(bradfitz): optimize for same-task case more and write
199 // right through? would need to document ownership rules at
200 // the same time. but then we could just assign *dst = *m
201 // here. This works for now:
202 err = proto.Unmarshal(b, s.dst)
211 // AllocatingByteSliceSink returns a Sink that allocates
212 // a byte slice to hold the received value and assigns
213 // it to *dst. The memory is not retained by groupcache.
214 func AllocatingByteSliceSink(dst *[]byte) Sink {
215 return &allocBytesSink{dst: dst}
218 type allocBytesSink struct {
223 func (s *allocBytesSink) view() (ByteView, error) {
227 func (s *allocBytesSink) setView(v ByteView) error {
229 *s.dst = cloneBytes(v.b)
237 func (s *allocBytesSink) SetProto(m proto.Message) error {
238 b, err := proto.Marshal(m)
242 return s.setBytesOwned(b)
245 func (s *allocBytesSink) SetBytes(b []byte) error {
246 return s.setBytesOwned(cloneBytes(b))
249 func (s *allocBytesSink) setBytesOwned(b []byte) error {
251 return errors.New("nil AllocatingByteSliceSink *[]byte dst")
253 *s.dst = cloneBytes(b) // another copy, protecting the read-only s.v.b view
259 func (s *allocBytesSink) SetString(v string) error {
261 return errors.New("nil AllocatingByteSliceSink *[]byte dst")
269 // TruncatingByteSliceSink returns a Sink that writes up to len(*dst)
270 // bytes to *dst. If more bytes are available, they're silently
271 // truncated. If fewer bytes are available than len(*dst), *dst
272 // is shrunk to fit the number of bytes available.
273 func TruncatingByteSliceSink(dst *[]byte) Sink {
274 return &truncBytesSink{dst: dst}
277 type truncBytesSink struct {
282 func (s *truncBytesSink) view() (ByteView, error) {
286 func (s *truncBytesSink) SetProto(m proto.Message) error {
287 b, err := proto.Marshal(m)
291 return s.setBytesOwned(b)
294 func (s *truncBytesSink) SetBytes(b []byte) error {
295 return s.setBytesOwned(cloneBytes(b))
298 func (s *truncBytesSink) setBytesOwned(b []byte) error {
300 return errors.New("nil TruncatingByteSliceSink *[]byte dst")
304 *s.dst = (*s.dst)[:n]
311 func (s *truncBytesSink) SetString(v string) error {
313 return errors.New("nil TruncatingByteSliceSink *[]byte dst")
317 *s.dst = (*s.dst)[:n]