chore: rename quicproquo → quicprochat in Rust workspace
Rename all crate directories, package names, binary names, proto package/module paths, ALPN strings, env var prefixes, config filenames, mDNS service names, and plugin ABI symbols from quicproquo/qpq to quicprochat/qpc.
This commit is contained in:
30
crates/quicprochat-proto/Cargo.toml
Normal file
30
crates/quicprochat-proto/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "quicprochat-proto"
|
||||
version = "0.2.0"
|
||||
edition.workspace = true
|
||||
description = "Protocol types for quicprochat — v1 Cap'n Proto (legacy) + v2 Protobuf (prost)"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository.workspace = true
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
# v1 legacy (Cap'n Proto) — used by existing server/client until rewrite
|
||||
capnp = { workspace = true }
|
||||
|
||||
# v2 (Protobuf via prost) — new RPC types
|
||||
prost = { workspace = true }
|
||||
prost-types = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
capnpc = { workspace = true }
|
||||
prost-build = { workspace = true }
|
||||
protobuf-src = "2"
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "warn"
|
||||
|
||||
[lints.clippy]
|
||||
# Generated Cap'n Proto code uses patterns that trigger clippy lints.
|
||||
unwrap_used = "allow"
|
||||
69
crates/quicprochat-proto/build.rs
Normal file
69
crates/quicprochat-proto/build.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! Build script for quicprochat-proto.
|
||||
//!
|
||||
//! Runs two code generators:
|
||||
//! 1. Cap'n Proto (v1 legacy) — from `schemas/*.capnp`
|
||||
//! 2. Protobuf/prost (v2) — from `proto/qpc/v1/*.proto`
|
||||
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
fn main() {
|
||||
// Vendor protoc from protobuf-src so the build doesn't require system protoc.
|
||||
std::env::set_var("PROTOC", protobuf_src::protoc());
|
||||
|
||||
let manifest_dir =
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
|
||||
let workspace_root = manifest_dir
|
||||
.join("../..")
|
||||
.canonicalize()
|
||||
.expect("canonicalize workspace root");
|
||||
|
||||
// ── v1: Cap'n Proto codegen ──────────────────────────────────────────────
|
||||
let schemas_dir = workspace_root.join("schemas");
|
||||
|
||||
for schema in &["auth.capnp", "delivery.capnp", "node.capnp", "federation.capnp"] {
|
||||
println!("cargo:rerun-if-changed={}", schemas_dir.join(schema).display());
|
||||
}
|
||||
|
||||
capnpc::CompilerCommand::new()
|
||||
.src_prefix(&schemas_dir)
|
||||
.file(schemas_dir.join("auth.capnp"))
|
||||
.file(schemas_dir.join("delivery.capnp"))
|
||||
.file(schemas_dir.join("node.capnp"))
|
||||
.file(schemas_dir.join("federation.capnp"))
|
||||
.run()
|
||||
.expect(
|
||||
"Cap'n Proto schema compilation failed. \
|
||||
Is `capnp` installed? (apt-get install capnproto / brew install capnp)",
|
||||
);
|
||||
|
||||
// ── v2: Protobuf/prost codegen ───────────────────────────────────────────
|
||||
let proto_dir = workspace_root.join("proto");
|
||||
|
||||
let proto_files = [
|
||||
"qpc/v1/common.proto",
|
||||
"qpc/v1/auth.proto",
|
||||
"qpc/v1/delivery.proto",
|
||||
"qpc/v1/keys.proto",
|
||||
"qpc/v1/channel.proto",
|
||||
"qpc/v1/user.proto",
|
||||
"qpc/v1/blob.proto",
|
||||
"qpc/v1/device.proto",
|
||||
"qpc/v1/p2p.proto",
|
||||
"qpc/v1/federation.proto",
|
||||
"qpc/v1/push.proto",
|
||||
"qpc/v1/group.proto",
|
||||
"qpc/v1/moderation.proto",
|
||||
"qpc/v1/recovery.proto",
|
||||
];
|
||||
|
||||
let full_paths: Vec<PathBuf> = proto_files.iter().map(|f| proto_dir.join(f)).collect();
|
||||
|
||||
for path in &full_paths {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
|
||||
prost_build::Config::new()
|
||||
.out_dir(PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR")))
|
||||
.compile_protos(&full_paths, &[&proto_dir])
|
||||
.expect("prost compile_protos failed");
|
||||
}
|
||||
161
crates/quicprochat-proto/src/lib.rs
Normal file
161
crates/quicprochat-proto/src/lib.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
//! Protocol types for quicprochat.
|
||||
//!
|
||||
//! This crate contains both:
|
||||
//! - **v1 (legacy)**: Cap'n Proto generated types from `schemas/*.capnp`
|
||||
//! - **v2**: Protobuf generated types from `proto/qpc/v1/*.proto`
|
||||
//!
|
||||
//! # Design constraints
|
||||
//!
|
||||
//! - **No crypto** — key material never enters this crate.
|
||||
//! - **No I/O** — callers own transport; this crate only converts bytes <-> types.
|
||||
//! - **No async** — pure synchronous data-layer code.
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
// v1 (legacy): Cap'n Proto generated types
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
#![allow(unused_parens)]
|
||||
|
||||
pub mod auth_capnp {
|
||||
include!(concat!(env!("OUT_DIR"), "/auth_capnp.rs"));
|
||||
}
|
||||
|
||||
pub mod delivery_capnp {
|
||||
include!(concat!(env!("OUT_DIR"), "/delivery_capnp.rs"));
|
||||
}
|
||||
|
||||
pub mod node_capnp {
|
||||
include!(concat!(env!("OUT_DIR"), "/node_capnp.rs"));
|
||||
}
|
||||
|
||||
pub mod federation_capnp {
|
||||
include!(concat!(env!("OUT_DIR"), "/federation_capnp.rs"));
|
||||
}
|
||||
|
||||
/// Serialise a Cap'n Proto message builder to unpacked wire bytes.
|
||||
pub fn to_bytes<A: capnp::message::Allocator>(
|
||||
msg: &capnp::message::Builder<A>,
|
||||
) -> Result<Vec<u8>, capnp::Error> {
|
||||
let mut buf = Vec::new();
|
||||
capnp::serialize::write_message(&mut buf, msg)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Deserialise unpacked wire bytes into a Cap'n Proto message.
|
||||
pub fn from_bytes(
|
||||
bytes: &[u8],
|
||||
) -> Result<capnp::message::Reader<capnp::serialize::OwnedSegments>, capnp::Error> {
|
||||
let mut options = capnp::message::ReaderOptions::new();
|
||||
options.traversal_limit_in_words(Some(1_048_576));
|
||||
let mut cursor = std::io::Cursor::new(bytes);
|
||||
capnp::serialize::read_message(&mut cursor, options)
|
||||
}
|
||||
|
||||
/// Deserialise with custom [`ReaderOptions`].
|
||||
pub fn from_bytes_with_options(
|
||||
bytes: &[u8],
|
||||
options: capnp::message::ReaderOptions,
|
||||
) -> Result<capnp::message::Reader<capnp::serialize::OwnedSegments>, capnp::Error> {
|
||||
let mut cursor = std::io::Cursor::new(bytes);
|
||||
capnp::serialize::read_message(&mut cursor, options)
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
// v2: Protobuf (prost) generated types
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/// Protobuf types for the v2 RPC protocol.
|
||||
pub mod qpc {
|
||||
pub mod v1 {
|
||||
include!(concat!(env!("OUT_DIR"), "/qpc.v1.rs"));
|
||||
}
|
||||
}
|
||||
|
||||
/// Method ID constants for the v2 RPC dispatch table.
|
||||
pub mod method_ids {
|
||||
// Auth (100-103)
|
||||
pub const OPAQUE_REGISTER_START: u16 = 100;
|
||||
pub const OPAQUE_REGISTER_FINISH: u16 = 101;
|
||||
pub const OPAQUE_LOGIN_START: u16 = 102;
|
||||
pub const OPAQUE_LOGIN_FINISH: u16 = 103;
|
||||
|
||||
// Delivery (200-205)
|
||||
pub const ENQUEUE: u16 = 200;
|
||||
pub const FETCH: u16 = 201;
|
||||
pub const FETCH_WAIT: u16 = 202;
|
||||
pub const PEEK: u16 = 203;
|
||||
pub const ACK: u16 = 204;
|
||||
pub const BATCH_ENQUEUE: u16 = 205;
|
||||
|
||||
// Keys (300-304)
|
||||
pub const UPLOAD_KEY_PACKAGE: u16 = 300;
|
||||
pub const FETCH_KEY_PACKAGE: u16 = 301;
|
||||
pub const UPLOAD_HYBRID_KEY: u16 = 302;
|
||||
pub const FETCH_HYBRID_KEY: u16 = 303;
|
||||
pub const FETCH_HYBRID_KEYS: u16 = 304;
|
||||
|
||||
// Channel (400)
|
||||
pub const CREATE_CHANNEL: u16 = 400;
|
||||
|
||||
// Group management (410-413)
|
||||
pub const REMOVE_MEMBER: u16 = 410;
|
||||
pub const UPDATE_GROUP_METADATA: u16 = 411;
|
||||
pub const LIST_GROUP_MEMBERS: u16 = 412;
|
||||
pub const ROTATE_KEYS: u16 = 413;
|
||||
|
||||
// User (500-501)
|
||||
pub const RESOLVE_USER: u16 = 500;
|
||||
pub const RESOLVE_IDENTITY: u16 = 501;
|
||||
|
||||
// Key Transparency (510-520)
|
||||
pub const REVOKE_KEY: u16 = 510;
|
||||
pub const CHECK_REVOCATION: u16 = 511;
|
||||
pub const AUDIT_KEY_TRANSPARENCY: u16 = 520;
|
||||
|
||||
// Blob (600-601)
|
||||
pub const UPLOAD_BLOB: u16 = 600;
|
||||
pub const DOWNLOAD_BLOB: u16 = 601;
|
||||
|
||||
// Device (700-702, 710)
|
||||
pub const REGISTER_DEVICE: u16 = 700;
|
||||
pub const LIST_DEVICES: u16 = 701;
|
||||
pub const REVOKE_DEVICE: u16 = 702;
|
||||
pub const REGISTER_PUSH_TOKEN: u16 = 710;
|
||||
|
||||
// P2P (800-802)
|
||||
pub const PUBLISH_ENDPOINT: u16 = 800;
|
||||
pub const RESOLVE_ENDPOINT: u16 = 801;
|
||||
pub const HEALTH: u16 = 802;
|
||||
|
||||
// Federation (900-905)
|
||||
pub const RELAY_ENQUEUE: u16 = 900;
|
||||
pub const RELAY_BATCH_ENQUEUE: u16 = 901;
|
||||
pub const PROXY_FETCH_KEY_PACKAGE: u16 = 902;
|
||||
pub const PROXY_FETCH_HYBRID_KEY: u16 = 903;
|
||||
pub const PROXY_RESOLVE_USER: u16 = 904;
|
||||
pub const FEDERATION_HEALTH: u16 = 905;
|
||||
|
||||
// Moderation (420-424)
|
||||
pub const REPORT_MESSAGE: u16 = 420;
|
||||
pub const BAN_USER: u16 = 421;
|
||||
pub const UNBAN_USER: u16 = 422;
|
||||
pub const LIST_REPORTS: u16 = 423;
|
||||
pub const LIST_BANNED: u16 = 424;
|
||||
|
||||
// Recovery (750-752)
|
||||
pub const STORE_RECOVERY_BUNDLE: u16 = 750;
|
||||
pub const FETCH_RECOVERY_BUNDLE: u16 = 751;
|
||||
pub const DELETE_RECOVERY_BUNDLE: u16 = 752;
|
||||
|
||||
// Account (950)
|
||||
pub const DELETE_ACCOUNT: u16 = 950;
|
||||
|
||||
// Push event types (1000+)
|
||||
pub const PUSH_NEW_MESSAGE: u16 = 1000;
|
||||
pub const PUSH_TYPING: u16 = 1001;
|
||||
pub const PUSH_PRESENCE: u16 = 1002;
|
||||
pub const PUSH_MEMBERSHIP: u16 = 1003;
|
||||
}
|
||||
|
||||
pub use prost;
|
||||
pub use bytes;
|
||||
Reference in New Issue
Block a user