github.com/ethersphere/bee/v2@v2.2.0/pkg/file/loadsave/loadsave.go (about) 1 // Copyright 2021 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package loadsave provides lightweight persistence abstraction 6 // for manifest operations. 7 package loadsave 8 9 import ( 10 "bytes" 11 "context" 12 "errors" 13 14 "github.com/ethersphere/bee/v2/pkg/file" 15 "github.com/ethersphere/bee/v2/pkg/file/joiner" 16 "github.com/ethersphere/bee/v2/pkg/file/pipeline" 17 "github.com/ethersphere/bee/v2/pkg/file/pipeline/builder" 18 storage "github.com/ethersphere/bee/v2/pkg/storage" 19 "github.com/ethersphere/bee/v2/pkg/swarm" 20 ) 21 22 var errReadonlyLoadSave = errors.New("readonly manifest loadsaver") 23 24 // loadSave is needed for manifest operations and provides 25 // simple wrapping over load and save operations using file 26 // package abstractions. use with caution since Loader will 27 // load all of the subtrie of a given hash in memory. 28 type loadSave struct { 29 getter storage.Getter 30 putter storage.Putter 31 pipelineFn func() pipeline.Interface 32 } 33 34 // New returns a new read-write load-saver. 35 func New(getter storage.Getter, putter storage.Putter, pipelineFn func() pipeline.Interface) file.LoadSaver { 36 return &loadSave{ 37 getter: getter, 38 putter: putter, 39 pipelineFn: pipelineFn, 40 } 41 } 42 43 // NewReadonly returns a new read-only load-saver 44 // which will error on write. 45 func NewReadonly(getter storage.Getter) file.LoadSaver { 46 return &loadSave{ 47 getter: getter, 48 } 49 } 50 51 func (ls *loadSave) Load(ctx context.Context, ref []byte) ([]byte, error) { 52 j, _, err := joiner.New(ctx, ls.getter, ls.putter, swarm.NewAddress(ref)) 53 if err != nil { 54 return nil, err 55 } 56 57 buf := bytes.NewBuffer(nil) 58 _, err = file.JoinReadAll(ctx, j, buf) 59 if err != nil { 60 return nil, err 61 } 62 63 return buf.Bytes(), nil 64 } 65 66 func (ls *loadSave) Save(ctx context.Context, data []byte) ([]byte, error) { 67 if ls.pipelineFn == nil { 68 return nil, errReadonlyLoadSave 69 } 70 71 pipe := ls.pipelineFn() 72 address, err := builder.FeedPipeline(ctx, pipe, bytes.NewReader(data)) 73 if err != nil { 74 return swarm.ZeroAddress.Bytes(), err 75 } 76 77 return address.Bytes(), nil 78 }