use protobuf for python/rust bridge

If we go ahead with betterproto on the Python side, it will mean
bumping the minimum Python dependency to 3.7.
This commit is contained in:
Damien Elmes 2019-12-24 13:33:44 +10:00
parent e893294ee4
commit 252a0cb54f
16 changed files with 649 additions and 46 deletions

6
.gitignore vendored
View file

@ -3,15 +3,18 @@
*\#
*~
.*.swp
.DS_Store
.build
.coverage
.DS_Store
.mypy_cache
.pytype
__pycache__
anki/buildhash.py
anki/proto
aqt/forms
locale
rs/ankirs/src/proto.rs
rs/target
tools/runanki.system
ts/node_modules
web/deckbrowser.js
@ -20,4 +23,3 @@ web/overview.js
web/reviewer-bottom.js
web/reviewer.js
web/webview.js
rs/target

View file

@ -96,6 +96,11 @@ RUST_TOOLCHAIN := $(shell cat rs/rust-toolchain)
rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
@touch $@
# Protobuf
######################
PROTODEPS := $(wildcard proto/*.proto)
# Typescript source
######################
@ -105,12 +110,12 @@ JSDEPS := $(patsubst ts/src/%.ts, web/%.js, $(TSDEPS))
# Rust source
######################
RSDEPS := $(wildcard rs/*/src/*.rs)
RSDEPS := $(shell find rs -type f | grep -v target)
# Building
######################
BUILDDEPS := .build/ui .build/js .build/rs
BUILDDEPS := .build/ui .build/js .build/rs .build/py-proto
.build/ui: $(RUNREQS) $(shell find designer -type f)
./tools/build_ui.sh
@ -120,10 +125,14 @@ BUILDDEPS := .build/ui .build/js .build/rs
(cd ts && npm run build)
@touch $@
.build/rs: .build/rust-deps $(RUNREQS) $(RSDEPS)
.build/rs: .build/rust-deps $(RUNREQS) $(RSDEPS) $(PROTODEPS)
(cd rs/pybridge && maturin develop $(RUSTARGS))
@touch $@
.build/py-proto: $(RUNREQS) $(PROTODEPS)
protoc -I proto --python_betterproto_out=anki/proto proto/bridge.proto
@touch $@
.PHONY: build clean
build: $(BUILDDEPS)
@ -147,6 +156,9 @@ run: build
.PHONY: check
check: rs-test rs-fmt rs-clippy py-mypy py-test py-fmt py-imports py-lint ts-fmt
.PHONY: fix
fix: fix-py-fmt fix-py-imports fix-rs-fmt fix-ts-fmt
# Checking python
######################
@ -156,7 +168,7 @@ PYCHECKDEPS := $(BUILDDEPS) .build/py-check-reqs $(shell find anki aqt -name '*.
mypy anki aqt
@touch $@
.build/pytest: $(PYCHECKDEPS) $(wildcard tests/*.py)
.build/py-test: $(PYCHECKDEPS) $(wildcard tests/*.py)
./tools/tests.sh
@touch $@

View file

@ -29,6 +29,7 @@ from anki.lang import _, ngettext
from anki.media import MediaManager
from anki.models import ModelManager
from anki.notes import Note
from anki.rsbridge import RSBridge
from anki.sched import Scheduler as V1Scheduler
from anki.schedv2 import Scheduler as V2Scheduler
from anki.sound import stripSounds
@ -84,8 +85,12 @@ class _Collection:
ls: int
conf: Dict[str, Any]
_undo: List[Any]
rust: RSBridge
def __init__(self, db: DB, server: bool = False, log: bool = False) -> None:
def __init__(
self, db: DB, server: bool = False, log: bool = False, rust: RSBridge = None
) -> None:
self.rust = rust
self._debugLog = log
self.db = db
self.path = db._path

View file

@ -1,10 +1,37 @@
import _ankirs # pytype: disable=import-error
import betterproto
from anki.proto import proto as pb
class BridgeException(Exception):
def __str__(self) -> str:
err: pb.BridgeError = self.args[0] # pylint: disable=unsubscriptable-object
(kind, obj) = betterproto.which_one_of(err, "value")
if kind == "invalid_input":
return f"invalid input: {obj.info}"
else:
return f"unhandled error: {err} {obj}"
class RSBridge:
def __init__(self):
self._bridge = _ankirs.Bridge()
assert self._bridge.cmd("") == "test"
def _run_command(self, input: pb.BridgeInput) -> pb.BridgeOutput:
input_bytes = bytes(input)
output_bytes = self._bridge.command(input_bytes)
output = pb.BridgeOutput().parse(output_bytes)
(kind, obj) = betterproto.which_one_of(output, "value")
if kind == "error":
raise BridgeException(obj)
else:
return output
def plus_one(self, num: int) -> int:
input = pb.BridgeInput(plus_one=pb.PlusOneIn(num=num))
output = self._run_command(input)
return output.plus_one.num
bridge = RSBridge()

View file

@ -12,6 +12,7 @@ from anki.collection import _Collection
from anki.consts import *
from anki.db import DB
from anki.lang import _
from anki.rsbridge import RSBridge
from anki.stdmodels import (
addBasicModel,
addBasicTypingModel,
@ -26,6 +27,8 @@ def Collection(
path: str, lock: bool = True, server: bool = False, log: bool = False
) -> _Collection:
"Open a new or existing collection. Path must be unicode."
bridge = RSBridge()
assert bridge.plus_one(5) == 6
assert path.endswith(".anki2")
path = os.path.abspath(path)
create = not os.path.exists(path)
@ -46,7 +49,7 @@ def Collection(
db.execute("pragma journal_mode = wal")
db.setAutocommit(False)
# add db to col and do any remaining upgrades
col = _Collection(db, server, log)
col = _Collection(db, server, log, rust=bridge)
if ver < SCHEMA_VERSION:
_upgrade(col, ver)
elif ver > SCHEMA_VERSION:

36
proto/bridge.proto Normal file
View file

@ -0,0 +1,36 @@
syntax = "proto3";
package proto;
message Empty {}
message BridgeInput {
oneof value {
PlusOneIn plus_one = 2;
}
}
message BridgeOutput {
oneof value {
BridgeError error = 1;
PlusOneOut plus_one = 2;
}
}
message BridgeError {
oneof value {
InvalidInputError invalid_input = 1;
}
}
message InvalidInputError {
string info = 1;
}
message PlusOneIn {
int32 num = 1;
}
message PlusOneOut {
int32 num = 1;
}

View file

@ -8,3 +8,4 @@ jsonschema
psutil; sys_platform == "win32"
distro; sys_platform != "win32" and sys_platform != "darwin"
typing
betterproto[compiler]

449
rs/Cargo.lock generated
View file

@ -12,6 +12,12 @@ dependencies = [
[[package]]
name = "ankirs"
version = "0.1.0"
dependencies = [
"bytes",
"failure",
"prost",
"prost-build",
]
[[package]]
name = "autocfg"
@ -19,14 +25,118 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]]
name = "backtrace"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
dependencies = [
"backtrace-sys",
"cfg-if",
"libc",
"rustc-demangle",
]
[[package]]
name = "backtrace-sys"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
[[package]]
name = "bytes"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
dependencies = [
"byteorder",
"iovec",
]
[[package]]
name = "c2-chacha"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
dependencies = [
"ppv-lite86",
]
[[package]]
name = "cc"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "ctor"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc"
dependencies = [
"quote",
"syn",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "failure"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
dependencies = [
"backtrace",
"failure_derive",
]
[[package]]
name = "failure_derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
dependencies = [
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
"synstructure",
]
[[package]]
name = "fixedbitset"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
[[package]]
name = "getrandom"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
@ -35,9 +145,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation",
]
[[package]]
@ -57,9 +176,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
"unindent",
]
@ -80,9 +199,27 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
dependencies = [
"either",
]
[[package]]
@ -103,12 +240,27 @@ version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
[[package]]
name = "multimap"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151"
[[package]]
name = "num-traits"
version = "0.2.10"
@ -135,20 +287,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "petgraph"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
dependencies = [
"fixedbitset",
]
[[package]]
name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
[[package]]
name = "proc-macro-hack"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]]
@ -157,13 +333,66 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
dependencies = [
"unicode-xid",
"unicode-xid 0.2.0",
]
[[package]]
name = "prost"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d14b1c185652833d24aaad41c5832b0be5616a590227c1fbff57c616754b23"
dependencies = [
"byteorder",
"bytes",
"prost-derive",
]
[[package]]
name = "prost-build"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb788126ea840817128183f8f603dce02cb7aea25c2a0b764359d8e20010702e"
dependencies = [
"bytes",
"heck",
"itertools",
"log",
"multimap",
"petgraph",
"prost",
"prost-types",
"tempfile",
"which",
]
[[package]]
name = "prost-derive"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e7dc378b94ac374644181a2247cebf59a6ec1c88b49ac77f3a94b86b79d0e11"
dependencies = [
"failure",
"itertools",
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.15.44",
]
[[package]]
name = "prost-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de482a366941c8d56d19b650fac09ca08508f2a696119ee7513ad590c8bac6f"
dependencies = [
"bytes",
"prost",
]
[[package]]
name = "pybridge"
version = "0.1.0"
dependencies = [
"ankirs",
"pyo3",
]
@ -194,9 +423,9 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f6e56fb3e97b344a8f87d036f94578399402c6b75949de6270cd07928f790b1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
@ -205,10 +434,19 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97452dcdf5941627ebc5c06664a07821fc7fc88d7515f02178193a8ebe316468"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.6",
"pyo3-derive-backend",
"quote",
"syn",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
@ -217,9 +455,56 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.6",
]
[[package]]
name = "rand"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
dependencies = [
"c2-chacha",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "regex"
version = "1.3.1"
@ -238,6 +523,21 @@ version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
[[package]]
name = "remove_dir_all"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
dependencies = [
"winapi",
]
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "ryu"
version = "1.0.2"
@ -259,9 +559,9 @@ version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
]
[[package]]
@ -281,15 +581,52 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid 0.1.0",
]
[[package]]
name = "syn"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"proc-macro2 1.0.6",
"quote 1.0.2",
"unicode-xid 0.2.0",
]
[[package]]
name = "synstructure"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
dependencies = [
"proc-macro2 1.0.6",
"quote 1.0.2",
"syn 1.0.11",
"unicode-xid 0.2.0",
]
[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
@ -301,6 +638,18 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.0"
@ -318,3 +667,41 @@ name = "version_check"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
[[package]]
name = "wasi"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
[[package]]
name = "which"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
dependencies = [
"failure",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -3,3 +3,11 @@ name = "ankirs"
version = "0.1.0"
edition = "2018"
authors = ["Ankitects Pty Ltd and contributors"]
[dependencies]
failure = "0.1.6"
prost = "0.5.0"
bytes = "0.4"
[build-dependencies]
prost-build = "0.5.0"

7
rs/ankirs/build.rs Normal file
View file

@ -0,0 +1,7 @@
use prost_build;
fn main() {
// avoid default OUT_DIR for now, for code completion
std::env::set_var("OUT_DIR", "src");
prost_build::compile_protos(&["../../proto/bridge.proto"], &["../../proto/"]).unwrap();
}

84
rs/ankirs/src/bridge.rs Normal file
View file

@ -0,0 +1,84 @@
use crate::err::{AnkiError, Result};
use crate::proto as pt;
use crate::proto::bridge_input::Value;
use prost::Message;
pub struct Bridge {}
impl Default for Bridge {
fn default() -> Self {
Bridge {}
}
}
/// Convert an Anki error to a protobuf error.
impl std::convert::From<AnkiError> for pt::BridgeError {
fn from(err: AnkiError) -> Self {
use pt::bridge_error::Value as V;
let value = match err {
AnkiError::InvalidInput { info } => V::InvalidInput(pt::InvalidInputError { info }),
};
pt::BridgeError { value: Some(value) }
}
}
// Convert an Anki error to a protobuf output.
impl std::convert::From<AnkiError> for pt::bridge_output::Value {
fn from(err: AnkiError) -> Self {
pt::bridge_output::Value::Error(err.into())
}
}
impl Bridge {
pub fn new() -> Bridge {
Bridge::default()
}
/// Decode a request, process it, and return the encoded result.
pub fn run_command_bytes(&mut self, req: &[u8]) -> Vec<u8> {
let mut buf = vec![];
let req = match pt::BridgeInput::decode(req) {
Ok(req) => req,
Err(_e) => {
// unable to decode
let err = AnkiError::invalid_input("couldn't decode bridge request");
let output = pt::BridgeOutput {
value: Some(err.into()),
};
output.encode(&mut buf).expect("encode failed");
return buf;
}
};
let resp = self.run_command(req);
resp.encode(&mut buf).expect("encode failed");
buf
}
fn run_command(&self, input: pt::BridgeInput) -> pt::BridgeOutput {
let oval = if let Some(ival) = input.value {
match self.run_command_inner(ival) {
Ok(output) => output,
Err(err) => err.into(),
}
} else {
AnkiError::invalid_input("unrecognized bridge input value").into()
};
pt::BridgeOutput { value: Some(oval) }
}
fn run_command_inner(&self, ival: pt::bridge_input::Value) -> Result<pt::bridge_output::Value> {
use pt::bridge_output::Value as OValue;
Ok(match ival {
Value::PlusOne(input) => OValue::PlusOne(self.plus_one(input)?),
})
}
fn plus_one(&self, input: pt::PlusOneIn) -> Result<pt::PlusOneOut> {
let num = input.num + 1;
Ok(pt::PlusOneOut { num })
}
}

16
rs/ankirs/src/err.rs Normal file
View file

@ -0,0 +1,16 @@
pub use failure::{Error, Fail};
pub type Result<T> = std::result::Result<T, AnkiError>;
#[derive(Debug, Fail)]
pub enum AnkiError {
#[fail(display = "invalid input: {}", info)]
InvalidInput { info: String },
}
// error helpers
impl AnkiError {
pub(crate) fn invalid_input<S: Into<String>>(s: S) -> AnkiError {
AnkiError::InvalidInput { info: s.into() }
}
}

View file

@ -1 +1,4 @@
mod proto;
pub mod bridge;
pub mod err;

View file

@ -4,6 +4,9 @@ version = "0.1.0"
edition = "2018"
authors = ["Ankitects Pty Ltd and contributors"]
[dependencies]
ankirs = { path = "../ankirs" }
[dependencies.pyo3]
version = "0.8.0"
features = ["extension-module"]

View file

@ -1,19 +1,27 @@
use pyo3::exceptions;
use ankirs::bridge::Bridge as RustBridge;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
#[pyclass]
struct Bridge {}
struct Bridge {
bridge: RustBridge,
}
#[pymethods]
impl Bridge {
#[new]
fn init(obj: &PyRawObject) {
obj.init({ Bridge {} });
obj.init({
Bridge {
bridge: Default::default(),
}
});
}
fn cmd(&mut self, _request: String) -> PyResult<String> {
Ok("test".to_string())
.map_err(|e: std::io::Error| exceptions::Exception::py_err(format!("{:?}", e)))
fn command(&mut self, py: Python, input: &PyBytes) -> PyResult<PyObject> {
let out_bytes = self.bridge.run_command_bytes(input.as_bytes());
let out_obj = PyBytes::new(py, &out_bytes);
Ok(out_obj.into())
}
}

1
rs/rustfmt.toml Normal file
View file

@ -0,0 +1 @@
ignore = ["proto.rs"]