-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathproxy.lua
119 lines (106 loc) · 3.39 KB
/
proxy.lua
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
---@class Proxy
local M = {}
local RAW = {'<RAW>'}
local CONFIG = {'<CONFIG>'}
local CUSTOM = {'<CUSTOM>'}
---@alias Proxy.Setter fun(self: table, raw: any, key: any, value: any, config: Proxy.Config, custom: any): any
---@alias Proxy.Getter fun(self: table, raw: any, key: any, config: Proxy.Config, custom: any): any
---@class Proxy.Config
---@field cache? boolean # 将读写的结果缓存起来,下次读写时不会再触发`setter`,`getter`(除非上次的结果是`nil`
---@field updateRaw? boolean # 是否将赋值写入到 `raw` 中
---@field recursive? boolean # 是否递归代理
---@field setter? { [any]: Proxy.Setter }
---@field getter? { [any]: Proxy.Getter }
---@field anySetter? Proxy.Setter # 只有没有对应的 `setter` 才会触发 `anySetter`
---@field anyGetter? Proxy.Getter # 只有没有对应的 `getter` 才会触发 `anyGetter`
---@field package _recursiveState? table
local defaultConfig = {
cache = true,
}
local metatable = {
__newindex = function (self, key, value)
local raw = rawget(self, RAW)
---@type Proxy.Config
local config = rawget(self, CONFIG)
local custom = rawget(self, CUSTOM)
local setter = config.setter and config.setter[key]
local nvalue
if setter then
nvalue = setter(self, raw, key, value, config, custom)
elseif config.anySetter then
nvalue = config.anySetter(self, raw, key, value, config, custom)
else
nvalue = value
end
if config.cache then
rawset(self, key, nvalue)
end
if config.updateRaw then
raw[key] = nvalue
end
end,
__index = function (self, key)
local raw = rawget(self, RAW)
---@type Proxy.Config
local config = rawget(self, CONFIG)
local custom = rawget(self, CUSTOM)
local getter = config.getter and config.getter[key]
local value
if getter then
value = getter(self, raw, key, config, custom)
elseif config.anyGetter then
value = config.anyGetter(self, raw, key, config, custom)
else
value = raw[key]
end
if config.cache then
rawset(self, key, value)
end
return value
end,
__pairs = function (self)
local raw = rawget(self, RAW)
return pairs(raw)
end,
__len = function (self)
local raw = rawget(self, RAW)
return #raw
end
}
local metaKV = { __mode = 'kv' }
---@generic T
---@param obj T # 要代理的对象
---@param config? Proxy.Config # 配置
---@param custom? any # 自定义数据
---@return T
function M.new(obj, config, custom)
config = config or defaultConfig
if config.recursive then
if not config._recursiveState then
config._recursiveState = setmetatable({}, metaKV)
end
if config._recursiveState[obj] then
return config._recursiveState[obj]
end
end
local proxy = setmetatable({
[RAW] = obj,
[CONFIG] = config,
[CUSTOM] = custom,
}, metatable)
if config.recursive then
config._recursiveState[obj] = proxy
end
return proxy
end
---@param proxyObj table
---@return any
function M.raw(proxyObj)
return proxyObj[RAW]
end
---@param proxyObj table
---@return table
function M.config(proxyObj)
return proxyObj[CONFIG]
end
return M