github.com/ethersphere/bee/v2@v2.2.0/pkg/manifest/simple.go (about)

     1  // Copyright 2020 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 manifest
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"fmt"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/file"
    13  	"github.com/ethersphere/bee/v2/pkg/manifest/simple"
    14  	"github.com/ethersphere/bee/v2/pkg/swarm"
    15  )
    16  
    17  const (
    18  	// ManifestSimpleContentType represents content type used for noting that
    19  	// specific file should be processed as 'simple' manifest
    20  	ManifestSimpleContentType = "application/bzz-manifest-simple+json"
    21  )
    22  
    23  type simpleManifest struct {
    24  	manifest simple.Manifest
    25  
    26  	reference swarm.Address
    27  	ls        file.LoadSaver
    28  }
    29  
    30  // NewSimpleManifest creates a new simple manifest.
    31  func NewSimpleManifest(ls file.LoadSaver) (Interface, error) {
    32  	return &simpleManifest{
    33  		manifest: simple.NewManifest(),
    34  		ls:       ls,
    35  	}, nil
    36  }
    37  
    38  // NewSimpleManifestReference loads existing simple manifest.
    39  func NewSimpleManifestReference(ref swarm.Address, l file.LoadSaver) (Interface, error) {
    40  	m := &simpleManifest{
    41  		manifest:  simple.NewManifest(),
    42  		reference: ref,
    43  		ls:        l,
    44  	}
    45  	err := m.load(context.Background(), ref)
    46  	return m, err
    47  }
    48  
    49  func (m *simpleManifest) Type() string {
    50  	return ManifestSimpleContentType
    51  }
    52  
    53  func (m *simpleManifest) Add(_ context.Context, path string, entry Entry) error {
    54  	e := entry.Reference().String()
    55  
    56  	return m.manifest.Add(path, e, entry.Metadata())
    57  }
    58  
    59  func (m *simpleManifest) Remove(_ context.Context, path string) error {
    60  	err := m.manifest.Remove(path)
    61  	if err != nil {
    62  		if errors.Is(err, simple.ErrNotFound) {
    63  			return ErrNotFound
    64  		}
    65  		return err
    66  	}
    67  
    68  	return nil
    69  }
    70  
    71  func (m *simpleManifest) Lookup(_ context.Context, path string) (Entry, error) {
    72  	n, err := m.manifest.Lookup(path)
    73  	if err != nil {
    74  		return nil, ErrNotFound
    75  	}
    76  
    77  	address, err := swarm.ParseHexAddress(n.Reference())
    78  	if err != nil {
    79  		return nil, fmt.Errorf("parse swarm address: %w", err)
    80  	}
    81  
    82  	entry := NewEntry(address, n.Metadata())
    83  
    84  	return entry, nil
    85  }
    86  
    87  func (m *simpleManifest) HasPrefix(_ context.Context, prefix string) (bool, error) {
    88  	return m.manifest.HasPrefix(prefix), nil
    89  }
    90  
    91  func (m *simpleManifest) Store(ctx context.Context, storeSizeFn ...StoreSizeFunc) (swarm.Address, error) {
    92  	data, err := m.manifest.MarshalBinary()
    93  	if err != nil {
    94  		return swarm.ZeroAddress, fmt.Errorf("manifest marshal error: %w", err)
    95  	}
    96  
    97  	if len(storeSizeFn) > 0 {
    98  		dataLen := int64(len(data))
    99  		for i := range storeSizeFn {
   100  			err = storeSizeFn[i](dataLen)
   101  			if err != nil {
   102  				return swarm.ZeroAddress, fmt.Errorf("manifest store size func: %w", err)
   103  			}
   104  		}
   105  	}
   106  
   107  	ref, err := m.ls.Save(ctx, data)
   108  	if err != nil {
   109  		return swarm.ZeroAddress, fmt.Errorf("manifest save error: %w", err)
   110  	}
   111  	m.reference = swarm.NewAddress(ref)
   112  	return m.reference, nil
   113  }
   114  
   115  func (m *simpleManifest) IterateAddresses(ctx context.Context, fn swarm.AddressIterFunc) error {
   116  	if swarm.ZeroAddress.Equal(m.reference) {
   117  		return ErrMissingReference
   118  	}
   119  
   120  	// NOTE: making it behave same for all manifest implementation
   121  	err := fn(m.reference)
   122  	if err != nil {
   123  		return fmt.Errorf("manifest iterate addresses: %w", err)
   124  	}
   125  
   126  	walker := func(path string, entry simple.Entry, err error) error {
   127  		if err != nil {
   128  			return err
   129  		}
   130  
   131  		ref, err := swarm.ParseHexAddress(entry.Reference())
   132  		if err != nil {
   133  			return err
   134  		}
   135  
   136  		return fn(ref)
   137  	}
   138  
   139  	err = m.manifest.WalkEntry("", walker)
   140  	if err != nil {
   141  		return fmt.Errorf("manifest iterate addresses: %w", err)
   142  	}
   143  
   144  	return nil
   145  }
   146  
   147  func (m *simpleManifest) load(ctx context.Context, reference swarm.Address) error {
   148  	buf, err := m.ls.Load(ctx, reference.Bytes())
   149  	if err != nil {
   150  		return fmt.Errorf("manifest load error: %w", err)
   151  	}
   152  
   153  	err = m.manifest.UnmarshalBinary(buf)
   154  	if err != nil {
   155  		return fmt.Errorf("manifest unmarshal error: %w", err)
   156  	}
   157  
   158  	return nil
   159  }