kobako 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +71 -0
- data/Cargo.lock +117 -140
- data/README.md +100 -125
- data/ROADMAP.md +23 -22
- data/SECURITY.md +1 -1
- data/crates/kobako-runtime/CHANGELOG.md +31 -0
- data/crates/kobako-runtime/Cargo.toml +2 -2
- data/crates/kobako-runtime/README.md +4 -3
- data/crates/kobako-runtime/src/error.rs +8 -9
- data/crates/kobako-runtime/src/lib.rs +1 -1
- data/crates/kobako-runtime/src/profile.rs +1 -1
- data/crates/kobako-runtime/src/runtime.rs +31 -17
- data/crates/kobako-runtime/src/snapshot.rs +13 -10
- data/crates/kobako-runtime/src/yielder.rs +9 -6
- data/crates/kobako-transport/CHANGELOG.md +28 -0
- data/crates/kobako-transport/Cargo.toml +1 -1
- data/crates/kobako-transport/README.md +21 -12
- data/crates/kobako-transport/src/abi.rs +11 -14
- data/crates/kobako-transport/src/envelope/bytes.rs +18 -6
- data/crates/kobako-transport/src/envelope/compile_reply.rs +139 -0
- data/crates/kobako-transport/src/envelope/outcome.rs +17 -16
- data/crates/kobako-transport/src/envelope/preamble.rs +513 -0
- data/crates/kobako-transport/src/envelope/reply.rs +77 -53
- data/crates/kobako-transport/src/envelope/request.rs +295 -0
- data/crates/kobako-transport/src/envelope/run.rs +1 -2
- data/crates/kobako-transport/src/envelope/tag.rs +49 -0
- data/crates/kobako-transport/src/envelope/unsupported.rs +105 -0
- data/crates/kobako-transport/src/envelope.rs +19 -12
- data/crates/kobako-transport/src/lib.rs +0 -2
- data/crates/kobako-wasmtime/CHANGELOG.md +44 -0
- data/crates/kobako-wasmtime/Cargo.toml +7 -5
- data/crates/kobako-wasmtime/README.md +2 -2
- data/crates/kobako-wasmtime/src/abi.rs +5 -8
- data/crates/kobako-wasmtime/src/ambient.rs +2 -2
- data/crates/kobako-wasmtime/src/cache.rs +25 -59
- data/crates/kobako-wasmtime/src/capture.rs +4 -11
- data/crates/kobako-wasmtime/src/config.rs +11 -14
- data/crates/kobako-wasmtime/src/dispatch.rs +70 -80
- data/crates/kobako-wasmtime/src/driver.rs +133 -86
- data/crates/kobako-wasmtime/src/exports.rs +88 -34
- data/crates/kobako-wasmtime/src/guest_mem.rs +145 -138
- data/crates/kobako-wasmtime/src/instance_pre.rs +11 -22
- data/crates/kobako-wasmtime/src/invocation.rs +55 -372
- data/crates/kobako-wasmtime/src/io.rs +286 -0
- data/crates/kobako-wasmtime/src/lib.rs +3 -24
- data/crates/kobako-wasmtime/src/limiter.rs +253 -0
- data/crates/kobako-wasmtime/src/trap.rs +32 -45
- data/crates/kobako-wasmtime/tests/preamble_flags.rs +69 -0
- data/crates/kobako-wasmtime/tests/snippet_compile.rs +94 -0
- data/crates/kobako-wasmtime/tests/support/mod.rs +34 -0
- data/crates/kobako-wasmtime/tests/unsupported_call.rs +50 -0
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +2 -2
- data/ext/kobako/src/runtime/bridge.rs +38 -47
- data/ext/kobako/src/runtime/errors.rs +26 -32
- data/ext/kobako/src/runtime/gvl.rs +4 -12
- data/ext/kobako/src/runtime.rs +169 -212
- data/lib/kobako/capture.rb +1 -4
- data/lib/kobako/catalog/extensions.rb +21 -59
- data/lib/kobako/catalog/flags.rb +41 -0
- data/lib/kobako/catalog/handles.rb +7 -54
- data/lib/kobako/catalog/services.rb +7 -61
- data/lib/kobako/catalog/snippets.rb +42 -66
- data/lib/kobako/catalog.rb +2 -10
- data/lib/kobako/codec/decoder.rb +9 -28
- data/lib/kobako/codec/encoder.rb +3 -22
- data/lib/kobako/codec/error.rb +6 -27
- data/lib/kobako/codec/ext_types.rb +72 -94
- data/lib/kobako/codec/handle_walk.rb +65 -130
- data/lib/kobako/codec/nesting.rb +3 -8
- data/lib/kobako/codec/state.rb +4 -10
- data/lib/kobako/codec/utils.rb +6 -34
- data/lib/kobako/codec.rb +3 -22
- data/lib/kobako/constant_name.rb +8 -0
- data/lib/kobako/context.rb +51 -112
- data/lib/kobako/errors.rb +51 -127
- data/lib/kobako/execution.rb +16 -21
- data/lib/kobako/extension.rb +23 -40
- data/lib/kobako/handle.rb +7 -12
- data/lib/kobako/outcome.rb +51 -80
- data/lib/kobako/payload/arguments.rb +1 -16
- data/lib/kobako/payload.rb +4 -12
- data/lib/kobako/pool.rb +23 -53
- data/lib/kobako/runtime.rb +7 -21
- data/lib/kobako/sandbox.rb +96 -133
- data/lib/kobako/sandbox_options.rb +38 -84
- data/lib/kobako/snippet/binary.rb +1 -16
- data/lib/kobako/snippet/source.rb +1 -16
- data/lib/kobako/snippet.rb +1 -9
- data/lib/kobako/transport/call.rb +1 -14
- data/lib/kobako/transport/dispatcher.rb +112 -195
- data/lib/kobako/transport/error.rb +6 -20
- data/lib/kobako/transport/exposure.rb +5 -10
- data/lib/kobako/transport/reflection.rb +39 -50
- data/lib/kobako/transport/run.rb +17 -71
- data/lib/kobako/transport/yielder.rb +21 -73
- data/lib/kobako/transport.rb +3 -15
- data/lib/kobako/unresolved.rb +4 -11
- data/lib/kobako/usage.rb +2 -6
- data/lib/kobako/version.rb +1 -1
- data/sig/kobako/catalog/extensions.rbs +2 -2
- data/sig/kobako/catalog/flags.rbs +17 -0
- data/sig/kobako/catalog/services.rbs +0 -6
- data/sig/kobako/catalog/snippets.rbs +4 -4
- data/sig/kobako/codec/ext_types.rbs +10 -8
- data/sig/kobako/codec/handle_walk.rbs +9 -7
- data/sig/kobako/codec/utils.rbs +2 -2
- data/sig/kobako/codec.rbs +2 -2
- data/sig/kobako/constant_name.rbs +3 -0
- data/sig/kobako/context.rbs +2 -3
- data/sig/kobako/errors.rbs +6 -0
- data/sig/kobako/outcome.rbs +6 -8
- data/sig/kobako/runtime.rbs +12 -8
- data/sig/kobako/sandbox.rbs +4 -0
- data/sig/kobako/sandbox_options.rbs +2 -6
- data/sig/kobako/transport/dispatcher.rbs +14 -18
- data/sig/kobako/transport/reflection.rbs +5 -3
- data/sig/kobako/transport/run.rbs +1 -3
- data/sig/kobako/transport/yielder.rbs +3 -3
- data/sig/kobako/transport.rbs +7 -6
- metadata +16 -4
- data/crates/kobako-transport/src/envelope/invocation_frames.rs +0 -241
- data/crates/kobako-wasmtime/src/frames.rs +0 -273
- data/rust-toolchain.toml +0 -15
data/sig/kobako/runtime.rbs
CHANGED
|
@@ -15,20 +15,28 @@ module Kobako
|
|
|
15
15
|
def eval: (
|
|
16
16
|
Kobako::Transport::dispatch_proc dispatch,
|
|
17
17
|
Array[String] paths,
|
|
18
|
-
|
|
19
|
-
Array[Kobako::Catalog::
|
|
18
|
+
Array[Kobako::Catalog::Snippets::tuple] snippets,
|
|
19
|
+
Array[Kobako::Catalog::Flags::tuple] flags,
|
|
20
|
+
String source
|
|
20
21
|
) -> Kobako::Runtime::Snapshot
|
|
21
22
|
|
|
22
23
|
def run: (
|
|
23
24
|
Kobako::Transport::dispatch_proc dispatch,
|
|
24
25
|
Array[String] paths,
|
|
25
26
|
Array[Kobako::Catalog::Snippets::tuple] snippets,
|
|
27
|
+
Array[Kobako::Catalog::Flags::tuple] flags,
|
|
26
28
|
String entrypoint,
|
|
27
29
|
String payload
|
|
28
30
|
) -> Kobako::Runtime::Snapshot
|
|
29
31
|
|
|
30
32
|
def profile: () -> Symbol
|
|
31
33
|
|
|
34
|
+
def compile: (
|
|
35
|
+
Array[String] paths,
|
|
36
|
+
Array[Kobako::Catalog::Snippets::tuple] snippets,
|
|
37
|
+
Array[Kobako::Catalog::Flags::tuple] flags
|
|
38
|
+
) -> Array[String]?
|
|
39
|
+
|
|
32
40
|
# Frame-scoped guest re-entry handle the ext hands the dispatch Proc as
|
|
33
41
|
# its last argument — the production conformer of
|
|
34
42
|
# +Kobako::Transport::_GuestYielder+, answering the Yield Reply already
|
|
@@ -39,13 +47,9 @@ module Kobako
|
|
|
39
47
|
|
|
40
48
|
# One invocation's result — the whole Snapshot the driver produced.
|
|
41
49
|
class Snapshot
|
|
42
|
-
def outcome: () -> [
|
|
43
|
-
|
|
44
|
-
def trapped?: () -> bool
|
|
45
|
-
|
|
46
|
-
def trap_kind: () -> Symbol?
|
|
50
|
+
def outcome: () -> [String, Kobako::Outcome::panic_fields?]
|
|
47
51
|
|
|
48
|
-
def
|
|
52
|
+
def trap_error: () -> Kobako::TrapError?
|
|
49
53
|
|
|
50
54
|
def wall_time: () -> Float
|
|
51
55
|
|
data/sig/kobako/sandbox.rbs
CHANGED
|
@@ -27,6 +27,8 @@ module Kobako
|
|
|
27
27
|
def preload: (code: String, name: Symbol | String) -> Kobako::Sandbox
|
|
28
28
|
| (binary: String) -> Kobako::Sandbox
|
|
29
29
|
|
|
30
|
+
def flag: (Symbol | String name, ?String value, ?advisory: bool) -> Kobako::Sandbox
|
|
31
|
+
|
|
30
32
|
def run: (Symbol | String target, *untyped args, **untyped kwargs) ?{ (Kobako::Context) -> void } -> Kobako::Execution
|
|
31
33
|
|
|
32
34
|
def eval: (String code) ?{ (Kobako::Context) -> void } -> Kobako::Execution
|
|
@@ -37,6 +39,8 @@ module Kobako
|
|
|
37
39
|
|
|
38
40
|
def new_invocation: () -> Kobako::Context
|
|
39
41
|
|
|
42
|
+
def refuse_once_invoked!: (String verb) -> void
|
|
43
|
+
|
|
40
44
|
def begin_invocation!: () -> void
|
|
41
45
|
end
|
|
42
46
|
end
|
|
@@ -39,12 +39,8 @@ module Kobako
|
|
|
39
39
|
|
|
40
40
|
def normalize_timeout: ((Float | Integer)? timeout) -> Float?
|
|
41
41
|
|
|
42
|
-
def
|
|
42
|
+
def normalize_byte_limit: (Integer? limit, String name) -> Integer?
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
def normalize_profile: (untyped profile) -> Symbol
|
|
47
|
-
|
|
48
|
-
def normalize_gvl: (untyped gvl) -> Symbol
|
|
44
|
+
def normalize_choice: (untyped value, Array[Symbol] choices, String name) -> Symbol
|
|
49
45
|
end
|
|
50
46
|
end
|
|
@@ -11,37 +11,33 @@ module Kobako
|
|
|
11
11
|
|
|
12
12
|
OWN_FAULTS: Hash[singleton(StandardError), String]
|
|
13
13
|
|
|
14
|
+
def self.dispatch: (Kobako::Transport::Call call, Kobako::Transport::_ServiceResolver resolver, Kobako::Transport::_HandleTable handles, Kobako::Transport::_GuestYielder guest_yielder) -> [bool, String, String?]
|
|
14
15
|
|
|
16
|
+
private
|
|
15
17
|
|
|
18
|
+
def self.run: (Kobako::Transport::Call call, Kobako::Transport::_ServiceResolver resolver, Kobako::Transport::_HandleTable handles, Kobako::Transport::Yielder? yielder) -> untyped
|
|
16
19
|
|
|
17
|
-
def self
|
|
20
|
+
def self.decode_arguments: (String payload) -> [Kobako::Payload::Arguments, bool]
|
|
18
21
|
|
|
19
|
-
def self
|
|
22
|
+
def self.resolve_call_args: (Kobako::Payload::Arguments arguments, Kobako::Codec::_HandleTable handles, bool carried_handle) -> [Array[untyped], Hash[Symbol, untyped]]
|
|
20
23
|
|
|
21
|
-
def self
|
|
24
|
+
def self.caught_fault: (StandardError error, Kobako::Transport::Yielder? yielder) -> [String, String]
|
|
22
25
|
|
|
23
|
-
def self
|
|
26
|
+
def self.invoke: (Kobako::Transport::Exposure exposure, String method, Array[untyped] args, Hash[Symbol, untyped] kwargs, Kobako::Transport::Yielder? yielder) -> untyped
|
|
24
27
|
|
|
25
|
-
def self
|
|
28
|
+
def self.reject_unreachable!: (Kobako::Transport::Exposure exposure, Symbol name) -> void
|
|
26
29
|
|
|
27
|
-
def self
|
|
30
|
+
def self.resolve_arg: (untyped value, Kobako::Codec::_HandleTable handles) -> untyped
|
|
28
31
|
|
|
29
|
-
def self
|
|
32
|
+
def self.resolve_target: (String | Integer target, Kobako::Transport::_ServiceResolver resolver, Kobako::Transport::_HandleTable handles) -> Kobako::Transport::Exposure
|
|
30
33
|
|
|
34
|
+
def self.resolve_path: (String path, Kobako::Transport::_ServiceResolver resolver) -> Kobako::Transport::Exposure
|
|
31
35
|
|
|
32
|
-
def self
|
|
36
|
+
def self.resolve_handle: (Integer id, Kobako::Transport::_HandleTable handles) -> Kobako::Transport::Exposure
|
|
33
37
|
|
|
34
|
-
def self
|
|
38
|
+
def self.encode_ok: (untyped value, Kobako::Codec::_HandleTable handles) -> String
|
|
35
39
|
|
|
36
|
-
def self
|
|
37
|
-
|
|
38
|
-
def self?.resolve_handle: (Integer id, Kobako::Transport::_HandleTable handler) -> Kobako::Transport::Exposure
|
|
39
|
-
|
|
40
|
-
def self?.encode_ok: (untyped value, Kobako::Codec::_HandleTable handler) -> String
|
|
41
|
-
|
|
42
|
-
def self?.wrap_as_handle: (untyped value, Kobako::Codec::_HandleTable handler) -> Kobako::Handle
|
|
43
|
-
|
|
44
|
-
def self?.fault: (String type, String message) -> [String, String]
|
|
40
|
+
def self.fault: (String type, String message) -> [String, String]
|
|
45
41
|
end
|
|
46
42
|
end
|
|
47
43
|
end
|
|
@@ -5,11 +5,13 @@ module Kobako
|
|
|
5
5
|
GADGET_OWNERS: Array[Module]
|
|
6
6
|
CALLABLE_ALLOW: Array[Symbol]
|
|
7
7
|
|
|
8
|
-
def self
|
|
8
|
+
def self.refusal: (Kobako::Transport::Exposure exposure, Symbol name) -> String?
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
private
|
|
11
11
|
|
|
12
|
-
def self
|
|
12
|
+
def self.ambient_refusal: (untyped target, Symbol name) -> String?
|
|
13
|
+
|
|
14
|
+
def self.ambient_owner?: (Module owner, untyped target) -> bool
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Transport
|
|
3
3
|
class Run < Data
|
|
4
|
-
NAME_PATTERN: Regexp
|
|
5
|
-
|
|
6
4
|
attr_reader entrypoint: Symbol
|
|
7
5
|
attr_reader args: Array[Kobako::Codec::wire_value]
|
|
8
6
|
attr_reader kwargs: Hash[Symbol, Kobako::Codec::wire_value]
|
|
@@ -11,7 +9,7 @@ module Kobako
|
|
|
11
9
|
|
|
12
10
|
def initialize: (entrypoint: Symbol | String, ?args: Array[untyped], ?kwargs: Hash[untyped, untyped]) -> void
|
|
13
11
|
|
|
14
|
-
def payload: (Kobako::Codec::_HandleTable
|
|
12
|
+
def payload: (Kobako::Codec::_HandleTable handles) -> String
|
|
15
13
|
|
|
16
14
|
private
|
|
17
15
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Transport
|
|
3
3
|
class Yielder
|
|
4
|
-
@
|
|
4
|
+
@guest_yielder: Kobako::Transport::_GuestYielder
|
|
5
5
|
@break_tag: Symbol
|
|
6
|
-
@
|
|
6
|
+
@handles: Kobako::Codec::_HandleTable
|
|
7
7
|
@active: bool
|
|
8
8
|
@raised: Kobako::BlockError?
|
|
9
9
|
|
|
10
|
-
def initialize: (Kobako::Transport::_GuestYielder
|
|
10
|
+
def initialize: (Kobako::Transport::_GuestYielder guest_yielder, Symbol break_tag, Kobako::Codec::_HandleTable handles) -> void
|
|
11
11
|
|
|
12
12
|
def fault_text: (Exception error) -> String?
|
|
13
13
|
|
data/sig/kobako/transport.rbs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Transport
|
|
3
3
|
# The guest re-entry callable a dispatch hands to a Yielder: invoked
|
|
4
|
-
# with the encoded yield args, it returns the
|
|
4
|
+
# with the encoded yield args, it returns the decoded Yield Reply as an
|
|
5
|
+
# +[arm, body, klass]+ triple.
|
|
5
6
|
# The ext's Kobako::Runtime::GuestYielder is the production conformer;
|
|
6
7
|
# modelled structurally so the Transport layer needs no upward
|
|
7
8
|
# dependency on Runtime.
|
|
@@ -15,11 +16,11 @@ module Kobako
|
|
|
15
16
|
# consumer (Runtime) cannot declare it differently.
|
|
16
17
|
type dispatch_proc = ^(String | Integer, String, bool, String, _GuestYielder) -> [bool, String, String?]
|
|
17
18
|
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# layer needs no upward dependency on
|
|
22
|
-
interface
|
|
19
|
+
# What a dispatch resolves constant-path targets against. The
|
|
20
|
+
# invocation's Kobako::Context is the production conformer, so its
|
|
21
|
+
# overrides answer before the Sandbox's bindings; modelled structurally
|
|
22
|
+
# so the Transport layer needs no upward dependency on Orchestration.
|
|
23
|
+
interface _ServiceResolver
|
|
23
24
|
def lookup: (String target) -> Exposure
|
|
24
25
|
end
|
|
25
26
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kobako
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.28.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aotokitsuruya
|
|
@@ -72,12 +72,16 @@ files:
|
|
|
72
72
|
- crates/kobako-transport/src/envelope.rs
|
|
73
73
|
- crates/kobako-transport/src/envelope/bytes.rs
|
|
74
74
|
- crates/kobako-transport/src/envelope/call.rs
|
|
75
|
+
- crates/kobako-transport/src/envelope/compile_reply.rs
|
|
75
76
|
- crates/kobako-transport/src/envelope/error_record.rs
|
|
76
77
|
- crates/kobako-transport/src/envelope/fault.rs
|
|
77
|
-
- crates/kobako-transport/src/envelope/invocation_frames.rs
|
|
78
78
|
- crates/kobako-transport/src/envelope/outcome.rs
|
|
79
|
+
- crates/kobako-transport/src/envelope/preamble.rs
|
|
79
80
|
- crates/kobako-transport/src/envelope/reply.rs
|
|
81
|
+
- crates/kobako-transport/src/envelope/request.rs
|
|
80
82
|
- crates/kobako-transport/src/envelope/run.rs
|
|
83
|
+
- crates/kobako-transport/src/envelope/tag.rs
|
|
84
|
+
- crates/kobako-transport/src/envelope/unsupported.rs
|
|
81
85
|
- crates/kobako-transport/src/lib.rs
|
|
82
86
|
- crates/kobako-wasmtime/CHANGELOG.md
|
|
83
87
|
- crates/kobako-wasmtime/Cargo.toml
|
|
@@ -90,12 +94,17 @@ files:
|
|
|
90
94
|
- crates/kobako-wasmtime/src/dispatch.rs
|
|
91
95
|
- crates/kobako-wasmtime/src/driver.rs
|
|
92
96
|
- crates/kobako-wasmtime/src/exports.rs
|
|
93
|
-
- crates/kobako-wasmtime/src/frames.rs
|
|
94
97
|
- crates/kobako-wasmtime/src/guest_mem.rs
|
|
95
98
|
- crates/kobako-wasmtime/src/instance_pre.rs
|
|
96
99
|
- crates/kobako-wasmtime/src/invocation.rs
|
|
100
|
+
- crates/kobako-wasmtime/src/io.rs
|
|
97
101
|
- crates/kobako-wasmtime/src/lib.rs
|
|
102
|
+
- crates/kobako-wasmtime/src/limiter.rs
|
|
98
103
|
- crates/kobako-wasmtime/src/trap.rs
|
|
104
|
+
- crates/kobako-wasmtime/tests/preamble_flags.rs
|
|
105
|
+
- crates/kobako-wasmtime/tests/snippet_compile.rs
|
|
106
|
+
- crates/kobako-wasmtime/tests/support/mod.rs
|
|
107
|
+
- crates/kobako-wasmtime/tests/unsupported_call.rs
|
|
99
108
|
- data/kobako.wasm
|
|
100
109
|
- ext/kobako/Cargo.toml
|
|
101
110
|
- ext/kobako/extconf.rb
|
|
@@ -108,6 +117,7 @@ files:
|
|
|
108
117
|
- lib/kobako/capture.rb
|
|
109
118
|
- lib/kobako/catalog.rb
|
|
110
119
|
- lib/kobako/catalog/extensions.rb
|
|
120
|
+
- lib/kobako/catalog/flags.rb
|
|
111
121
|
- lib/kobako/catalog/handles.rb
|
|
112
122
|
- lib/kobako/catalog/services.rb
|
|
113
123
|
- lib/kobako/catalog/snippets.rb
|
|
@@ -120,6 +130,7 @@ files:
|
|
|
120
130
|
- lib/kobako/codec/nesting.rb
|
|
121
131
|
- lib/kobako/codec/state.rb
|
|
122
132
|
- lib/kobako/codec/utils.rb
|
|
133
|
+
- lib/kobako/constant_name.rb
|
|
123
134
|
- lib/kobako/context.rb
|
|
124
135
|
- lib/kobako/errors.rb
|
|
125
136
|
- lib/kobako/execution.rb
|
|
@@ -147,11 +158,11 @@ files:
|
|
|
147
158
|
- lib/kobako/usage.rb
|
|
148
159
|
- lib/kobako/version.rb
|
|
149
160
|
- release-please-config.json
|
|
150
|
-
- rust-toolchain.toml
|
|
151
161
|
- sig/kobako.rbs
|
|
152
162
|
- sig/kobako/capture.rbs
|
|
153
163
|
- sig/kobako/catalog.rbs
|
|
154
164
|
- sig/kobako/catalog/extensions.rbs
|
|
165
|
+
- sig/kobako/catalog/flags.rbs
|
|
155
166
|
- sig/kobako/catalog/handles.rbs
|
|
156
167
|
- sig/kobako/catalog/services.rbs
|
|
157
168
|
- sig/kobako/catalog/snippets.rbs
|
|
@@ -164,6 +175,7 @@ files:
|
|
|
164
175
|
- sig/kobako/codec/nesting.rbs
|
|
165
176
|
- sig/kobako/codec/state.rbs
|
|
166
177
|
- sig/kobako/codec/utils.rbs
|
|
178
|
+
- sig/kobako/constant_name.rbs
|
|
167
179
|
- sig/kobako/context.rbs
|
|
168
180
|
- sig/kobako/errors.rbs
|
|
169
181
|
- sig/kobako/execution.rbs
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
//! The invocation frames — Frame 1's bound constant paths and Frame 3's
|
|
2
|
-
//! preloaded snippets, the two both entry points read before running
|
|
3
|
-
//! anything. The numbering skips Frame 2 because the `#eval` user source
|
|
4
|
-
//! is raw UTF-8 with no envelope of its own.
|
|
5
|
-
//!
|
|
6
|
-
//! Both are mandatory-presence even when empty, so a reader never has to
|
|
7
|
-
//! tell an absent frame from an empty one, and each frame's length reaches
|
|
8
|
-
//! the guest from the channel's own prefix rather than from the envelope.
|
|
9
|
-
|
|
10
|
-
use super::bytes::{Reader, Writer};
|
|
11
|
-
use super::DecodeError;
|
|
12
|
-
|
|
13
|
-
const SNIPPET_SOURCE: u8 = 0;
|
|
14
|
-
const SNIPPET_BYTECODE: u8 = 1;
|
|
15
|
-
|
|
16
|
-
/// Frame 1 — the bound constant paths the guest installs proxies from.
|
|
17
|
-
/// Always present; an empty list means no Service is bound.
|
|
18
|
-
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
|
19
|
-
pub struct Bindings {
|
|
20
|
-
pub paths: Vec<String>,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
impl Bindings {
|
|
24
|
-
pub fn decode(bytes: &[u8]) -> Result<Self, DecodeError> {
|
|
25
|
-
let mut reader = Reader::new(bytes);
|
|
26
|
-
let paths = reader.text_list()?;
|
|
27
|
-
reader.finish()?;
|
|
28
|
-
Ok(Bindings { paths })
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
pub fn encode(&self) -> Vec<u8> {
|
|
32
|
-
let mut writer = Writer::new();
|
|
33
|
-
writer.list(&self.paths);
|
|
34
|
-
writer.into_bytes()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/// One preloaded snippet. Source carries the filename the guest compiles
|
|
39
|
-
/// under; bytecode does not, because its filename — when it has one — lives
|
|
40
|
-
/// in the bytecode's own debug section.
|
|
41
|
-
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
42
|
-
pub enum Snippet {
|
|
43
|
-
Source { name: String, body: String },
|
|
44
|
-
Bytecode { body: Vec<u8> },
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/// Frame 3 — the preloaded snippets, in insertion order. Always present;
|
|
48
|
-
/// a zero count means nothing was preloaded.
|
|
49
|
-
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
|
50
|
-
pub struct Snippets {
|
|
51
|
-
pub entries: Vec<Snippet>,
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
impl Snippets {
|
|
55
|
-
pub fn decode(bytes: &[u8]) -> Result<Self, DecodeError> {
|
|
56
|
-
let mut reader = Reader::new(bytes);
|
|
57
|
-
let count = reader.u32()? as usize;
|
|
58
|
-
// Each entry costs at least a kind byte, so a count past the bytes
|
|
59
|
-
// left cannot be satisfied; refusing it bounds the allocation.
|
|
60
|
-
if count > reader.remaining().len() {
|
|
61
|
-
return Err(DecodeError::new(
|
|
62
|
-
"Frame 3 declares more entries than the frame holds",
|
|
63
|
-
));
|
|
64
|
-
}
|
|
65
|
-
let mut entries = Vec::with_capacity(count);
|
|
66
|
-
for _ in 0..count {
|
|
67
|
-
entries.push(match reader.u8()? {
|
|
68
|
-
SNIPPET_SOURCE => Snippet::Source {
|
|
69
|
-
name: reader.text()?.to_owned(),
|
|
70
|
-
body: reader.text()?.to_owned(),
|
|
71
|
-
},
|
|
72
|
-
SNIPPET_BYTECODE => Snippet::Bytecode {
|
|
73
|
-
body: reader.bytes()?.to_vec(),
|
|
74
|
-
},
|
|
75
|
-
_ => return Err(DecodeError::new("Frame 3 snippet kind must be 0 or 1")),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
reader.finish()?;
|
|
79
|
-
Ok(Snippets { entries })
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
pub fn encode(&self) -> Vec<u8> {
|
|
83
|
-
let mut writer = Writer::new();
|
|
84
|
-
writer.u32(self.entries.len() as u32);
|
|
85
|
-
for entry in &self.entries {
|
|
86
|
-
match entry {
|
|
87
|
-
Snippet::Source { name, body } => {
|
|
88
|
-
writer
|
|
89
|
-
.u8(SNIPPET_SOURCE)
|
|
90
|
-
.bytes(name.as_bytes())
|
|
91
|
-
.bytes(body.as_bytes());
|
|
92
|
-
}
|
|
93
|
-
Snippet::Bytecode { body } => {
|
|
94
|
-
writer.u8(SNIPPET_BYTECODE).bytes(body);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
writer.into_bytes()
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
#[cfg(test)]
|
|
103
|
-
mod tests {
|
|
104
|
-
use super::*;
|
|
105
|
-
|
|
106
|
-
// @behavior WE-050
|
|
107
|
-
#[test]
|
|
108
|
-
fn empty_bindings_round_trip() {
|
|
109
|
-
let encoded = Bindings::default().encode();
|
|
110
|
-
assert_eq!(
|
|
111
|
-
Bindings::decode(&encoded),
|
|
112
|
-
Ok(Bindings::default()),
|
|
113
|
-
"a Sandbox with no bindings must send a present, empty Frame 1"
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// @behavior WE-051
|
|
118
|
-
#[test]
|
|
119
|
-
fn bindings_round_trip_every_path() {
|
|
120
|
-
let bindings = Bindings {
|
|
121
|
-
paths: vec!["MyService::KV".into(), "File".into()],
|
|
122
|
-
};
|
|
123
|
-
let encoded = bindings.encode();
|
|
124
|
-
assert_eq!(
|
|
125
|
-
Bindings::decode(&encoded),
|
|
126
|
-
Ok(bindings),
|
|
127
|
-
"Frame 1 must carry every bound path in order"
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// @behavior WE-052
|
|
132
|
-
#[test]
|
|
133
|
-
fn snippets_round_trip_both_kinds_in_order() {
|
|
134
|
-
let snippets = Snippets {
|
|
135
|
-
entries: vec![
|
|
136
|
-
Snippet::Source {
|
|
137
|
-
name: "Helper".into(),
|
|
138
|
-
body: "def helper; end".into(),
|
|
139
|
-
},
|
|
140
|
-
Snippet::Bytecode {
|
|
141
|
-
body: vec![0x52, 0x49, 0x54, 0x45],
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
};
|
|
145
|
-
let encoded = snippets.encode();
|
|
146
|
-
assert_eq!(
|
|
147
|
-
Snippets::decode(&encoded),
|
|
148
|
-
Ok(snippets),
|
|
149
|
-
"Frame 3 must carry source and bytecode entries in insertion order"
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// @behavior WE-053
|
|
154
|
-
#[test]
|
|
155
|
-
fn an_empty_snippet_table_round_trips() {
|
|
156
|
-
let encoded = Snippets::default().encode();
|
|
157
|
-
assert_eq!(
|
|
158
|
-
Snippets::decode(&encoded),
|
|
159
|
-
Ok(Snippets::default()),
|
|
160
|
-
"a Sandbox with no preloads must send a present, zero-count Frame 3"
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// @behavior WE-054
|
|
165
|
-
#[test]
|
|
166
|
-
fn golden_layout_pins_the_bindings_as_a_counted_list() {
|
|
167
|
-
let bindings = Bindings {
|
|
168
|
-
paths: vec!["A".into()],
|
|
169
|
-
};
|
|
170
|
-
assert_eq!(
|
|
171
|
-
bindings.encode(),
|
|
172
|
-
vec![
|
|
173
|
-
0, 0, 0, 1, // path count
|
|
174
|
-
0, 0, 0, 1, b'A',
|
|
175
|
-
],
|
|
176
|
-
"Frame 1 must be a counted list of paths, so the count precedes the first entry"
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// @behavior WE-055
|
|
181
|
-
#[test]
|
|
182
|
-
fn golden_layout_pins_the_snippet_entry_shape() {
|
|
183
|
-
let snippets = Snippets {
|
|
184
|
-
entries: vec![
|
|
185
|
-
Snippet::Source {
|
|
186
|
-
name: "N".into(),
|
|
187
|
-
body: "b".into(),
|
|
188
|
-
},
|
|
189
|
-
Snippet::Bytecode { body: vec![0x52] },
|
|
190
|
-
],
|
|
191
|
-
};
|
|
192
|
-
assert_eq!(
|
|
193
|
-
snippets.encode(),
|
|
194
|
-
vec![
|
|
195
|
-
0, 0, 0, 2, // entry count
|
|
196
|
-
0, // kind: source
|
|
197
|
-
0, 0, 0, 1, b'N', // name, source only
|
|
198
|
-
0, 0, 0, 1, b'b', // body
|
|
199
|
-
1, // kind: bytecode
|
|
200
|
-
0, 0, 0, 1, 0x52, // body, no name
|
|
201
|
-
],
|
|
202
|
-
"a source entry must encode as kind byte 0 with a name and a bytecode entry as \
|
|
203
|
-
kind byte 1 with none, so the two stay distinguishable by their tag alone"
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// @behavior WE-056
|
|
208
|
-
#[test]
|
|
209
|
-
fn an_unknown_snippet_kind_is_refused() {
|
|
210
|
-
let bytes = {
|
|
211
|
-
let mut w = Writer::new();
|
|
212
|
-
w.u32(1).u8(9);
|
|
213
|
-
w.into_bytes()
|
|
214
|
-
};
|
|
215
|
-
assert!(
|
|
216
|
-
Snippets::decode(&bytes).is_err(),
|
|
217
|
-
"a Frame 3 snippet kind that is neither source nor bytecode must be rejected"
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// @behavior WE-057
|
|
222
|
-
#[test]
|
|
223
|
-
fn a_snippet_count_the_frame_cannot_satisfy_is_refused() {
|
|
224
|
-
let bytes = [0xff, 0xff, 0xff, 0xff];
|
|
225
|
-
assert!(
|
|
226
|
-
Snippets::decode(&bytes).is_err(),
|
|
227
|
-
"a Frame 3 count larger than the frame must be rejected before any allocation"
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// @behavior WE-058
|
|
232
|
-
#[test]
|
|
233
|
-
fn trailing_bytes_after_a_frame_are_refused() {
|
|
234
|
-
let mut encoded = Bindings::default().encode();
|
|
235
|
-
encoded.push(0);
|
|
236
|
-
assert!(
|
|
237
|
-
Bindings::decode(&encoded).is_err(),
|
|
238
|
-
"bytes past Frame 1's last field must fail loudly as a framing desync"
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
}
|