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 }