This repository has been archived by the owner on Feb 21, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interface.go
165 lines (142 loc) · 5.02 KB
/
interface.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package loader
import (
"bytes"
"errors"
"io"
"os"
"time"
"github.com/lestrrat/go-xslate/compiler"
"github.com/lestrrat/go-xslate/vm"
"github.com/lestrrat/go-xslate/parser"
)
// CacheStrategy specifies how the cache should be checked
type CacheStrategy int
const (
// CacheNone flag specifies that cache checking and setting hould be skipped
CacheNone CacheStrategy = iota
// CacheVerify flag specifies that cached ByteCode generation time should be
// verified against the source's last modified time. If new, the source is
// re-parsed and re-compiled even on a cache hit.
CacheVerify
// CacheNoVerify flag specifies that if we have a cache hit, the ByteCode
// is not verified against the source. If there's a cache hit, it is
// used regardless of updates to the original template on file system
CacheNoVerify
)
// CacheEntity contains all the othings required to perform calculations
// necessary to validate a template
type CacheEntity struct {
ByteCode *vm.ByteCode
Source TemplateSource
}
// Cache defines the interface for things that can cache generated ByteCode
type Cache interface {
Get(string) (*CacheEntity, error)
Set(string, *CacheEntity) error
Delete(string) error
}
// CachedByteCodeLoader is the default ByteCodeLoader that loads templates
// from the file system and caches in the file system, too
type CachedByteCodeLoader struct {
*StringByteCodeLoader // gives us LoadString
*ReaderByteCodeLoader // gives us LoadReader
Fetcher TemplateFetcher
Caches []Cache
CacheLevel CacheStrategy
}
// FileCache is Cache implementation that stores caches in the file system
type FileCache struct {
Dir string
}
// MemoryCache is what's used store cached ByteCode in memory for maximum
// speed. As of this writing this cache never freed. We may need to
// introduce LRU in the future
type MemoryCache map[string]*CacheEntity
// FileTemplateFetcher is a TemplateFetcher that loads template strings
// in the file system.
type FileTemplateFetcher struct {
Paths []string
}
// NewFileSource creates a new FileSource
func NewFileSource(path string) *FileSource {
return &FileSource{path, time.Time{}, nil}
}
// FileSource is a TemplateSource variant that holds template information
// in a file.
type FileSource struct {
Path string
LastStat time.Time
LastStatResult os.FileInfo
}
// HTTPTemplateFetcher is a proof of concept loader that fetches templates
// from external http servers. Probably not a good thing to use in
// your production environment
type HTTPTemplateFetcher struct {
URLs []string
}
// HTTPSource represents a template source fetched via HTTP
type HTTPSource struct {
Buffer *bytes.Buffer
LastModifiedTime time.Time
}
// ReaderByteCodeLoader is a fancy name for objects that can "given a template
// string, parse and compile it". This is one of the most common operations
// that users want to do, but it needs to be separate from other loaders
// because there's no sane way to cache intermediate results, and therefore
// has significant performance penalty
type ReaderByteCodeLoader struct {
*Flags
Parser parser.Parser
Compiler compiler.Compiler
}
// Mask... set of constants are used as flags to denote Debug modes.
// If you're using these you should be reading the source code
const (
MaskDumpByteCode = 1 << iota
MaskDumpAST
)
// Flags holds the flags to indicate if certain debug operations should be
// performed during load time
type Flags struct{ flags int32 }
// DebugDumper defines interface that an object able to dump debug informatin
// during load time must fulfill
type DebugDumper interface {
DumpAST(bool)
DumpByteCode(bool)
ShouldDumpAST() bool
ShouldDumpByteCode() bool
}
// ByteCodeLoader defines the interface for objects that can load
// ByteCode specified by a key
type ByteCodeLoader interface {
DebugDumper
LoadString(string, string) (*vm.ByteCode, error)
Load(string) (*vm.ByteCode, error)
}
// TemplateFetcher defines the interface for objects that can load
// TemplateSource specified by a key
type TemplateFetcher interface {
FetchTemplate(string) (TemplateSource, error)
}
// TemplateSource is an abstraction over the actual template, which may live
// on a file system, cache, database, whatever.
// It needs to be able to give us the actual template string AND its
// last modified time
type TemplateSource interface {
LastModified() (time.Time, error)
Bytes() ([]byte, error)
Reader() (io.Reader, error)
}
// ErrTemplateNotFound is returned whenever one of the loaders failed to
// find a suitable template
var ErrTemplateNotFound = errors.New("error: Specified template was not found")
// StringByteCodeLoader is a fancy name for objects that can "given a template
// string, parse and compile it". This is one of the most common operations
// that users want to do, but it needs to be separate from other loaders
// because there's no sane way to cache intermediate results, and therefore
// has significant performance penalty
type StringByteCodeLoader struct {
*Flags
Parser parser.Parser
Compiler compiler.Compiler
}