aboutsummaryrefslogtreecommitdiffstats
path: root/swarm/chunk/chunk.go
blob: 7540af8ce9d116459d1596a995d0c928e344da68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package chunk

import (
    "errors"
    "fmt"

    "github.com/ethereum/go-ethereum/common"
)

const (
    DefaultSize   = 4096
    MaxPO         = 16
    AddressLength = 32
)

var (
    ErrChunkNotFound = errors.New("chunk not found")
    ErrChunkInvalid  = errors.New("invalid chunk")
)

type Chunk interface {
    Address() Address
    Data() []byte
}

type chunk struct {
    addr  Address
    sdata []byte
}

func NewChunk(addr Address, data []byte) *chunk {
    return &chunk{
        addr:  addr,
        sdata: data,
    }
}

func (c *chunk) Address() Address {
    return c.addr
}

func (c *chunk) Data() []byte {
    return c.sdata
}

func (self *chunk) String() string {
    return fmt.Sprintf("Address: %v Chunksize: %v", self.addr.Log(), len(self.sdata))
}

type Address []byte

var ZeroAddr = Address(common.Hash{}.Bytes())

func (a Address) Hex() string {
    return fmt.Sprintf("%064x", []byte(a[:]))
}

func (a Address) Log() string {
    if len(a[:]) < 8 {
        return fmt.Sprintf("%x", []byte(a[:]))
    }
    return fmt.Sprintf("%016x", []byte(a[:8]))
}

func (a Address) String() string {
    return fmt.Sprintf("%064x", []byte(a))
}

func (a Address) MarshalJSON() (out []byte, err error) {
    return []byte(`"` + a.String() + `"`), nil
}

func (a *Address) UnmarshalJSON(value []byte) error {
    s := string(value)
    *a = make([]byte, 32)
    h := common.Hex2Bytes(s[1 : len(s)-1])
    copy(*a, h)
    return nil
}

// Proximity returns the proximity order of the MSB distance between x and y
//
// The distance metric MSB(x, y) of two equal length byte sequences x an y is the
// value of the binary integer cast of the x^y, ie., x and y bitwise xor-ed.
// the binary cast is big endian: most significant bit first (=MSB).
//
// Proximity(x, y) is a discrete logarithmic scaling of the MSB distance.
// It is defined as the reverse rank of the integer part of the base 2
// logarithm of the distance.
// It is calculated by counting the number of common leading zeros in the (MSB)
// binary representation of the x^y.
//
// (0 farthest, 255 closest, 256 self)
func Proximity(one, other []byte) (ret int) {
    b := (MaxPO-1)/8 + 1
    if b > len(one) {
        b = len(one)
    }
    m := 8
    for i := 0; i < b; i++ {
        oxo := one[i] ^ other[i]
        for j := 0; j < m; j++ {
            if (oxo>>uint8(7-j))&0x01 != 0 {
                return i*8 + j
            }
        }
    }
    return MaxPO
}