diff --git a/proto/anki/ankidroid.proto b/proto/anki/ankidroid.proto index 38c2b354b..cb9db1ecd 100644 --- a/proto/anki/ankidroid.proto +++ b/proto/anki/ankidroid.proto @@ -4,18 +4,10 @@ option java_multiple_files = true; import "anki/generic.proto"; import "anki/scheduler.proto"; -import "anki/codegen.proto"; package anki.ankidroid; service AnkidroidService { - rpc SchedTimingTodayLegacy(SchedTimingTodayLegacyRequest) - returns (scheduler.SchedTimingTodayResponse) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc LocalMinutesWestLegacy(generic.Int64) returns (generic.Int32) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } rpc RunDbCommand(generic.Json) returns (generic.Json); rpc RunDbCommandProto(generic.Json) returns (DbResponse); rpc InsertForId(generic.Json) returns (generic.Int64); @@ -23,15 +15,17 @@ service AnkidroidService { rpc FlushAllQueries(generic.Empty) returns (generic.Empty); rpc FlushQuery(generic.Int32) returns (generic.Empty); rpc GetNextResultPage(GetNextResultPageRequest) returns (DbResponse); - rpc SetPageSize(generic.Int64) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } rpc GetColumnNamesFromQuery(generic.String) returns (generic.StringList); rpc GetActiveSequenceNumbers(generic.Empty) returns (GetActiveSequenceNumbersResponse); - rpc DebugProduceError(generic.String) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } +} + +service BackendAnkidroidService { + rpc SchedTimingTodayLegacy(SchedTimingTodayLegacyRequest) + returns (scheduler.SchedTimingTodayResponse); + rpc LocalMinutesWestLegacy(generic.Int64) returns (generic.Int32); + rpc SetPageSize(generic.Int64) returns (generic.Empty); + rpc DebugProduceError(generic.String) returns (generic.Empty); } message DebugActiveDatabaseSequenceNumbersResponse { diff --git a/proto/anki/card_rendering.proto b/proto/anki/card_rendering.proto index ae5886c46..866e2e9ae 100644 --- a/proto/anki/card_rendering.proto +++ b/proto/anki/card_rendering.proto @@ -28,7 +28,7 @@ service CardRenderingService { rpc DecodeIriPaths(generic.String) returns (generic.String); rpc StripHtml(StripHtmlRequest) returns (generic.String) { // a bunch of our unit tests access this without a collection - option (codegen.rust_methods) = RUST_METHODS_COLLECTION_AND_MANUAL_BACKEND; + option (codegen.backend_method) = BACKEND_METHOD_IMPLEMENT; } rpc CompareAnswer(CompareAnswerRequest) returns (generic.String); rpc ExtractClozeForTyping(ExtractClozeForTypingRequest) diff --git a/proto/anki/codegen.proto b/proto/anki/codegen.proto index a25591d3c..51feed224 100644 --- a/proto/anki/codegen.proto +++ b/proto/anki/codegen.proto @@ -8,21 +8,18 @@ package anki.codegen; import "google/protobuf/descriptor.proto"; extend google.protobuf.MethodOptions { - RustMethods rust_methods = 50000; + BackendMethod backend_method = 50000; } message MethodOptions { - RustMethods rust_methods = 50000; + BackendMethod backend_method = 50000; } -enum RustMethods { +enum BackendMethod { /// Used for typical collection-based operations. We must implement the // method on Collection. The same method is automatically implemented on // Backend, which forwards to Collection. - RUST_METHODS_COLLECTION_AND_AUTO_BACKEND = 0; - /// Method only makes sense on the backend (eg one that closes and reopens - /// the collection). Backend method needs to be implemented. - RUST_METHODS_BACKEND_ONLY = 1; + BACKEND_METHOD_DELEGATE = 0; /// Both the backend and collection need to implement the method; there /// is no auto-delegation. Can be used to provide a method on both, but /// skip the Collection mutex lock when a backend handle is available. @@ -30,5 +27,5 @@ enum RustMethods { /// method in other services that doesn't happen to need the collection, /// we just delegate to the collection method for convenience, and to make /// sure it's available even if the consumer is not using Backend. - RUST_METHODS_COLLECTION_AND_MANUAL_BACKEND = 2; + BACKEND_METHOD_IMPLEMENT = 1; } diff --git a/proto/anki/collection.proto b/proto/anki/collection.proto index 475be93af..08c618223 100644 --- a/proto/anki/collection.proto +++ b/proto/anki/collection.proto @@ -8,15 +8,8 @@ option java_multiple_files = true; package anki.collection; import "anki/generic.proto"; -import "anki/codegen.proto"; service CollectionService { - rpc OpenCollection(OpenCollectionRequest) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc CloseCollection(CloseCollectionRequest) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } rpc CheckDatabase(generic.Empty) returns (CheckDatabaseResponse); rpc GetUndoStatus(generic.Empty) returns (UndoStatus); rpc Undo(generic.Empty) returns (OpChangesAfterUndo); @@ -25,18 +18,19 @@ service CollectionService { rpc MergeUndoEntries(generic.UInt32) returns (OpChanges); rpc LatestProgress(generic.Empty) returns (Progress); rpc SetWantsAbort(generic.Empty) returns (generic.Empty); +} + +service BackendCollectionService { + rpc OpenCollection(OpenCollectionRequest) returns (generic.Empty); + rpc CloseCollection(CloseCollectionRequest) returns (generic.Empty); // Create a no-media backup. Caller must ensure there is no active // transaction. Unlike a collection export, does not require reopening the DB, // as there is no downgrade step. // Returns false if it's not time to make a backup yet. - rpc CreateBackup(CreateBackupRequest) returns (generic.Bool) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } + rpc CreateBackup(CreateBackupRequest) returns (generic.Bool); // If a backup is running, wait for it to complete. Will return an error // if the backup encountered an error. - rpc AwaitBackupCompletion(generic.Empty) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } + rpc AwaitBackupCompletion(generic.Empty) returns (generic.Empty); } message OpenCollectionRequest { diff --git a/proto/anki/i18n.proto b/proto/anki/i18n.proto index 3330b190d..c00898eb9 100644 --- a/proto/anki/i18n.proto +++ b/proto/anki/i18n.proto @@ -12,13 +12,13 @@ import "anki/codegen.proto"; service I18nService { rpc TranslateString(TranslateStringRequest) returns (generic.String) { - option (codegen.rust_methods) = RUST_METHODS_COLLECTION_AND_MANUAL_BACKEND; + option (codegen.backend_method) = BACKEND_METHOD_IMPLEMENT; } rpc FormatTimespan(FormatTimespanRequest) returns (generic.String) { - option (codegen.rust_methods) = RUST_METHODS_COLLECTION_AND_MANUAL_BACKEND; + option (codegen.backend_method) = BACKEND_METHOD_IMPLEMENT; } rpc I18nResources(I18nResourcesRequest) returns (generic.Json) { - option (codegen.rust_methods) = RUST_METHODS_COLLECTION_AND_MANUAL_BACKEND; + option (codegen.backend_method) = BACKEND_METHOD_IMPLEMENT; } } diff --git a/proto/anki/import_export.proto b/proto/anki/import_export.proto index 4d1d1d1a6..f490aee3a 100644 --- a/proto/anki/import_export.proto +++ b/proto/anki/import_export.proto @@ -14,14 +14,6 @@ import "anki/generic.proto"; import "anki/codegen.proto"; service ImportExportService { - rpc ImportCollectionPackage(ImportCollectionPackageRequest) - returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc ExportCollectionPackage(ExportCollectionPackageRequest) - returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } rpc ImportAnkiPackage(ImportAnkiPackageRequest) returns (ImportResponse); rpc ExportAnkiPackage(ExportAnkiPackageRequest) returns (generic.UInt32); rpc GetCsvMetadata(CsvMetadataRequest) returns (CsvMetadata); @@ -32,6 +24,13 @@ service ImportExportService { rpc ImportJsonString(generic.String) returns (ImportResponse); } +service BackendImportExportService { + rpc ImportCollectionPackage(ImportCollectionPackageRequest) + returns (generic.Empty); + rpc ExportCollectionPackage(ExportCollectionPackageRequest) + returns (generic.Empty); +} + message ImportCollectionPackageRequest { string col_path = 1; string backup_path = 2; diff --git a/proto/anki/sync.proto b/proto/anki/sync.proto index 546496480..43e3ac198 100644 --- a/proto/anki/sync.proto +++ b/proto/anki/sync.proto @@ -8,33 +8,16 @@ option java_multiple_files = true; package anki.sync; import "anki/generic.proto"; -import "anki/codegen.proto"; -service SyncService { - rpc SyncMedia(SyncAuth) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc AbortMediaSync(generic.Empty) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc SyncLogin(SyncLoginRequest) returns (SyncAuth) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc SyncStatus(SyncAuth) returns (SyncStatusResponse) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc SyncCollection(SyncAuth) returns (SyncCollectionResponse) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc FullUpload(SyncAuth) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc FullDownload(SyncAuth) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } - rpc AbortSync(generic.Empty) returns (generic.Empty) { - option (codegen.rust_methods) = RUST_METHODS_BACKEND_ONLY; - } +service BackendSyncService { + rpc SyncMedia(SyncAuth) returns (generic.Empty); + rpc AbortMediaSync(generic.Empty) returns (generic.Empty); + rpc SyncLogin(SyncLoginRequest) returns (SyncAuth); + rpc SyncStatus(SyncAuth) returns (SyncStatusResponse); + rpc SyncCollection(SyncAuth) returns (SyncCollectionResponse); + rpc FullUpload(SyncAuth) returns (generic.Empty); + rpc FullDownload(SyncAuth) returns (generic.Empty); + rpc AbortSync(generic.Empty) returns (generic.Empty); } message SyncAuth { diff --git a/rslib/rust_interface.rs b/rslib/rust_interface.rs index 4c4988af6..287c20a70 100644 --- a/rslib/rust_interface.rs +++ b/rslib/rust_interface.rs @@ -6,7 +6,7 @@ use std::fmt::Write; use std::path::PathBuf; use anki_io::write_file_if_changed; -use anki_proto::codegen::RustMethods; +use anki_proto::codegen::BackendMethod; use anyhow::Context; use anyhow::Result; use inflections::Inflect; @@ -48,6 +48,7 @@ struct RustMethod { input_type: Option, output_type: Option, options: anki_proto::codegen::MethodOptions, + service_name: String, } impl RustMethod { @@ -74,21 +75,21 @@ impl RustMethod { } fn wants_abstract_backend_method(&self) -> bool { - self.options.rust_methods() != RustMethods::CollectionAndAutoBackend + self.service_name.starts_with("Backend") + || self.options.backend_method() == BackendMethod::Implement } fn wants_abstract_collection_method(&self) -> bool { - self.options.rust_methods() != RustMethods::BackendOnly + !self.service_name.starts_with("Backend") } -} -impl RustMethod { fn from_proto(method: prost_reflect::MethodDescriptor) -> Self { RustMethod { name: method.name().to_snake_case(), input_type: rust_type(method.input().full_name()), output_type: rust_type(method.output().full_name()), options: method.options().transcode_to().unwrap(), + service_name: method.parent_service().name().to_string(), } } } @@ -189,7 +190,11 @@ fn render_collection_trait(service: &RustService, buf: &mut String) { } fn render_backend_trait(service: &RustService, buf: &mut String) { - let name = format!("Backend{}", service.name); + let name = if !service.name.starts_with("Backend") { + format!("Backend{}", service.name) + } else { + service.name.clone() + }; writeln!(buf, "pub trait {name} {{").unwrap(); for method in &service.methods { if method.wants_abstract_backend_method() {