• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

go-spatial / tegola / 8ca83999a

07 Dec 2024 07:11PM UTC coverage: 42.844% (+0.05%) from 42.794%
8ca83999a

push

github

ARolek
chore: vendor update

chore: vendor update

chore: drop gcs context

7026 of 16399 relevant lines covered (42.84%)

215.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.84
/cache/cache.go
1
package cache
2

3
import (
4
        "context"
5
        "fmt"
6
        "log"
7
        "path/filepath"
8
        "sort"
9
        "strconv"
10
        "strings"
11

12
        "github.com/go-spatial/tegola"
13
        "github.com/go-spatial/tegola/dict"
14
        "github.com/go-spatial/tegola/maths"
15
)
16

17
// Interface defines a cache back end
18
type Interface interface {
19
        Get(ctx context.Context, key *Key) (val []byte, hit bool, err error)
20
        Set(ctx context.Context, key *Key, val []byte) error
21
        Purge(ctx context.Context, key *Key) error
22
}
23

24
// Wrapped Cache are for cache backend that wrap other cache backends
25
// Original will return the first cache backend to be wrapped
26
type Wrapped interface {
27
        Original() Interface
28
}
29

30
// ParseKey will parse a string in the format /:map/:layer/:z/:x/:y into a Key struct. The :layer value is optional
31
// ParseKey also supports other OS delimiters (i.e. Windows - "\")
32
func ParseKey(str string) (*Key, error) {
3✔
33
        var err error
3✔
34
        var key Key
3✔
35

3✔
36
        // convert to all slashes to forward slashes. without this reading from certain OSes (i.e. windows)
3✔
37
        // will fail our keyParts check since it uses backslashes.
3✔
38
        str = filepath.ToSlash(str)
3✔
39

3✔
40
        // remove the base-path and the first slash, then split the parts
3✔
41
        keyParts := strings.Split(strings.TrimLeft(str, "/"), "/")
3✔
42

3✔
43
        // we're expecting a z/x/y scheme
3✔
44
        if len(keyParts) < 3 || len(keyParts) > 5 {
3✔
45
                err = ErrInvalidFileKeyParts{
×
46
                        path:          str,
×
47
                        keyPartsCount: len(keyParts),
×
48
                }
×
49

×
50
                log.Println(err.Error())
×
51
                return nil, err
×
52
        }
×
53

54
        var zxy []string
3✔
55

3✔
56
        switch len(keyParts) {
3✔
57
        case 5: // map, layer, z, x, y
1✔
58
                key.MapName = keyParts[0]
1✔
59
                key.LayerName = keyParts[1]
1✔
60
                zxy = keyParts[2:]
1✔
61
        case 4: // map, z, x, y
1✔
62
                key.MapName = keyParts[0]
1✔
63
                zxy = keyParts[1:]
1✔
64
        case 3: // z, x, y
1✔
65
                zxy = keyParts
1✔
66
        }
67

68
        // parse our URL vals into integers
69
        var placeholder uint64
3✔
70
        placeholder, err = strconv.ParseUint(zxy[0], 10, 32)
3✔
71
        if err != nil || placeholder > tegola.MaxZ {
3✔
72
                err = ErrInvalidFileKey{
×
73
                        path: str,
×
74
                        key:  "Z",
×
75
                        val:  zxy[0],
×
76
                }
×
77

×
78
                log.Printf(err.Error())
×
79
                return nil, err
×
80
        }
×
81

82
        key.Z = uint(placeholder)
3✔
83
        maxXYatZ := maths.Exp2(placeholder) - 1
3✔
84

3✔
85
        placeholder, err = strconv.ParseUint(zxy[1], 10, 32)
3✔
86
        if err != nil || placeholder > maxXYatZ {
3✔
87
                err = ErrInvalidFileKey{
×
88
                        path: str,
×
89
                        key:  "X",
×
90
                        val:  zxy[1],
×
91
                }
×
92

×
93
                log.Printf(err.Error())
×
94
                return nil, err
×
95
        }
×
96

97
        key.X = uint(placeholder)
3✔
98

3✔
99
        // trim the extension if it exists
3✔
100
        yParts := strings.Split(zxy[2], ".")
3✔
101
        placeholder, err = strconv.ParseUint(yParts[0], 10, 64)
3✔
102
        if err != nil || placeholder > maxXYatZ {
3✔
103
                err = ErrInvalidFileKey{
×
104
                        path: str,
×
105
                        key:  "Y",
×
106
                        val:  zxy[2],
×
107
                }
×
108

×
109
                log.Printf(err.Error())
×
110
                return nil, err
×
111
        }
×
112
        key.Y = uint(placeholder)
3✔
113

3✔
114
        return &key, nil
3✔
115
}
116

117
type Key struct {
118
        MapName   string
119
        LayerName string
120
        Z         uint
121
        X         uint
122
        Y         uint
123
}
124

125
func (k Key) String() string {
×
126
        return filepath.Join(
×
127
                k.MapName,
×
128
                k.LayerName,
×
129
                strconv.FormatUint(uint64(k.Z), 10),
×
130
                strconv.FormatUint(uint64(k.X), 10),
×
131
                strconv.FormatUint(uint64(k.Y), 10))
×
132
}
×
133

134
// InitFunc initialize a cache given a config map.
135
// The InitFunc should validate the config map, and report any errors.
136
// This is called by the For function.
137
type InitFunc func(dict.Dicter) (Interface, error)
138

139
var cache map[string]InitFunc
140

141
// Register is called by the init functions of the cache.
142
func Register(cacheType string, init InitFunc) error {
×
143
        if cache == nil {
×
144
                cache = make(map[string]InitFunc)
×
145
        }
×
146

147
        if _, ok := cache[cacheType]; ok {
×
148
                return fmt.Errorf("Cache (%v) already exists", cacheType)
×
149

×
150
        }
×
151
        cache[cacheType] = init
×
152

×
153
        return nil
×
154
}
155

156
// Registered returns the cache's that have been registered.
157
func Registered() (c []string) {
×
158
        for k := range cache {
×
159
                c = append(c, k)
×
160
        }
×
161
        sort.Strings(c)
×
162
        return c
×
163
}
164

165
// For function returns a configured cache of the given type, provided the correct config map.
166
func For(cacheType string, config dict.Dicter) (Interface, error) {
×
167
        if cache == nil {
×
168
                return nil, fmt.Errorf("No cache backends registered.")
×
169
        }
×
170

171
        c, ok := cache[cacheType]
×
172
        if !ok {
×
173
                return nil, fmt.Errorf("No cache backends registered by the cache type: (%v)", cacheType)
×
174
        }
×
175

176
        return c(config)
×
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc