/
path.go
127 lines (103 loc) · 2.25 KB
/
path.go
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package simplepath
import (
"bytes"
"fmt"
"github.com/digitalbitsorg/go/services/frontier/internal/db2/core"
"github.com/digitalbitsorg/go/services/frontier/internal/paths"
"github.com/digitalbitsorg/go/xdr"
)
// pathNode implements the paths.Path interface and represents a path
// as a linked list pointing from source to destination.
type pathNode struct {
Asset xdr.Asset
Tail *pathNode
Q *core.Q
}
// check interface compatibility
var _ paths.Path = &pathNode{}
func (p *pathNode) String() string {
if p == nil {
return ""
}
var out bytes.Buffer
fmt.Fprintf(&out, "%v", p.Asset)
cur := p.Tail
for cur != nil {
fmt.Fprintf(&out, " -> %v", cur.Asset)
cur = cur.Tail
}
return out.String()
}
// Destination implements paths.Path.Destination interface method
func (p *pathNode) Destination() xdr.Asset {
cur := p
for cur.Tail != nil {
cur = cur.Tail
}
return cur.Asset
}
// Source implements paths.Path.Source interface method
func (p *pathNode) Source() xdr.Asset {
// the destination for path is the head of the linked list
return p.Asset
}
// Path implements paths.Path.Path interface method
func (p *pathNode) Path() []xdr.Asset {
path := p.Flatten()
if len(path) < 2 {
return nil
}
// return the flattened slice without the first and last elements
// which are the source and the destination assets
return path[1 : len(path)-1]
}
// Cost implements the paths.Path.Cost interface method
func (p *pathNode) Cost(amount xdr.Int64) (result xdr.Int64, err error) {
result = amount
if p.Tail == nil {
return
}
cur := p
for cur.Tail != nil {
ob := cur.OrderBook()
result, err = ob.Cost(cur.Tail.Asset, result)
if err != nil {
return
}
cur = cur.Tail
}
return
}
// Depth returns the length of the list
func (p *pathNode) Depth() int {
depth := 0
cur := p
for {
if cur == nil {
return depth
}
cur = cur.Tail
depth++
}
}
// Flatten walks the list and returns a slice of assets
func (p *pathNode) Flatten() (result []xdr.Asset) {
cur := p
for {
if cur == nil {
return
}
result = append(result, cur.Asset)
cur = cur.Tail
}
}
func (p *pathNode) OrderBook() *orderBook {
if p.Tail == nil {
return nil
}
return &orderBook{
Selling: p.Tail.Asset,
Buying: p.Asset,
Q: p.Q,
}
}