kobako 0.1.2 → 0.2.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/Cargo.lock +1 -1
- data/README.md +95 -60
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +1 -1
- data/ext/kobako/src/wasm/cache.rs +39 -1
- data/ext/kobako/src/wasm/dispatch.rs +20 -20
- data/ext/kobako/src/wasm/host_state.rs +261 -34
- data/ext/kobako/src/wasm/instance.rs +467 -272
- data/ext/kobako/src/wasm.rs +50 -19
- data/lib/kobako/capture.rb +46 -0
- data/lib/kobako/codec/decoder.rb +66 -0
- data/lib/kobako/codec/encoder.rb +37 -0
- data/lib/kobako/codec/error.rb +33 -0
- data/lib/kobako/codec/factory.rb +155 -0
- data/lib/kobako/codec/utils.rb +55 -0
- data/lib/kobako/codec.rb +27 -0
- data/lib/kobako/errors.rb +24 -1
- data/lib/kobako/outcome/panic.rb +42 -0
- data/lib/kobako/outcome.rb +133 -0
- data/lib/kobako/rpc/dispatcher.rb +169 -0
- data/lib/kobako/rpc/envelope.rb +118 -0
- data/lib/kobako/{wire/exception.rb → rpc/fault.rb} +6 -4
- data/lib/kobako/{wire → rpc}/handle.rb +4 -2
- data/lib/kobako/{registry → rpc}/handle_table.rb +9 -9
- data/lib/kobako/{registry/service_group.rb → rpc/namespace.rb} +20 -11
- data/lib/kobako/rpc/server.rb +156 -0
- data/lib/kobako/rpc.rb +11 -0
- data/lib/kobako/sandbox.rb +149 -69
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako/wasm.rb +6 -16
- data/lib/kobako.rb +2 -0
- data/sig/kobako/capture.rbs +13 -0
- data/sig/kobako/codec/decoder.rbs +11 -0
- data/sig/kobako/codec/encoder.rbs +7 -0
- data/sig/kobako/codec/error.rbs +18 -0
- data/sig/kobako/codec/factory.rbs +31 -0
- data/sig/kobako/codec/utils.rbs +9 -0
- data/sig/kobako/errors.rbs +52 -0
- data/sig/kobako/outcome/panic.rbs +34 -0
- data/sig/kobako/outcome.rbs +24 -0
- data/sig/kobako/rpc/dispatcher.rbs +33 -0
- data/sig/kobako/rpc/envelope.rbs +51 -0
- data/sig/kobako/rpc/fault.rbs +20 -0
- data/sig/kobako/rpc/handle.rbs +19 -0
- data/sig/kobako/rpc/handle_table.rbs +25 -0
- data/sig/kobako/rpc/namespace.rbs +24 -0
- data/sig/kobako/rpc/server.rbs +37 -0
- data/sig/kobako/rpc.rbs +4 -0
- data/sig/kobako/sandbox.rbs +53 -0
- data/sig/kobako/wasm.rbs +37 -0
- data/sig/kobako.rbs +0 -1
- metadata +37 -17
- data/lib/kobako/registry/dispatcher.rb +0 -168
- data/lib/kobako/registry.rb +0 -160
- data/lib/kobako/sandbox/outcome_decoder.rb +0 -100
- data/lib/kobako/sandbox/output_buffer.rb +0 -79
- data/lib/kobako/wire/codec/decoder.rb +0 -87
- data/lib/kobako/wire/codec/encoder.rb +0 -41
- data/lib/kobako/wire/codec/error.rb +0 -35
- data/lib/kobako/wire/codec/factory.rb +0 -136
- data/lib/kobako/wire/codec.rb +0 -44
- data/lib/kobako/wire/envelope/payloads.rb +0 -145
- data/lib/kobako/wire/envelope.rb +0 -147
- data/lib/kobako/wire.rb +0 -40
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module Outcome
|
|
3
|
+
class Panic
|
|
4
|
+
ORIGIN_SANDBOX: String
|
|
5
|
+
ORIGIN_SERVICE: String
|
|
6
|
+
|
|
7
|
+
attr_reader origin: String
|
|
8
|
+
attr_reader klass: String
|
|
9
|
+
attr_reader message: String
|
|
10
|
+
attr_reader backtrace: Array[String]
|
|
11
|
+
attr_reader details: untyped
|
|
12
|
+
|
|
13
|
+
def initialize: (
|
|
14
|
+
origin: String,
|
|
15
|
+
klass: String,
|
|
16
|
+
message: String,
|
|
17
|
+
?backtrace: Array[String],
|
|
18
|
+
?details: untyped
|
|
19
|
+
) -> void
|
|
20
|
+
|
|
21
|
+
def with: (
|
|
22
|
+
?origin: String,
|
|
23
|
+
?klass: String,
|
|
24
|
+
?message: String,
|
|
25
|
+
?backtrace: Array[String],
|
|
26
|
+
?details: untyped
|
|
27
|
+
) -> Panic
|
|
28
|
+
|
|
29
|
+
def ==: (untyped other) -> bool
|
|
30
|
+
|
|
31
|
+
def hash: () -> Integer
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module Outcome
|
|
3
|
+
TYPE_VALUE: Integer
|
|
4
|
+
TYPE_PANIC: Integer
|
|
5
|
+
|
|
6
|
+
def self?.decode: (String bytes) -> untyped
|
|
7
|
+
|
|
8
|
+
def self?.build_trap_error: (Integer? tag) -> TrapError
|
|
9
|
+
|
|
10
|
+
def self?.split_tag: (String bytes) -> [Integer?, String]
|
|
11
|
+
|
|
12
|
+
def self?.decode_value: (String body) -> untyped
|
|
13
|
+
|
|
14
|
+
def self?.decode_panic: (String body) -> void
|
|
15
|
+
|
|
16
|
+
def self?.parse_panic: (String body) -> Panic
|
|
17
|
+
|
|
18
|
+
def self?.build_panic_error: (Panic panic) -> (SandboxError | ServiceError)
|
|
19
|
+
|
|
20
|
+
def self?.panic_target_class: (Panic panic) -> (singleton(SandboxError) | singleton(ServiceError))
|
|
21
|
+
|
|
22
|
+
def self?.build_wire_violation_error: (String message) -> SandboxError
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
module Dispatcher
|
|
4
|
+
class UndefinedTargetError < StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class DisconnectedTargetError < StandardError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self?.dispatch: (String request_bytes, Server server) -> String
|
|
11
|
+
|
|
12
|
+
def self?.encode_caught_error: (StandardError error) -> String
|
|
13
|
+
|
|
14
|
+
def self?.invoke: (untyped target, String method, Array[untyped] args, Hash[Symbol, untyped] kwargs) -> untyped
|
|
15
|
+
|
|
16
|
+
def self?.resolve_arg: (untyped value, HandleTable handle_table) -> untyped
|
|
17
|
+
|
|
18
|
+
def self?.resolve_target: (String | Kobako::RPC::Handle target, Server server, HandleTable handle_table) -> untyped
|
|
19
|
+
|
|
20
|
+
def self?.resolve_path: (String path, Server server) -> untyped
|
|
21
|
+
|
|
22
|
+
def self?.resolve_handle: (Kobako::RPC::Handle handle, HandleTable handle_table) -> untyped
|
|
23
|
+
|
|
24
|
+
def self?.require_live_object!: (Integer id, HandleTable handle_table) -> untyped
|
|
25
|
+
|
|
26
|
+
def self?.encode_ok: (untyped value, Server server) -> String
|
|
27
|
+
|
|
28
|
+
def self?.wrap_as_handle: (untyped value, Server server) -> Kobako::RPC::Handle
|
|
29
|
+
|
|
30
|
+
def self?.encode_error: (String type, String message) -> String
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
STATUS_OK: Integer
|
|
4
|
+
STATUS_ERROR: Integer
|
|
5
|
+
|
|
6
|
+
class Request
|
|
7
|
+
attr_reader target: String | Kobako::RPC::Handle
|
|
8
|
+
attr_reader method_name: String
|
|
9
|
+
attr_reader args: Array[untyped]
|
|
10
|
+
attr_reader kwargs: Hash[Symbol, untyped]
|
|
11
|
+
|
|
12
|
+
def initialize: (target: String | Kobako::RPC::Handle, method: String, ?args: Array[untyped], ?kwargs: Hash[Symbol, untyped]) -> void
|
|
13
|
+
|
|
14
|
+
def with: (?target: String | Kobako::RPC::Handle, ?method: String, ?args: Array[untyped], ?kwargs: Hash[Symbol, untyped]) -> Request
|
|
15
|
+
|
|
16
|
+
def ==: (untyped other) -> bool
|
|
17
|
+
|
|
18
|
+
def hash: () -> Integer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.encode_request: (Request request) -> String
|
|
22
|
+
|
|
23
|
+
def self.decode_request: (String bytes) -> Request
|
|
24
|
+
|
|
25
|
+
class Response
|
|
26
|
+
attr_reader status: Integer
|
|
27
|
+
attr_reader payload: untyped
|
|
28
|
+
|
|
29
|
+
def self.ok: (untyped value) -> Response
|
|
30
|
+
|
|
31
|
+
def self.error: (Kobako::RPC::Fault fault) -> Response
|
|
32
|
+
|
|
33
|
+
def initialize: (Integer status, untyped payload) -> void
|
|
34
|
+
| (status: Integer, payload: untyped) -> void
|
|
35
|
+
|
|
36
|
+
def with: (?status: Integer, ?payload: untyped) -> Response
|
|
37
|
+
|
|
38
|
+
def ok?: () -> bool
|
|
39
|
+
|
|
40
|
+
def error?: () -> bool
|
|
41
|
+
|
|
42
|
+
def ==: (untyped other) -> bool
|
|
43
|
+
|
|
44
|
+
def hash: () -> Integer
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.encode_response: (Response response) -> String
|
|
48
|
+
|
|
49
|
+
def self.decode_response: (String bytes) -> Response
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
class Fault
|
|
4
|
+
VALID_TYPES: Array[String]
|
|
5
|
+
|
|
6
|
+
attr_reader type: String
|
|
7
|
+
attr_reader message: String
|
|
8
|
+
attr_reader details: untyped
|
|
9
|
+
|
|
10
|
+
def initialize: (String type, String message, untyped details) -> void
|
|
11
|
+
| (type: String, message: String, ?details: untyped) -> void
|
|
12
|
+
|
|
13
|
+
def with: (?type: String, ?message: String, ?details: untyped) -> Fault
|
|
14
|
+
|
|
15
|
+
def ==: (untyped other) -> bool
|
|
16
|
+
|
|
17
|
+
def hash: () -> Integer
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
class Handle
|
|
4
|
+
MIN_ID: Integer
|
|
5
|
+
MAX_ID: Integer
|
|
6
|
+
|
|
7
|
+
attr_reader id: Integer
|
|
8
|
+
|
|
9
|
+
def initialize: (Integer id) -> void
|
|
10
|
+
| (id: Integer) -> void
|
|
11
|
+
|
|
12
|
+
def with: (?id: Integer) -> Handle
|
|
13
|
+
|
|
14
|
+
def ==: (untyped other) -> bool
|
|
15
|
+
|
|
16
|
+
def hash: () -> Integer
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
class HandleTable
|
|
4
|
+
def initialize: (?next_id: Integer) -> void
|
|
5
|
+
|
|
6
|
+
def alloc: (untyped object) -> Integer
|
|
7
|
+
|
|
8
|
+
def fetch: (Integer id) -> untyped
|
|
9
|
+
|
|
10
|
+
def release: (Integer id) -> untyped
|
|
11
|
+
|
|
12
|
+
def reset!: () -> self
|
|
13
|
+
|
|
14
|
+
def mark_disconnected: (Integer id) -> self
|
|
15
|
+
|
|
16
|
+
def size: () -> Integer
|
|
17
|
+
|
|
18
|
+
def include?: (Integer id) -> bool
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def require_bound!: (Integer id) -> void
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
class Namespace
|
|
4
|
+
NAME_PATTERN: Regexp
|
|
5
|
+
|
|
6
|
+
attr_reader name: String
|
|
7
|
+
attr_reader members: Hash[String, untyped]
|
|
8
|
+
|
|
9
|
+
def initialize: (String name) -> void
|
|
10
|
+
|
|
11
|
+
def bind: (Symbol | String member, untyped object) -> self
|
|
12
|
+
|
|
13
|
+
def []: (Symbol | String member) -> untyped
|
|
14
|
+
|
|
15
|
+
def fetch: (Symbol | String member) -> untyped
|
|
16
|
+
|
|
17
|
+
def to_preamble: () -> [String, Array[String]]
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def validate_member_name!: (Symbol | String member) -> String
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module RPC
|
|
3
|
+
class Server
|
|
4
|
+
attr_reader handle_table: HandleTable
|
|
5
|
+
|
|
6
|
+
def initialize: (?handle_table: HandleTable) -> void
|
|
7
|
+
|
|
8
|
+
def define: (Symbol | String name) -> Kobako::RPC::Namespace
|
|
9
|
+
|
|
10
|
+
def lookup: (String target) -> untyped
|
|
11
|
+
|
|
12
|
+
def bound?: (String target) -> bool
|
|
13
|
+
|
|
14
|
+
def namespaces: () -> Array[Kobako::RPC::Namespace]
|
|
15
|
+
|
|
16
|
+
def size: () -> Integer
|
|
17
|
+
|
|
18
|
+
def empty?: () -> bool
|
|
19
|
+
|
|
20
|
+
def to_preamble: () -> Array[[String, Array[String]]]
|
|
21
|
+
|
|
22
|
+
def encoded_preamble: () -> String
|
|
23
|
+
|
|
24
|
+
def seal!: () -> self
|
|
25
|
+
|
|
26
|
+
def sealed?: () -> bool
|
|
27
|
+
|
|
28
|
+
def reset_handles!: () -> HandleTable
|
|
29
|
+
|
|
30
|
+
def dispatch: (String request_bytes) -> String
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def parse_target: (String target) -> [Kobako::RPC::Namespace?, String?, String?]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/sig/kobako/rpc.rbs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
class Sandbox
|
|
3
|
+
DEFAULT_OUTPUT_LIMIT: Integer
|
|
4
|
+
|
|
5
|
+
DEFAULT_TIMEOUT_SECONDS: Float
|
|
6
|
+
|
|
7
|
+
DEFAULT_MEMORY_LIMIT: Integer
|
|
8
|
+
|
|
9
|
+
attr_reader wasm_path: String
|
|
10
|
+
attr_reader instance: Kobako::Wasm::Instance
|
|
11
|
+
attr_reader stdout_limit: Integer
|
|
12
|
+
attr_reader stderr_limit: Integer
|
|
13
|
+
attr_reader timeout: Float?
|
|
14
|
+
attr_reader memory_limit: Integer?
|
|
15
|
+
attr_reader services: Kobako::RPC::Server
|
|
16
|
+
|
|
17
|
+
def initialize: (
|
|
18
|
+
?wasm_path: String?,
|
|
19
|
+
?stdout_limit: Integer?,
|
|
20
|
+
?stderr_limit: Integer?,
|
|
21
|
+
?timeout: (Float | Integer)?,
|
|
22
|
+
?memory_limit: Integer?
|
|
23
|
+
) -> void
|
|
24
|
+
|
|
25
|
+
def stdout: () -> String
|
|
26
|
+
|
|
27
|
+
def stderr: () -> String
|
|
28
|
+
|
|
29
|
+
def stdout_truncated?: () -> bool
|
|
30
|
+
|
|
31
|
+
def stderr_truncated?: () -> bool
|
|
32
|
+
|
|
33
|
+
def define: (Symbol | String name) -> Kobako::RPC::Namespace
|
|
34
|
+
|
|
35
|
+
def run: (String source) -> untyped
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def clear_captures!: () -> void
|
|
40
|
+
|
|
41
|
+
def normalize_timeout: ((Float | Integer)? timeout) -> Float?
|
|
42
|
+
|
|
43
|
+
def normalize_memory_limit: (Integer? memory_limit) -> Integer?
|
|
44
|
+
|
|
45
|
+
def reset_run_state!: () -> void
|
|
46
|
+
|
|
47
|
+
def read_captures!: () -> void
|
|
48
|
+
|
|
49
|
+
def run_guest: (String preamble, String source) -> void
|
|
50
|
+
|
|
51
|
+
def take_result!: () -> untyped
|
|
52
|
+
end
|
|
53
|
+
end
|
data/sig/kobako/wasm.rbs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module Wasm
|
|
3
|
+
class Error < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class ModuleNotBuiltError < Error
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.default_path: () -> String
|
|
10
|
+
|
|
11
|
+
class TimeoutError < Error
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class MemoryLimitError < Error
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Instance
|
|
18
|
+
def self.from_path: (
|
|
19
|
+
String path,
|
|
20
|
+
(Float | Integer)? timeout_seconds,
|
|
21
|
+
Integer? memory_limit,
|
|
22
|
+
Integer? stdout_limit_bytes,
|
|
23
|
+
Integer? stderr_limit_bytes
|
|
24
|
+
) -> Instance
|
|
25
|
+
|
|
26
|
+
def server=: (Kobako::RPC::Server server) -> void
|
|
27
|
+
|
|
28
|
+
def run: (String preamble, String source) -> void
|
|
29
|
+
|
|
30
|
+
def stdout: () -> [String, bool]
|
|
31
|
+
|
|
32
|
+
def stderr: () -> [String, bool]
|
|
33
|
+
|
|
34
|
+
def outcome!: () -> String
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/sig/kobako.rbs
CHANGED
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.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aotokitsuruya
|
|
@@ -61,27 +61,47 @@ files:
|
|
|
61
61
|
- ext/kobako/src/wasm/host_state.rs
|
|
62
62
|
- ext/kobako/src/wasm/instance.rs
|
|
63
63
|
- lib/kobako.rb
|
|
64
|
+
- lib/kobako/capture.rb
|
|
65
|
+
- lib/kobako/codec.rb
|
|
66
|
+
- lib/kobako/codec/decoder.rb
|
|
67
|
+
- lib/kobako/codec/encoder.rb
|
|
68
|
+
- lib/kobako/codec/error.rb
|
|
69
|
+
- lib/kobako/codec/factory.rb
|
|
70
|
+
- lib/kobako/codec/utils.rb
|
|
64
71
|
- lib/kobako/errors.rb
|
|
65
|
-
- lib/kobako/
|
|
66
|
-
- lib/kobako/
|
|
67
|
-
- lib/kobako/
|
|
68
|
-
- lib/kobako/
|
|
72
|
+
- lib/kobako/outcome.rb
|
|
73
|
+
- lib/kobako/outcome/panic.rb
|
|
74
|
+
- lib/kobako/rpc.rb
|
|
75
|
+
- lib/kobako/rpc/dispatcher.rb
|
|
76
|
+
- lib/kobako/rpc/envelope.rb
|
|
77
|
+
- lib/kobako/rpc/fault.rb
|
|
78
|
+
- lib/kobako/rpc/handle.rb
|
|
79
|
+
- lib/kobako/rpc/handle_table.rb
|
|
80
|
+
- lib/kobako/rpc/namespace.rb
|
|
81
|
+
- lib/kobako/rpc/server.rb
|
|
69
82
|
- lib/kobako/sandbox.rb
|
|
70
|
-
- lib/kobako/sandbox/outcome_decoder.rb
|
|
71
|
-
- lib/kobako/sandbox/output_buffer.rb
|
|
72
83
|
- lib/kobako/version.rb
|
|
73
84
|
- lib/kobako/wasm.rb
|
|
74
|
-
- lib/kobako/wire.rb
|
|
75
|
-
- lib/kobako/wire/codec.rb
|
|
76
|
-
- lib/kobako/wire/codec/decoder.rb
|
|
77
|
-
- lib/kobako/wire/codec/encoder.rb
|
|
78
|
-
- lib/kobako/wire/codec/error.rb
|
|
79
|
-
- lib/kobako/wire/codec/factory.rb
|
|
80
|
-
- lib/kobako/wire/envelope.rb
|
|
81
|
-
- lib/kobako/wire/envelope/payloads.rb
|
|
82
|
-
- lib/kobako/wire/exception.rb
|
|
83
|
-
- lib/kobako/wire/handle.rb
|
|
84
85
|
- sig/kobako.rbs
|
|
86
|
+
- sig/kobako/capture.rbs
|
|
87
|
+
- sig/kobako/codec/decoder.rbs
|
|
88
|
+
- sig/kobako/codec/encoder.rbs
|
|
89
|
+
- sig/kobako/codec/error.rbs
|
|
90
|
+
- sig/kobako/codec/factory.rbs
|
|
91
|
+
- sig/kobako/codec/utils.rbs
|
|
92
|
+
- sig/kobako/errors.rbs
|
|
93
|
+
- sig/kobako/outcome.rbs
|
|
94
|
+
- sig/kobako/outcome/panic.rbs
|
|
95
|
+
- sig/kobako/rpc.rbs
|
|
96
|
+
- sig/kobako/rpc/dispatcher.rbs
|
|
97
|
+
- sig/kobako/rpc/envelope.rbs
|
|
98
|
+
- sig/kobako/rpc/fault.rbs
|
|
99
|
+
- sig/kobako/rpc/handle.rbs
|
|
100
|
+
- sig/kobako/rpc/handle_table.rbs
|
|
101
|
+
- sig/kobako/rpc/namespace.rbs
|
|
102
|
+
- sig/kobako/rpc/server.rbs
|
|
103
|
+
- sig/kobako/sandbox.rbs
|
|
104
|
+
- sig/kobako/wasm.rbs
|
|
85
105
|
homepage: https://github.com/elct9620/kobako
|
|
86
106
|
licenses:
|
|
87
107
|
- Apache-2.0
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Kobako
|
|
4
|
-
class Registry
|
|
5
|
-
# Pure-function dispatcher for guest-initiated RPC calls. Decodes a
|
|
6
|
-
# msgpack-encoded Request envelope, resolves the target object through the
|
|
7
|
-
# Registry (path lookup or HandleTable lookup), invokes the method, and
|
|
8
|
-
# returns a msgpack-encoded Response envelope.
|
|
9
|
-
#
|
|
10
|
-
# The module is stateless — all mutable state is threaded through the
|
|
11
|
-
# +registry+ argument so Dispatcher has no instance variables and no side
|
|
12
|
-
# effects beyond mutating the HandleTable via +alloc+ when a non-wire-
|
|
13
|
-
# representable return value must be wrapped ({SPEC.md B-14}[link:../../../SPEC.md]).
|
|
14
|
-
#
|
|
15
|
-
# Entry point:
|
|
16
|
-
#
|
|
17
|
-
# Kobako::Registry::Dispatcher.dispatch(request_bytes, registry)
|
|
18
|
-
# # => msgpack-encoded Response bytes (never raises)
|
|
19
|
-
module Dispatcher
|
|
20
|
-
module_function
|
|
21
|
-
|
|
22
|
-
# Internal sentinel raised when target resolution fails. Mapped to
|
|
23
|
-
# Response.err with type="undefined". Contained at the wire boundary —
|
|
24
|
-
# not part of the public Kobako error taxonomy
|
|
25
|
-
# ({SPEC.md E-xx}[link:../../../SPEC.md]).
|
|
26
|
-
class UndefinedTargetError < StandardError; end
|
|
27
|
-
|
|
28
|
-
# Internal sentinel raised when a Handle target resolves to the
|
|
29
|
-
# +:disconnected+ sentinel in the HandleTable (ABA protection,
|
|
30
|
-
# {SPEC.md E-14}[link:../../../SPEC.md]). Mapped to Response.err with
|
|
31
|
-
# type="disconnected". Contained at the wire boundary.
|
|
32
|
-
class DisconnectedTargetError < StandardError; end
|
|
33
|
-
|
|
34
|
-
# Dispatch a single RPC request and return the encoded response bytes.
|
|
35
|
-
# Called by +Kobako::Registry#dispatch+ which is invoked from the Rust
|
|
36
|
-
# ext inside +__kobako_rpc_call+. +request_bytes+ is the msgpack-encoded
|
|
37
|
-
# Request envelope. +registry+ is the live registry for this run, used
|
|
38
|
-
# to resolve path-based targets via +#lookup+ and to access the
|
|
39
|
-
# +#handle_table+ for Handle-based targets and return-value wrapping.
|
|
40
|
-
# Always returns a binary String — never raises. Any failure during
|
|
41
|
-
# decode, lookup, or method invocation is reified as a Response.err
|
|
42
|
-
# envelope so the guest sees the failure as a normal RPC error rather
|
|
43
|
-
# than a wasm trap
|
|
44
|
-
# ({SPEC.md B-12}[link:../../../SPEC.md]).
|
|
45
|
-
def dispatch(request_bytes, registry)
|
|
46
|
-
value = perform_dispatch(request_bytes, registry)
|
|
47
|
-
encode_ok_or_wrap(value, registry)
|
|
48
|
-
rescue StandardError => e
|
|
49
|
-
encode_dispatch_error(e)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Map an error raised during dispatch to a Response.err envelope.
|
|
53
|
-
# +error+ is the +StandardError+ caught at the dispatch boundary. Returns
|
|
54
|
-
# a msgpack-encoded Response envelope (binary). Four error buckets
|
|
55
|
-
# ({SPEC.md B-12}[link:../../../SPEC.md]): +Wire::Codec::Error+ →
|
|
56
|
-
# type="runtime" (wire decode failed); +DisconnectedTargetError+ →
|
|
57
|
-
# type="disconnected" (E-14); +UndefinedTargetError+ → type="undefined"
|
|
58
|
-
# (E-13); +ArgumentError+ → type="argument" (B-12 arity mismatch);
|
|
59
|
-
# everything else → type="runtime".
|
|
60
|
-
def encode_dispatch_error(error)
|
|
61
|
-
case error
|
|
62
|
-
when Kobako::Wire::Codec::Error then encode_err("runtime", "wire decode failed: #{error.message}")
|
|
63
|
-
when DisconnectedTargetError then encode_err("disconnected", error.message)
|
|
64
|
-
when UndefinedTargetError then encode_err("undefined", error.message)
|
|
65
|
-
when ArgumentError then encode_err("argument", error.message)
|
|
66
|
-
else encode_err("runtime", "#{error.class}: #{error.message}")
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def perform_dispatch(request_bytes, registry)
|
|
71
|
-
request = Kobako::Wire::Envelope.decode_request(request_bytes)
|
|
72
|
-
handle_table = registry.handle_table
|
|
73
|
-
target_object = resolve_target(request.target, registry, handle_table)
|
|
74
|
-
args = request.args.map { |v| resolve_arg(v, handle_table) }
|
|
75
|
-
kwargs = request.kwargs.transform_values { |v| resolve_arg(v, handle_table) }
|
|
76
|
-
invoke(target_object, request.method_name, args, kwargs)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Dispatch +method+ on +target+. +kwargs+ is already Symbol-keyed
|
|
80
|
-
# (the +Envelope::Request+ invariant pins it). The empty-kwargs
|
|
81
|
-
# branch omits the +**+ splat so Ruby 3.x's strict kwargs
|
|
82
|
-
# separation does not reject calls to no-kwarg methods when the
|
|
83
|
-
# wire carries the uniform empty-map shape.
|
|
84
|
-
def invoke(target, method, args, kwargs)
|
|
85
|
-
if kwargs.empty?
|
|
86
|
-
target.public_send(method.to_sym, *args)
|
|
87
|
-
else
|
|
88
|
-
target.public_send(method.to_sym, *args, **kwargs)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# {SPEC.md B-16}[link:../../../SPEC.md] — A Wire::Handle arriving as a positional or keyword
|
|
93
|
-
# argument identifies a host-side object previously allocated by a prior
|
|
94
|
-
# RPC's Handle wrap (B-14). Resolve it back to the Ruby object before
|
|
95
|
-
# the dispatch reaches +public_send+. A Handle whose entry is the
|
|
96
|
-
# +:disconnected+ sentinel (E-14) raises DisconnectedTargetError so
|
|
97
|
-
# the dispatcher emits a Response.err with type="disconnected".
|
|
98
|
-
def resolve_arg(value, handle_table)
|
|
99
|
-
case value
|
|
100
|
-
when Kobako::Wire::Handle
|
|
101
|
-
fetch_live_object(value.id, handle_table)
|
|
102
|
-
else
|
|
103
|
-
value
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Resolve a Request target to the Ruby object the Registry (or
|
|
108
|
-
# HandleTable) holds. String targets go through the Registry;
|
|
109
|
-
# Handle targets (ext 0x01) go through the HandleTable.
|
|
110
|
-
#
|
|
111
|
-
# Target type is already validated by +Wire::Envelope.decode_request+
|
|
112
|
-
# before this method is reached, so no else-branch is needed here —
|
|
113
|
-
# the wire layer is the system boundary that enforces the invariant.
|
|
114
|
-
def resolve_target(target, registry, handle_table)
|
|
115
|
-
case target
|
|
116
|
-
when String
|
|
117
|
-
resolve_path(target, registry)
|
|
118
|
-
when Kobako::Wire::Handle
|
|
119
|
-
resolve_handle(target, handle_table)
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def resolve_path(path, registry)
|
|
124
|
-
registry.lookup(path)
|
|
125
|
-
rescue KeyError => e
|
|
126
|
-
raise UndefinedTargetError, e.message
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def resolve_handle(handle, handle_table)
|
|
130
|
-
fetch_live_object(handle.id, handle_table)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Resolve +id+ through the HandleTable, distinguishing the
|
|
134
|
-
# +:disconnected+ sentinel (E-14) from an unknown id (E-13).
|
|
135
|
-
def fetch_live_object(id, handle_table)
|
|
136
|
-
object = handle_table.fetch(id)
|
|
137
|
-
raise DisconnectedTargetError, "Handle id #{id} is disconnected" if object == :disconnected
|
|
138
|
-
|
|
139
|
-
object
|
|
140
|
-
rescue Kobako::HandleTableError => e
|
|
141
|
-
raise UndefinedTargetError, e.message
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Encode +value+ as a +Response.ok+ envelope. When the value is not
|
|
145
|
-
# wire-representable per {SPEC.md B-13}[link:../../../SPEC.md]'s type
|
|
146
|
-
# mapping, the +UnsupportedType+ rescue routes it through the
|
|
147
|
-
# HandleTable and re-encodes with the Capability Handle in place
|
|
148
|
-
# ({SPEC.md B-14}[link:../../../SPEC.md]). The happy path encodes
|
|
149
|
-
# exactly once.
|
|
150
|
-
def encode_ok_or_wrap(value, registry)
|
|
151
|
-
encode_ok(value)
|
|
152
|
-
rescue Kobako::Wire::Codec::UnsupportedType
|
|
153
|
-
encode_ok(Kobako::Wire::Handle.new(registry.handle_table.alloc(value)))
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def encode_ok(value)
|
|
157
|
-
response = Kobako::Wire::Envelope::Response.ok(value)
|
|
158
|
-
Kobako::Wire::Envelope.encode_response(response)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def encode_err(type, message)
|
|
162
|
-
exception = Kobako::Wire::Exception.new(type: type, message: message)
|
|
163
|
-
response = Kobako::Wire::Envelope::Response.err(exception)
|
|
164
|
-
Kobako::Wire::Envelope.encode_response(response)
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|