/
pluginbundle.go
161 lines (132 loc) · 3.57 KB
/
pluginbundle.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
package plugin
import (
"fmt"
"git.golaxy.org/core/internal/exception"
"git.golaxy.org/core/util/generic"
"git.golaxy.org/core/util/iface"
"git.golaxy.org/core/util/types"
"reflect"
"slices"
"sync"
)
// PluginBundle 插件包
type PluginBundle interface {
PluginProvider
// Install 安装插件,不设置插件名称时,将会使用插件实例名称作为插件名称
Install(pluginFace iface.FaceAny, name ...string) PluginInfo
// Uninstall 卸载插件
Uninstall(name string)
// Get 获取插件
Get(name string) (PluginInfo, bool)
// Range 遍历所有已注册的插件
Range(fun generic.Func1[PluginInfo, bool])
// ReverseRange 反向遍历所有已注册的插件
ReverseRange(fun generic.Func1[PluginInfo, bool])
activate(name string, b bool)
}
// NewPluginBundle 创建插件包
func NewPluginBundle() PluginBundle {
return &_PluginBundle{
pluginMap: map[string]*PluginInfo{},
}
}
// PluginInfo 插件信息
type PluginInfo struct {
Name string // 插件名
Face iface.FaceAny // 插件Face
Reflected reflect.Value // 插件反射值
Active bool // 是否激活
}
type _PluginBundle struct {
sync.RWMutex
pluginMap map[string]*PluginInfo
pluginList []*PluginInfo
}
// GetPluginBundle 获取插件包
func (bundle *_PluginBundle) GetPluginBundle() PluginBundle {
return bundle
}
// Install 安装插件,不设置插件名称时,将会使用插件实例名称作为插件名称
func (bundle *_PluginBundle) Install(pluginFace iface.FaceAny, name ...string) PluginInfo {
if pluginFace.IsNil() {
panic(fmt.Errorf("%w: %w: pluginFace is nil", ErrPlugin, exception.ErrArgs))
}
bundle.Lock()
defer bundle.Unlock()
var _name string
if len(name) > 0 {
_name = name[0]
} else {
_name = types.AnyFullName(pluginFace.Iface)
}
_, ok := bundle.pluginMap[_name]
if ok {
panic(fmt.Errorf("%w: plugin %q is already installed", ErrPlugin, name))
}
pluginInfo := &PluginInfo{
Name: _name,
Face: pluginFace,
Reflected: reflect.ValueOf(pluginFace.Iface),
Active: false,
}
bundle.pluginList = append(bundle.pluginList, pluginInfo)
bundle.pluginMap[_name] = pluginInfo
return *pluginInfo
}
// Uninstall 卸载插件
func (bundle *_PluginBundle) Uninstall(name string) {
bundle.Lock()
defer bundle.Unlock()
pluginInfo, ok := bundle.pluginMap[name]
if !ok {
return
}
if pluginInfo.Active {
panic(fmt.Errorf("%w: plugin %q is active, can't uninstall", ErrPlugin, name))
}
delete(bundle.pluginMap, name)
bundle.pluginList = slices.DeleteFunc(bundle.pluginList, func(info *PluginInfo) bool {
return info.Name == name
})
}
// Get 获取插件
func (bundle *_PluginBundle) Get(name string) (PluginInfo, bool) {
bundle.RLock()
defer bundle.RUnlock()
pluginInfo, ok := bundle.pluginMap[name]
if !ok {
return PluginInfo{}, false
}
return *pluginInfo, ok
}
// Range 遍历所有已注册的插件
func (bundle *_PluginBundle) Range(fun generic.Func1[PluginInfo, bool]) {
bundle.RLock()
copied := slices.Clone(bundle.pluginList)
bundle.RUnlock()
for i := range copied {
if !fun.Exec(*copied[i]) {
return
}
}
}
// ReverseRange 反向遍历所有已注册的插件
func (bundle *_PluginBundle) ReverseRange(fun generic.Func1[PluginInfo, bool]) {
bundle.RLock()
copied := slices.Clone(bundle.pluginList)
bundle.RUnlock()
for i := len(copied) - 1; i >= 0; i-- {
if !fun.Exec(*copied[i]) {
return
}
}
}
func (bundle *_PluginBundle) activate(name string, b bool) {
bundle.Lock()
defer bundle.Unlock()
pluginInfo, ok := bundle.pluginMap[name]
if !ok {
return
}
pluginInfo.Active = b
}