github.com/ethersphere/bee/v2@v2.2.0/pkg/swarm/distance.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 swarm
     6  
     7  import (
     8  	"errors"
     9  	"math/big"
    10  )
    11  
    12  // Distance returns the distance between address x and address y as a (comparable) big integer using the distance metric defined in the swarm specification.
    13  // Fails if not all addresses are of equal length.
    14  func Distance(x, y Address) (*big.Int, error) {
    15  	distanceBytes, err := DistanceRaw(x, y)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	r := big.NewInt(0)
    20  	r.SetBytes(distanceBytes)
    21  	return r, nil
    22  }
    23  
    24  // DistanceRaw returns the distance between address x and address y in big-endian binary format using the distance metric defined in the swarm specification.
    25  // Fails if not all addresses are of equal length.
    26  func DistanceRaw(x, y Address) ([]byte, error) {
    27  	xb, yb := x.b, y.b
    28  
    29  	if len(xb) != len(yb) {
    30  		return nil, errors.New("address length must match")
    31  	}
    32  	c := make([]byte, len(xb))
    33  	for i, addr := range xb {
    34  		c[i] = addr ^ yb[i]
    35  	}
    36  	return c, nil
    37  }
    38  
    39  // DistanceCmp compares x and y to a in terms of the distance metric defined in the swarm specification.
    40  // it returns:
    41  //   - 1 if x is closer to a than y
    42  //   - 0 if x and y are equally far apart from a (this means that x and y are the same address)
    43  //   - -1 if x is farther from a than y
    44  //
    45  // Fails if not all addresses are of equal length.
    46  func DistanceCmp(a, x, y Address) (int, error) {
    47  	ab, xb, yb := a.b, x.b, y.b
    48  
    49  	if len(ab) != len(xb) || len(ab) != len(yb) {
    50  		return 0, errors.New("address length must match")
    51  	}
    52  
    53  	for i := range ab {
    54  		dx := xb[i] ^ ab[i]
    55  		dy := yb[i] ^ ab[i]
    56  		if dx == dy {
    57  			continue
    58  		} else if dx < dy {
    59  			return 1, nil
    60  		}
    61  		return -1, nil
    62  	}
    63  	return 0, nil
    64  }