github.com/ethersphere/bee/v2@v2.2.0/pkg/file/splitter/splitter.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 splitter provides implementations of the file.Splitter interface
     6  package splitter
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  
    14  	"github.com/ethersphere/bee/v2/pkg/file"
    15  	"github.com/ethersphere/bee/v2/pkg/file/splitter/internal"
    16  	storage "github.com/ethersphere/bee/v2/pkg/storage"
    17  	"github.com/ethersphere/bee/v2/pkg/swarm"
    18  )
    19  
    20  // simpleSplitter wraps a non-optimized implementation of file.Splitter
    21  type simpleSplitter struct {
    22  	putter storage.Putter
    23  }
    24  
    25  // NewSimpleSplitter creates a new SimpleSplitter
    26  func NewSimpleSplitter(storePutter storage.Putter) file.Splitter {
    27  	return &simpleSplitter{
    28  		putter: storePutter,
    29  	}
    30  }
    31  
    32  // Split implements the file.Splitter interface
    33  //
    34  // It uses a non-optimized internal component that blocks when performing
    35  // multiple levels of hashing when building the file hash tree.
    36  //
    37  // It returns the Swarmhash of the data.
    38  func (s *simpleSplitter) Split(ctx context.Context, r io.ReadCloser, dataLength int64, toEncrypt bool) (addr swarm.Address, err error) {
    39  	j := internal.NewSimpleSplitterJob(ctx, s.putter, dataLength, toEncrypt)
    40  	var total int64
    41  	data := make([]byte, swarm.ChunkSize)
    42  	var eof bool
    43  	for !eof {
    44  		c, err := r.Read(data)
    45  		total += int64(c)
    46  		if err != nil {
    47  			if errors.Is(err, io.EOF) {
    48  				if total < dataLength {
    49  					return swarm.ZeroAddress, fmt.Errorf("splitter only received %d bytes of data, expected %d bytes", total+int64(c), dataLength)
    50  				}
    51  				eof = true
    52  				continue
    53  			} else {
    54  				return swarm.ZeroAddress, err
    55  			}
    56  		}
    57  		cc, err := j.Write(data[:c])
    58  		if err != nil {
    59  			return swarm.ZeroAddress, err
    60  		}
    61  		if cc < c {
    62  			return swarm.ZeroAddress, fmt.Errorf("write count to file hasher component %d does not match read count %d", cc, c)
    63  		}
    64  	}
    65  
    66  	sum := j.Sum(nil)
    67  	newAddress := swarm.NewAddress(sum)
    68  	return newAddress, nil
    69  }