diff --git a/Cargo.lock b/Cargo.lock index 9153bb9826..42dc4f8cf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,19 +447,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "bare_gen" -version = "25.7.1" -dependencies = [ - "heck 0.5.0", - "pest", - "pest_derive", - "proc-macro2", - "quote", - "serde", - "syn 2.0.104", -] - [[package]] name = "base64" version = "0.13.1" @@ -1416,7 +1403,7 @@ dependencies = [ "universaldb", "url", "uuid", - "versioned-data-util", + "vbare", ] [[package]] @@ -1424,15 +1411,11 @@ name = "epoxy-protocol" version = "25.7.1" dependencies = [ "anyhow", - "bare_gen", - "indoc", - "prettyplease", "rivet-util", "serde", "serde_bare", - "serde_json", - "syn 2.0.104", - "versioned-data-util", + "vbare", + "vbare-compiler", ] [[package]] @@ -2794,7 +2777,7 @@ dependencies = [ "universaldb", "url", "utoipa", - "versioned-data-util", + "vbare", ] [[package]] @@ -3281,7 +3264,7 @@ dependencies = [ "universaldb", "universalpubsub", "utoipa", - "versioned-data-util", + "vbare", ] [[package]] @@ -3324,7 +3307,7 @@ dependencies = [ "tokio", "tokio-tungstenite", "universalpubsub", - "versioned-data-util", + "vbare", ] [[package]] @@ -3357,7 +3340,7 @@ dependencies = [ "tracing", "universalpubsub", "url", - "versioned-data-util", + "vbare", ] [[package]] @@ -4259,17 +4242,13 @@ name = "rivet-data" version = "25.7.1" dependencies = [ "anyhow", - "bare_gen", "gasoline", - "indoc", - "prettyplease", "rivet-runner-protocol", "rivet-util", "serde", "serde_bare", - "serde_json", - "syn 2.0.104", - "versioned-data-util", + "vbare", + "vbare-compiler", ] [[package]] @@ -4336,7 +4315,7 @@ dependencies = [ "universaldb", "url", "uuid", - "versioned-data-util", + "vbare", ] [[package]] @@ -4528,18 +4507,14 @@ name = "rivet-runner-protocol" version = "25.7.1" dependencies = [ "anyhow", - "bare_gen", "base64 0.22.1", "gasoline", - "indoc", - "prettyplease", "rivet-util", "serde", "serde_bare", - "serde_json", - "syn 2.0.104", "utoipa", - "versioned-data-util", + "vbare", + "vbare-compiler", ] [[package]] @@ -4651,7 +4626,7 @@ dependencies = [ "serde", "universaldb", "utoipa", - "versioned-data-util", + "vbare", ] [[package]] @@ -4659,16 +4634,12 @@ name = "rivet-ups-protocol" version = "25.7.1" dependencies = [ "anyhow", - "bare_gen", "base64 0.22.1", - "indoc", - "prettyplease", "rivet-util", "serde", "serde_bare", - "serde_json", - "syn 2.0.104", - "versioned-data-util", + "vbare", + "vbare-compiler", ] [[package]] @@ -6382,7 +6353,7 @@ dependencies = [ "tracing", "tracing-subscriber", "uuid", - "versioned-data-util", + "vbare", ] [[package]] @@ -6484,6 +6455,42 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vbare" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf4d898b11572484cc064900e2a63dc88f72c621c2c52fd032b14537668702e" +dependencies = [ + "anyhow", +] + +[[package]] +name = "vbare-compiler" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9b0bf0c86821fe75c989d1548183085e274d1f04797498d30854dc85fa11ad" +dependencies = [ + "indoc", + "prettyplease", + "syn 2.0.104", + "vbare-gen", +] + +[[package]] +name = "vbare-gen" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f045599483ef9d44f6965143afbfa82e103e4e9810f5f07d1fc023a2547f28fe" +dependencies = [ + "heck 0.5.0", + "pest", + "pest_derive", + "proc-macro2", + "quote", + "serde", + "syn 2.0.104", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -6519,15 +6526,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "versioned-data-util" -version = "25.7.1" -dependencies = [ - "anyhow", - "serde", - "serde_bare", -] - [[package]] name = "vte" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index c96c7e2989..4fed60dcbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" -members = ["packages/common/api-builder","packages/common/api-types","packages/common/api-util","packages/common/cache/build","packages/common/cache/result","packages/common/clickhouse-inserter","packages/common/clickhouse-user-query","packages/common/config","packages/common/env","packages/common/error/core","packages/common/error/macros","packages/common/gasoline/core","packages/common/gasoline/macros","packages/common/logs","packages/common/metrics","packages/common/pools","packages/common/runtime","packages/common/service-manager","packages/common/telemetry","packages/common/test-deps","packages/common/test-deps-docker","packages/common/types","packages/common/universaldb","packages/common/universalpubsub","packages/common/util/core","packages/common/util/id","packages/common/versioned-data-util","packages/core/actor-kv","packages/core/api-peer","packages/core/api-public","packages/core/bootstrap","packages/core/dump-openapi","packages/core/guard/core","packages/core/guard/server","packages/core/pegboard-gateway","packages/core/pegboard-runner","packages/core/pegboard-serverless","packages/core/workflow-worker","packages/infra/engine","packages/services/epoxy","packages/services/internal","packages/services/namespace","packages/services/pegboard","sdks/rust/api-full","sdks/rust/bare_gen","sdks/rust/data","sdks/rust/epoxy-protocol","sdks/rust/runner-protocol","sdks/rust/ups-protocol"] +members = ["packages/common/api-builder","packages/common/api-types","packages/common/api-util","packages/common/cache/build","packages/common/cache/result","packages/common/clickhouse-inserter","packages/common/clickhouse-user-query","packages/common/config","packages/common/env","packages/common/error/core","packages/common/error/macros","packages/common/gasoline/core","packages/common/gasoline/macros","packages/common/logs","packages/common/metrics","packages/common/pools","packages/common/runtime","packages/common/service-manager","packages/common/telemetry","packages/common/test-deps","packages/common/test-deps-docker","packages/common/types","packages/common/universaldb","packages/common/universalpubsub","packages/common/util/core","packages/common/util/id","packages/core/actor-kv","packages/core/api-peer","packages/core/api-public","packages/core/bootstrap","packages/core/dump-openapi","packages/core/guard/core","packages/core/guard/server","packages/core/pegboard-gateway","packages/core/pegboard-runner","packages/core/pegboard-serverless","packages/core/workflow-worker","packages/infra/engine","packages/services/epoxy","packages/services/internal","packages/services/namespace","packages/services/pegboard","sdks/rust/api-full","sdks/rust/data","sdks/rust/epoxy-protocol","sdks/rust/runner-protocol","sdks/rust/ups-protocol"] [workspace.package] version = "25.7.1" @@ -332,9 +332,6 @@ path = "packages/common/util/core" [workspace.dependencies.rivet-util-id] path = "packages/common/util/id" -[workspace.dependencies.versioned-data-util] -path = "packages/common/versioned-data-util" - [workspace.dependencies.pegboard-actor-kv] path = "packages/core/actor-kv" @@ -386,9 +383,6 @@ path = "packages/services/pegboard" [workspace.dependencies.rivet-api-full] path = "sdks/rust/api-full" -[workspace.dependencies.bare_gen] -path = "sdks/rust/bare_gen" - [workspace.dependencies.rivet-data] path = "sdks/rust/data" @@ -401,6 +395,12 @@ path = "sdks/rust/runner-protocol" [workspace.dependencies.rivet-ups-protocol] path = "sdks/rust/ups-protocol" +[workspace.dependencies.vbare] +version = "0.0.2" + +[workspace.dependencies.vbare-compiler] +version = "0.0.2" + [profile.dev] overflow-checks = false debug = false diff --git a/out/openapi.json b/out/openapi.json index e7faf42314..176eb09c96 100644 --- a/out/openapi.json +++ b/out/openapi.json @@ -347,7 +347,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ActorsListResponse" + "$ref": "#/components/schemas/NamespaceListResponse" } } } @@ -862,14 +862,14 @@ "ActorsListResponse": { "type": "object", "required": [ - "namespaces", + "actors", "pagination" ], "properties": { - "namespaces": { + "actors": { "type": "array", "items": { - "$ref": "#/components/schemas/Namespace" + "$ref": "#/components/schemas/Actor" } }, "pagination": { @@ -947,6 +947,25 @@ } } }, + "NamespaceListResponse": { + "type": "object", + "required": [ + "namespaces", + "pagination" + ], + "properties": { + "namespaces": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Namespace" + } + }, + "pagination": { + "$ref": "#/components/schemas/Pagination" + } + }, + "additionalProperties": false + }, "NamespacesCreateRequest": { "type": "object", "required": [ diff --git a/packages/common/types/Cargo.toml b/packages/common/types/Cargo.toml index 0dde0d6af1..49bb8b9549 100644 --- a/packages/common/types/Cargo.toml +++ b/packages/common/types/Cargo.toml @@ -15,4 +15,4 @@ rivet-util.workspace = true serde.workspace = true universaldb.workspace = true utoipa.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true diff --git a/packages/common/universalpubsub/Cargo.toml b/packages/common/universalpubsub/Cargo.toml index 4ffddeb77c..e066aa6662 100644 --- a/packages/common/universalpubsub/Cargo.toml +++ b/packages/common/universalpubsub/Cargo.toml @@ -16,7 +16,7 @@ rivet-error.workspace = true rivet-ups-protocol.workspace = true rivet-util.workspace = true serde_json.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true serde.workspace = true sha2.workspace = true tokio-postgres.workspace = true diff --git a/packages/common/universalpubsub/src/chunking.rs b/packages/common/universalpubsub/src/chunking.rs index 8bf846b7a2..2c230efbb9 100644 --- a/packages/common/universalpubsub/src/chunking.rs +++ b/packages/common/universalpubsub/src/chunking.rs @@ -4,7 +4,7 @@ use std::time::{Duration, Instant}; use anyhow::*; use rivet_ups_protocol::versioned::UpsMessage; use rivet_ups_protocol::{MessageBody, MessageChunk, MessageStart, PROTOCOL_VERSION}; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; pub const CHUNK_BUFFER_GC_INTERVAL: Duration = Duration::from_secs(60); pub const CHUNK_BUFFER_MAX_AGE: Duration = Duration::from_secs(300); diff --git a/packages/common/versioned-data-util/Cargo.toml b/packages/common/versioned-data-util/Cargo.toml deleted file mode 100644 index c8659bdf38..0000000000 --- a/packages/common/versioned-data-util/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "versioned-data-util" -version.workspace = true -authors.workspace = true -license.workspace = true -edition.workspace = true - -[dependencies] -anyhow.workspace = true - -[dev-dependencies] -serde.workspace = true -serde_bare.workspace = true diff --git a/packages/common/versioned-data-util/src/lib.rs b/packages/common/versioned-data-util/src/lib.rs deleted file mode 100644 index 95aa903465..0000000000 --- a/packages/common/versioned-data-util/src/lib.rs +++ /dev/null @@ -1,138 +0,0 @@ -use anyhow::*; - -pub trait VersionedData<'a>: Sized { - type Latest; - - fn latest(latest: Self::Latest) -> Self; - fn into_latest(self) -> Result; - fn deserialize_version(payload: &'a [u8], version: u16) -> Result; - fn serialize_version(self, version: u16) -> Result>; - - fn deserialize_converters() -> Vec Result> { - // HACK: We do this for the type checker - if false { vec![identity] } else { Vec::new() } - } - - fn serialize_converters() -> Vec Result> { - // HACK: We do this for the type checker - if false { vec![identity] } else { Vec::new() } - } - - fn deserialize(payload: &'a [u8], version: u16) -> Result { - let mut data = Self::deserialize_version(payload, version)?; - - for converter in Self::deserialize_converters() - .iter() - .skip(version.saturating_sub(1) as usize) - { - data = converter(data)?; - } - - data.into_latest() - } - - fn serialize(self, version: u16) -> Result> { - let mut data = self; - - for converter in Self::serialize_converters() - .iter() - .skip(version.saturating_sub(1) as usize) - { - data = converter(data)?; - } - - Self::serialize_version(data, version) - } - - /// Serializes data with the version encoded as the first byte. - fn deserialize_with_embedded_version(payload: &'a [u8]) -> Result { - if payload.len() < 2 { - bail!("payload too short for embedded version"); - } - - let version = u16::from_le_bytes([payload[0], payload[1]]); - let payload = &payload[2..]; - - Self::deserialize(payload, version) - } - - /// Deserializes data with the version encoded as the first byte. - fn serialize_with_embedded_version(self, version: u16) -> Result> { - let payload = self.serialize(version)?; - let mut result = Vec::with_capacity(2 + payload.len()); - result.extend_from_slice(&version.to_le_bytes()); - result.extend_from_slice(&payload); - Ok(result) - } -} - -pub trait OwnedVersionedData: Sized { - type Latest; - - fn latest(latest: Self::Latest) -> Self; - fn into_latest(self) -> Result; - fn deserialize_version(payload: &[u8], version: u16) -> Result; - fn serialize_version(self, version: u16) -> Result>; - - fn deserialize_converters() -> Vec Result> { - // HACK: We do this for the type checker - if false { vec![identity] } else { Vec::new() } - } - - fn serialize_converters() -> Vec Result> { - // HACK: We do this for the type checker - if false { vec![identity] } else { Vec::new() } - } - - fn deserialize(payload: &[u8], version: u16) -> Result { - let mut data = Self::deserialize_version(payload, version)?; - - for converter in Self::deserialize_converters() - .iter() - .skip(version.saturating_sub(1) as usize) - { - data = converter(data)?; - } - - data.into_latest() - } - - fn serialize(self, version: u16) -> Result> { - let mut data = self; - - for converter in Self::serialize_converters() - .iter() - .skip(version.saturating_sub(1) as usize) - { - data = converter(data)?; - } - - Self::serialize_version(data, version) - } - - // See VersionedData::deserialize_with_embedded_version. - fn deserialize_with_embedded_version(payload: &[u8]) -> Result { - if payload.len() < 2 { - bail!("payload too short for embedded version"); - } - - let version = u16::from_le_bytes([payload[0], payload[1]]); - let payload = &payload[2..]; - - Self::deserialize(payload, version) - } - - // See VersionedData::serialize_with_embedded_version. - fn serialize_with_embedded_version(self, version: u16) -> Result> { - let payload = self.serialize(version)?; - let mut result = Vec::with_capacity(2 + payload.len()); - result.extend_from_slice(&version.to_le_bytes()); - result.extend_from_slice(&payload); - Ok(result) - } -} - -/// Helper for default trait methods. -fn identity(v: T) -> Result { - Ok(v) -} diff --git a/packages/common/versioned-data-util/tests/test.rs b/packages/common/versioned-data-util/tests/test.rs deleted file mode 100644 index 990e6a8872..0000000000 --- a/packages/common/versioned-data-util/tests/test.rs +++ /dev/null @@ -1,243 +0,0 @@ -use anyhow::*; -use serde::{Deserialize, Serialize}; -use versioned_data_util::OwnedVersionedData; - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -struct TestDataV1 { - id: u32, - name: String, -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -struct TestDataV2 { - id: u32, - name: String, - description: String, -} - -#[derive(Clone)] -enum TestData { - V1(TestDataV1), - V2(TestDataV2), -} - -impl OwnedVersionedData for TestData { - type Latest = TestDataV2; - - fn latest(latest: TestDataV2) -> Self { - TestData::V2(latest) - } - - fn into_latest(self) -> Result { - #[allow(irrefutable_let_patterns)] - if let TestData::V2(data) = self { - Ok(data) - } else { - bail!("version not latest"); - } - } - - fn deserialize_version(payload: &[u8], version: u16) -> Result { - match version { - 1 => Ok(TestData::V1(serde_bare::from_slice(payload)?)), - 2 => Ok(TestData::V2(serde_bare::from_slice(payload)?)), - _ => bail!("invalid version: {version}"), - } - } - - fn serialize_version(self, _version: u16) -> Result> { - match self { - TestData::V1(data) => serde_bare::to_vec(&data).map_err(Into::into), - TestData::V2(data) => serde_bare::to_vec(&data).map_err(Into::into), - } - } - - fn deserialize_converters() -> Vec Result> { - vec![Self::v1_to_v2] - } - - fn serialize_converters() -> Vec Result> { - vec![Self::v2_to_v1] - } -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -struct TestDataNoConvertersV1 { - id: u32, - name: String, -} - -#[derive(Clone)] -enum TestDataNoConverters { - V1(TestDataNoConvertersV1), -} - -impl OwnedVersionedData for TestDataNoConverters { - type Latest = TestDataNoConvertersV1; - - fn latest(latest: TestDataNoConvertersV1) -> Self { - TestDataNoConverters::V1(latest) - } - - fn into_latest(self) -> Result { - #[allow(irrefutable_let_patterns)] - if let TestDataNoConverters::V1(data) = self { - Ok(data) - } else { - bail!("version not latest"); - } - } - - fn deserialize_version(payload: &[u8], version: u16) -> Result { - match version { - 1 => Ok(TestDataNoConverters::V1(serde_bare::from_slice(payload)?)), - _ => bail!("invalid version: {version}"), - } - } - - fn serialize_version(self, _version: u16) -> Result> { - match self { - TestDataNoConverters::V1(data) => serde_bare::to_vec(&data).map_err(Into::into), - } - } -} - -impl TestData { - fn v1_to_v2(self) -> Result { - match self { - TestData::V1(v1) => Ok(TestData::V2(TestDataV2 { - id: v1.id, - name: v1.name, - description: "default".to_string(), - })), - v2 => Ok(v2), - } - } - - fn v2_to_v1(self) -> Result { - match self { - TestData::V2(v2) => Ok(TestData::V1(TestDataV1 { - id: v2.id, - name: v2.name, - })), - v1 => Ok(v1), - } - } -} - -#[test] -fn test_v2_to_v1_to_v2() { - let data = TestDataV2 { - id: 456, - name: "test".to_string(), - description: "will be stripped".to_string(), - }; - - let payload = TestData::V2(data.clone()).serialize(1).unwrap(); - - let deserialized = TestData::deserialize(&payload, 1).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "test"); - assert_eq!(deserialized.description, "default"); -} - -#[test] -fn test_v2_to_v2() { - let data = TestDataV2 { - id: 456, - name: "test".to_string(), - description: "data".to_string(), - }; - - let payload = TestData::V2(data.clone()).serialize(2).unwrap(); - - let deserialized = TestData::deserialize(&payload, 2).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "test"); - assert_eq!(deserialized.description, "data"); -} - -#[test] -fn test_unsupported_version() { - assert!(TestData::deserialize(&[], 99).is_err()); -} - -#[test] -fn test_serialize() { - let data = TestData::V2(TestDataV2 { - id: 456, - name: "serialize_test".to_string(), - description: "will be stripped".to_string(), - }); - - // Test serializing to V1 (should convert V2 -> V1) - let result = data.clone().serialize(1).unwrap(); - let deserialized: TestDataV1 = serde_bare::from_slice(&result).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "serialize_test"); - - // Test serializing to V2 - let result = data.serialize(2).unwrap(); - let deserialized: TestDataV2 = serde_bare::from_slice(&result).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "serialize_test"); - assert_eq!(deserialized.description, "will be stripped"); -} - -#[test] -fn test_embedded_v2_to_v1_to_v2() { - let data = TestDataV2 { - id: 456, - name: "test".to_string(), - description: "will be stripped".to_string(), - }; - - let payload = TestData::V2(data.clone()) - .serialize_with_embedded_version(1) - .unwrap(); - - // First 2 bytes should be the version (2 in little-endian) - assert_eq!(payload[0], 1u8); - assert_eq!(payload[1], 0u8); - - let deserialized = TestData::deserialize_with_embedded_version(&payload).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "test"); - assert_eq!(deserialized.description, "default"); -} - -#[test] -fn test_embedded_v2_to_v2() { - let data = TestDataV2 { - id: 456, - name: "test".to_string(), - description: "data".to_string(), - }; - - let payload = TestData::V2(data.clone()) - .serialize_with_embedded_version(2) - .unwrap(); - - // First 2 bytes should be the version (2 in little-endian) - assert_eq!(payload[0], 2u8); - assert_eq!(payload[1], 0u8); - - let deserialized = TestData::deserialize_with_embedded_version(&payload).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "test"); - assert_eq!(deserialized.description, "data"); -} - -#[test] -fn test_no_converters() { - let data = TestDataNoConvertersV1 { - id: 456, - name: "test".to_string(), - }; - - let payload = TestDataNoConverters::V1(data.clone()).serialize(1).unwrap(); - - let deserialized = TestDataNoConverters::deserialize(&payload, 1).unwrap(); - assert_eq!(deserialized.id, 456); - assert_eq!(deserialized.name, "test"); -} diff --git a/packages/core/pegboard-gateway/Cargo.toml b/packages/core/pegboard-gateway/Cargo.toml index c204cb9069..4447b19c0f 100644 --- a/packages/core/pegboard-gateway/Cargo.toml +++ b/packages/core/pegboard-gateway/Cargo.toml @@ -24,4 +24,4 @@ thiserror.workspace = true tokio-tungstenite.workspace = true tokio.workspace = true universalpubsub.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true diff --git a/packages/core/pegboard-gateway/src/shared_state.rs b/packages/core/pegboard-gateway/src/shared_state.rs index 9e9de26392..60615b01d0 100644 --- a/packages/core/pegboard-gateway/src/shared_state.rs +++ b/packages/core/pegboard-gateway/src/shared_state.rs @@ -9,7 +9,7 @@ use std::{ }; use tokio::sync::{Mutex, mpsc}; use universalpubsub::{NextOutput, PubSub, PublishOpts, Subscriber}; -use versioned_data_util::OwnedVersionedData as _; +use vbare::OwnedVersionedData as _; const GC_INTERVAL: Duration = Duration::from_secs(60); const MESSAGE_ACK_TIMEOUT: Duration = Duration::from_secs(5); diff --git a/packages/core/pegboard-runner/Cargo.toml b/packages/core/pegboard-runner/Cargo.toml index bcca3f7e2c..d529b7b9c9 100644 --- a/packages/core/pegboard-runner/Cargo.toml +++ b/packages/core/pegboard-runner/Cargo.toml @@ -29,7 +29,7 @@ tokio.workspace = true tokio-tungstenite.workspace = true tracing.workspace = true url.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true universalpubsub.workspace = true pegboard.workspace = true diff --git a/packages/core/pegboard-runner/src/client_to_pubsub_task.rs b/packages/core/pegboard-runner/src/client_to_pubsub_task.rs index 643fc1f495..6572e5fd5a 100644 --- a/packages/core/pegboard-runner/src/client_to_pubsub_task.rs +++ b/packages/core/pegboard-runner/src/client_to_pubsub_task.rs @@ -9,7 +9,7 @@ use rivet_guard_core::websocket_handle::WebSocketReceiver; use rivet_runner_protocol::{self as protocol, PROTOCOL_VERSION, versioned}; use std::sync::{Arc, atomic::Ordering}; use universalpubsub::PublishOpts; -use versioned_data_util::OwnedVersionedData as _; +use vbare::OwnedVersionedData as _; use crate::{ conn::Conn, diff --git a/packages/core/pegboard-runner/src/conn.rs b/packages/core/pegboard-runner/src/conn.rs index aa11e3ddac..6545b242f6 100644 --- a/packages/core/pegboard-runner/src/conn.rs +++ b/packages/core/pegboard-runner/src/conn.rs @@ -13,7 +13,7 @@ use std::{ time::Duration, }; use tokio::sync::Mutex; -use versioned_data_util::OwnedVersionedData as _; +use vbare::OwnedVersionedData as _; use crate::{errors::WsError, utils::UrlData}; diff --git a/packages/core/pegboard-runner/src/pubsub_to_client_task.rs b/packages/core/pegboard-runner/src/pubsub_to_client_task.rs index 98e1dcd460..edbae136da 100644 --- a/packages/core/pegboard-runner/src/pubsub_to_client_task.rs +++ b/packages/core/pegboard-runner/src/pubsub_to_client_task.rs @@ -5,7 +5,7 @@ use hyper_tungstenite::tungstenite::Message as WsMessage; use rivet_runner_protocol::{self as protocol, versioned}; use std::sync::Arc; use universalpubsub::{NextOutput, Subscriber}; -use versioned_data_util::OwnedVersionedData as _; +use vbare::OwnedVersionedData as _; use crate::{ conn::{Conn, TunnelActiveRequest}, diff --git a/packages/infra/engine/Cargo.toml b/packages/infra/engine/Cargo.toml index c431000f03..ec65521d74 100644 --- a/packages/infra/engine/Cargo.toml +++ b/packages/infra/engine/Cargo.toml @@ -66,4 +66,4 @@ rivet-util.workspace = true rstest.workspace = true tokio-tungstenite.workspace = true tracing-subscriber.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true diff --git a/packages/services/epoxy/Cargo.toml b/packages/services/epoxy/Cargo.toml index b20f72c94d..5acd9ecc8b 100644 --- a/packages/services/epoxy/Cargo.toml +++ b/packages/services/epoxy/Cargo.toml @@ -34,7 +34,7 @@ tracing.workspace = true universaldb.workspace = true url.workspace = true uuid.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true [dev-dependencies] gas.workspace = true diff --git a/packages/services/epoxy/src/http_client.rs b/packages/services/epoxy/src/http_client.rs index f3b440a79f..5d94b230e1 100644 --- a/packages/services/epoxy/src/http_client.rs +++ b/packages/services/epoxy/src/http_client.rs @@ -7,7 +7,7 @@ use epoxy_protocol::{ use futures_util::{StreamExt, stream::FuturesUnordered}; use rivet_api_builder::ApiCtx; use std::future::Future; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; use crate::utils; diff --git a/packages/services/epoxy/src/http_routes.rs b/packages/services/epoxy/src/http_routes.rs index 0350a0ec89..50777228b3 100644 --- a/packages/services/epoxy/src/http_routes.rs +++ b/packages/services/epoxy/src/http_routes.rs @@ -2,7 +2,7 @@ use anyhow::*; use axum::body::Bytes; use epoxy_protocol::{protocol, versioned}; use rivet_api_builder::prelude::*; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; #[derive(Deserialize)] pub struct VersionedPath { diff --git a/packages/services/epoxy/src/keys/replica.rs b/packages/services/epoxy/src/keys/replica.rs index 809abb5fa4..e65788d3a0 100644 --- a/packages/services/epoxy/src/keys/replica.rs +++ b/packages/services/epoxy/src/keys/replica.rs @@ -1,7 +1,7 @@ use anyhow::*; use epoxy_protocol::protocol::{ReplicaId, SlotId}; use universaldb::prelude::*; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; #[derive(Debug)] pub struct InstanceNumberKey; diff --git a/packages/services/namespace/Cargo.toml b/packages/services/namespace/Cargo.toml index 66bcc71131..dbeba660ce 100644 --- a/packages/services/namespace/Cargo.toml +++ b/packages/services/namespace/Cargo.toml @@ -22,4 +22,4 @@ tracing.workspace = true universaldb.workspace = true url.workspace = true utoipa.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true diff --git a/packages/services/namespace/src/keys.rs b/packages/services/namespace/src/keys.rs index bb55eef205..1349f8d065 100644 --- a/packages/services/namespace/src/keys.rs +++ b/packages/services/namespace/src/keys.rs @@ -5,7 +5,7 @@ use gas::prelude::*; use serde::Serialize; use universaldb::prelude::*; use utoipa::ToSchema; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; pub fn subspace() -> universaldb::utils::Subspace { universaldb::utils::Subspace::new(&(RIVET, NAMESPACE)) diff --git a/packages/services/pegboard/Cargo.toml b/packages/services/pegboard/Cargo.toml index 2d686fbf65..e9a661c822 100644 --- a/packages/services/pegboard/Cargo.toml +++ b/packages/services/pegboard/Cargo.toml @@ -28,4 +28,4 @@ tracing.workspace = true universaldb.workspace = true universalpubsub.workspace = true utoipa.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true diff --git a/packages/services/pegboard/src/keys/ns.rs b/packages/services/pegboard/src/keys/ns.rs index a30a82d8c6..33dc7ddbcc 100644 --- a/packages/services/pegboard/src/keys/ns.rs +++ b/packages/services/pegboard/src/keys/ns.rs @@ -3,7 +3,7 @@ use std::result::Result::Ok; use anyhow::*; use gas::prelude::*; use universaldb::prelude::*; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; #[derive(Debug)] pub struct RunnerAllocIdxKey { diff --git a/packages/services/pegboard/src/keys/runner.rs b/packages/services/pegboard/src/keys/runner.rs index fcdd520ee1..d7c6774115 100644 --- a/packages/services/pegboard/src/keys/runner.rs +++ b/packages/services/pegboard/src/keys/runner.rs @@ -3,7 +3,7 @@ use std::result::Result::Ok; use anyhow::*; use gas::prelude::*; use universaldb::prelude::*; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; #[derive(Debug)] pub struct CreateTsKey { diff --git a/packages/services/pegboard/src/workflows/runner.rs b/packages/services/pegboard/src/workflows/runner.rs index 8da7c531aa..4dc38ee257 100644 --- a/packages/services/pegboard/src/workflows/runner.rs +++ b/packages/services/pegboard/src/workflows/runner.rs @@ -7,7 +7,7 @@ use universaldb::{ utils::{FormalChunkedKey, IsolationLevel::*}, }; use universalpubsub::PublishOpts; -use versioned_data_util::OwnedVersionedData as _; +use vbare::OwnedVersionedData as _; use crate::{keys, workflows::actor::Allocate}; diff --git a/sdks/rust/bare_gen/Cargo.toml b/sdks/rust/bare_gen/Cargo.toml deleted file mode 100644 index f25f434d9e..0000000000 --- a/sdks/rust/bare_gen/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "bare_gen" -version.workspace = true -authors.workspace = true -license.workspace = true -edition.workspace = true - -[dependencies] -heck.workspace = true -pest_derive.workspace = true -pest.workspace = true -proc-macro2.workspace = true -quote.workspace = true -serde.workspace = true -syn.workspace = true diff --git a/sdks/rust/bare_gen/src/grammar.pest b/sdks/rust/bare_gen/src/grammar.pest deleted file mode 100644 index b9fd16bf70..0000000000 --- a/sdks/rust/bare_gen/src/grammar.pest +++ /dev/null @@ -1,46 +0,0 @@ -//schema = { SOI ~ user_type+ ~ EOI } -schema = { SOI ~ user_type+ ~ EOI } -type_l = _{ "type" } -user_type = { "type" ~ user_type_name ~ any_type } -user_type_name = @{ ASCII_ALPHA_UPPER ~ (ASCII_ALPHANUMERIC | "_" | "-")* } -unsigned_t = { "uint" | "u64" | "u32" | "u16" | "u8" } -signed_t = { "int" | "i64" | "i32" | "i16" | "i8" } -void_t = { "void" } -str_t = { "str" } -bool_t = { "bool" } -float_t = { "f32" | "f64" } -data_t = { "data" ~ (length)? } -enum_t = { "enum" ~ "{" ~ enum_value+ ~ "}" } -enum_value = { enum_value_name ~ ("=" ~ integer)? } -enum_value_name = @{ ASCII_ALPHA_UPPER ~ (ASCII_ALPHANUMERIC | "_" | "-")* } -list_t = { "list" ~ type_t ~ length? } -type_t = _{ "<" ~ any_type ~ ">" } -struct_t = { "struct" ~ "{" ~ struct_field+ ~ "}" } -map_t = { "map" ~ type_t ~ type_t } -union_t = { "union" ~ "{" ~ any_type ~ ("|" ~ any_type)* ~ "}" } -optional_t = { "optional" ~ type_t } -struct_field = { struct_field_name ~ ":" ~ any_type } -struct_field_name = { (ASCII_ALPHANUMERIC | "_" | "-")+ } -length = _{ "[" ~ integer ~ "]" } -integer = !{ ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } -primative_type = _{ - unsigned_t - | signed_t - | bool_t - | float_t - | data_t - | str_t - | void_t -} -any_type = _{ - user_type_name - | list_t - | struct_t - | enum_t - | map_t - | union_t - | optional_t - | primative_type -} -WHITESPACE = _{ " " | "\n" | "\t" | NEWLINE } -COMMENT = _{ "#" ~ (!NEWLINE ~ ANY)* ~ NEWLINE } \ No newline at end of file diff --git a/sdks/rust/bare_gen/src/lib.rs b/sdks/rust/bare_gen/src/lib.rs deleted file mode 100644 index 6c8cdb358a..0000000000 --- a/sdks/rust/bare_gen/src/lib.rs +++ /dev/null @@ -1,398 +0,0 @@ -/*! -`bare_gen` provides a simple function that generates Rust types from BARE schema files. -Generated types implicitly implement `serde::Serialize` and `serde::Deserialize`, as `serde_bare` -is used to handle encoding and decoding. Please see -[serde_bare's documentation](https://docs.rs/serde_bare/latest/serde_bare/) for information on how -the Rust data model maps to the BARE data model. - -To use this macro, define a BARE schema file and populate it with type declarations. - -For example: - - -```bare -// schema.bare -type PublicKey data[128] -type Time str # ISO 8601 - -type Department enum { - ACCOUNTING - ADMINISTRATION - CUSTOMER_SERVICE - DEVELOPMENT - - # Reserved for the CEO - JSMITH = 99 -} - -type Address list[4] # street, city, state, country - -type Customer struct { - name: str - email: str - address: Address - orders: list - metadata: map -} - -type Employee struct { - name: str - email: str - address: Address - department: Department - hireDate: Time - publicKey: optional - metadata: map -} - -type TerminatedEmployee void - -type Person union {Customer | Employee | TerminatedEmployee} -``` - -Then, within a Rust source file: - -```ignore - -bare_gen::bare_schema("schema.bare"); // TokenStream - -``` - -# BARE => Rust Data Mapping - -In most areas, the BARE data model maps cleanly to a Rust representation. Unless otherwise -specified, the most obvious Rust data type is generated from a given BARE type. For example, -a BARE `option` is mapped to Rust's `Option`, BARE unions and enums are mapped to -Rust `enum`s. See below for opinions that this crate has around data types that do not map -as cleanly or require additional explanation. - -## Maps - -BARE maps are interpreted as `HashMap` in Rust. As of now, this is not configurable, but -may be in the future. - -## Variable Length Integers - -The variable `uint` and `int` types are mapped to [`serde_bare::UInt`] and [`serde_bare::Int`] -respectively. These types wrap `u64` and `i64` (the largest possible sized values stored in BARE -variable length integers). - -Arrays that have 32 or less elements are mapped directly as Rust arrays, while BARE arrays with -more than 32 elements are converted into `Vec`. - -*/ - -use std::{collections::BTreeMap, fs::read_to_string, path::Path}; - -use heck::{ToSnakeCase, ToUpperCamelCase}; -use parser::{AnyType, PrimativeType, StructField, parse_string}; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; - -mod parser; - -fn ident_from_string(s: &String) -> Ident { - Ident::new(s, Span::call_site()) -} - -/// `bare_schema` parses a BARE schema file and generates equivalent Rust code that is capable of -/// being serialized to and deserialized from bytes using the BARE encoding format. The macro takes -/// exactly one argument, a string that will be parsed as path pointing to a BARE schema file. The -/// path is treated as relative to the file location of the macro's use. -/// For details on how the BARE data model maps to the Rust data model, see the [`Serialize` -/// derive macro's documentation.](https://docs.rs/serde_bare/latest/serde_bare/) -pub fn bare_schema(schema_path: &Path) -> proc_macro2::TokenStream { - let file = read_to_string(schema_path).unwrap(); - let mut schema_generator = SchemaGenerator { - global_output: Default::default(), - user_type_registry: parse_string(&file), - }; - - for (name, user_type) in &schema_generator.user_type_registry.clone() { - schema_generator.gen_user_type(&name, &user_type); - } - - schema_generator.complete() -} - -struct SchemaGenerator { - global_output: Vec, - user_type_registry: BTreeMap, -} - -impl SchemaGenerator { - /// Completes a generation cycle by consuming the `SchemaGenerator` and yielding a - /// `TokenStream`. - fn complete(self) -> TokenStream { - let user_type_syntax = self.global_output; - quote! { - #[allow(unused_imports)] - use rivet_util::serde::HashableMap; - #[allow(unused_imports)] - use serde::{Serialize, Deserialize}; - #[allow(unused_imports)] - use serde_bare::{Uint, Int}; - - #(#user_type_syntax)* - } - } - - /// `gen_user_type` is responsible for generating the token streams of a single user type at a top - /// level. Rust does not support anonymous structs/enums/etc., so we must recursively parse any - /// anonymous definitions and generate top-level definitions. As such, this function may generate - /// multiple types. - fn gen_user_type(&mut self, name: &String, t: &AnyType) { - #[allow(unused_assignments)] - use AnyType::*; - let def = match t { - Primative(p) => { - let def = gen_primative_type_def(p); - let ident = ident_from_string(name); - quote! { - pub type #ident = #def; - } - } - List { inner, length } => { - let def = self.gen_list(name, inner.as_ref(), length); - let ident = ident_from_string(name); - quote! { - pub type #ident = #def; - } - } - Struct(fields) => { - self.gen_struct(name, fields); - // `gen_struct` only has side-effects on the registry, so we return nothing - TokenStream::new() - } - Map { key, value } => { - let map_def = self.gen_map(name, key.as_ref(), value.as_ref()); - let ident = ident_from_string(name); - quote! { - pub type #ident = #map_def; - } - } - Optional(inner) => { - let inner_def = self.dispatch_type(name, inner); - let ident = ident_from_string(name); - quote! { - pub type #ident = #inner_def; - } - } - TypeReference(reference) => { - panic!("Type reference is not valid as a top level definition: {reference}") - } - Enum(members) => { - self.gen_enum(name, members); - // `gen_enum` only has side-effects on the registry, so we return nothing - TokenStream::new() - } - Union(members) => { - self.gen_union(name, members); - // `gen_union` only has side-effects on the registry, so we return nothing - TokenStream::new() - } - }; - self.global_output.push(def); - } - - fn dispatch_type(&mut self, name: &String, any_type: &AnyType) -> TokenStream { - match any_type { - AnyType::Primative(p) => gen_primative_type_def(p), - AnyType::List { inner, length } => self.gen_list(name, inner.as_ref(), length), - AnyType::Struct(fields) => self.gen_struct(name, fields), - AnyType::Enum(members) => self.gen_enum(name, members), - AnyType::Map { key, value } => self.gen_map(name, key.as_ref(), value.as_ref()), - AnyType::Union(members) => self.gen_union(name, members), - AnyType::Optional(inner) => self.gen_option(name, inner), - AnyType::TypeReference(i) => { - let ident = ident_from_string(i); - quote! { #ident } - } - } - } - - fn gen_map(&mut self, name: &String, key: &AnyType, value: &AnyType) -> TokenStream { - let key_def = self.dispatch_type(name, key); - let val_def = self.dispatch_type(name, value); - quote! { - HashableMap<#key_def, #val_def> - } - } - - fn gen_list( - &mut self, - name: &String, - inner_type: &AnyType, - size: &Option, - ) -> TokenStream { - let inner_def = self.dispatch_type(name, inner_type); - match *size { - Some(size) if size <= 32 => quote! { - [#inner_def; #size] - }, - _ => quote! { - Vec<#inner_def> - }, - } - } - - fn gen_struct(&mut self, name: &String, fields: &Vec) -> TokenStream { - // clone so we can safely drain this - let fields_clone = fields.clone(); - let fields_gen = self.gen_struct_field(name, fields_clone); - self.gen_anonymous(name, |ident| { - quote! { - #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Hash)] - pub struct #ident { - #(#fields_gen),* - } - } - }) - } - - fn gen_union(&mut self, name: &String, members: &Vec) -> TokenStream { - let mut members_def: Vec = Vec::with_capacity(members.len()); - for (i, member) in members.iter().enumerate() { - // If this member is a user type alias for void, we'll not generate an inner type later - let is_void_type = match member { - AnyType::TypeReference(i) if self.user_type_registry.get(i).is_some() => { - let reference = self.user_type_registry.get(i).unwrap(); - matches!(reference, AnyType::Primative(PrimativeType::Void)) - } - _ => false, - }; - - // This is to allow the `registry` binding to not shadow the function arg, but instead - // rebind it as it's used in the subsequent `gen_anonymous` call. We'll get move errors if - // we don't do it this way. - #[allow(unused_assignments)] - let mut member_def = TokenStream::new(); - member_def = match member { - AnyType::Struct(fields) => { - let fields_defs = self.gen_struct_field(name, fields.clone()); - quote! { - { - #(#fields_defs),* - } - } - } - AnyType::TypeReference(i) if is_void_type => { - let inner_def = ident_from_string(i); - // The `inner_def` is always a top-level type here - quote! { - #inner_def - } - } - _ => { - let inner_def = self.dispatch_type(&format!("{name}Member{i}"), member); - // The `inner_def` is always a top-level type here - quote! { - #inner_def(#inner_def) - } - } - }; - members_def.push(member_def); - } - self.gen_anonymous(name, |ident| { - quote! { - #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Hash)] - pub enum #ident { - #(#members_def),* - } - } - }) - } - - fn gen_option(&mut self, name: &String, inner: &AnyType) -> TokenStream { - let inner_def = self.dispatch_type(name, inner); - quote! { - Option<#inner_def> - } - } - - fn gen_struct_field( - &mut self, - struct_name: &String, - fields: Vec, - ) -> Vec { - let mut fields_gen: Vec = Vec::with_capacity(fields.len()); - for StructField { name, type_r } in fields { - let name = name.to_snake_case(); - #[allow(unused_assignments)] - let field_gen = self.dispatch_type(&format!("{struct_name}{name}"), &type_r); - let ident = ident_from_string(&name); - fields_gen.push(quote! { - pub #ident: #field_gen - }) - } - fields_gen - } - - fn gen_enum(&mut self, name: &String, members: &Vec<(String, Option)>) -> TokenStream { - let member_defs = members.iter().map(|(name, val)| { - let ident = ident_from_string(&name.to_upper_camel_case()); - if let Some(val) = val { - quote! { - #ident = #val - } - } else { - quote! { - #ident - } - } - }); - self.gen_anonymous(name, |ident| { - quote! { - #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, PartialOrd, Ord, Hash, Clone)] - #[repr(usize)] - pub enum #ident { - #(#member_defs),* - } - } - }) - } - - /// `gen_anonymous` generates an identifier from the provided `name`, passed it to `inner`, pushes - /// the result of `inner` to the `registry`, and yields a quoted version of the generated - /// identifier. This is a common operation when generating types that are anonymous in a BARE - /// schema but not allowed by be defined anonymously in Rust. - fn gen_anonymous( - &mut self, - name: &String, - inner: impl FnOnce(Ident) -> TokenStream, - ) -> TokenStream { - let ident = ident_from_string(name); - self.global_output.push(inner(ident.clone())); - quote! { - #ident - } - } -} - -fn gen_primative_type_def(p: &PrimativeType) -> TokenStream { - use PrimativeType::*; - match p { - UInt => quote! { Uint }, - U64 => quote! { u64 }, - U32 => quote! { u32 }, - U16 => quote! { u16 }, - U8 => quote! { u8 }, - Int => quote! { Int }, - I64 => quote! { i64 }, - I32 => quote! { i32 }, - I16 => quote! { i16 }, - I8 => quote! { i8 }, - F64 => quote! { f64 }, - F32 => quote! { f32 }, - Str => quote! { String }, - Data(s) => match s { - Some(size) if *size <= 32 => quote! { [u8; #size] }, - _ => quote! { Vec }, - }, - Void => quote! { () }, - Bool => quote! { bool }, - } -} diff --git a/sdks/rust/bare_gen/src/parser.rs b/sdks/rust/bare_gen/src/parser.rs deleted file mode 100644 index 7f30422439..0000000000 --- a/sdks/rust/bare_gen/src/parser.rs +++ /dev/null @@ -1,228 +0,0 @@ -#![allow(dead_code)] -use pest::{Parser, iterators::Pair}; -use pest_derive::Parser; -use std::collections::BTreeMap; - -#[derive(Parser)] -#[grammar = "grammar.pest"] -struct BARE; - -pub type Length = usize; - -#[derive(Debug, Clone, Copy)] -pub enum PrimativeType { - UInt, - U64, - U32, - U16, - U8, - Int, - I64, - I32, - I16, - I8, - F64, - F32, - Str, - Data(Option), - Void, - Bool, -} - -#[derive(Debug, Clone)] -pub enum AnyType { - Primative(PrimativeType), - List { - inner: Box, - length: Option, - }, - Struct(Vec), - Enum(Vec<(String, Option)>), - Map { - key: Box, - value: Box, - }, - Union(Vec), - Optional(Box), - TypeReference(String), -} - -#[derive(Debug, Clone)] -pub struct StructField { - pub name: String, - pub type_r: AnyType, -} - -pub fn parse_string(schema: &str) -> BTreeMap { - let schema = BARE::parse(Rule::schema, &schema) - .unwrap_or_else(|e| panic!("{}", e)) - .next() - .unwrap(); // this can't fail if parsing didn't fail - if schema.as_rule() != Rule::schema { - unreachable!() - } - let mut user_type_registry: BTreeMap = BTreeMap::default(); - for user_types in schema.into_inner() { - if user_types.as_rule() == Rule::EOI { - break; - } - let mut inner = user_types.into_inner(); - let user_type_name = inner.next().unwrap(); - let user_type_type = inner.next().unwrap(); - if user_type_registry.contains_key(user_type_name.as_str()) { - panic!("Duplicate definition: {:?}", user_type_name.as_span()) - } - let t = parse_any_type(&user_type_registry, user_type_type); - user_type_registry.insert(user_type_name.as_str().into(), t); - } - user_type_registry -} - -fn parse_any_type(registry: &BTreeMap, pair: Pair<'_, Rule>) -> AnyType { - match pair.as_rule() { - Rule::unsigned_t => parse_unsigned_int(pair), - Rule::signed_t => parse_signed_int(pair), - Rule::void_t => AnyType::Primative(PrimativeType::Void), - Rule::str_t => AnyType::Primative(PrimativeType::Str), - Rule::bool_t => AnyType::Primative(PrimativeType::Bool), - Rule::float_t => parse_float(pair), - Rule::data_t => { - let length_t = pair.into_inner().next(); - if let Some(length_t) = length_t { - let length: usize = length_t.as_str().parse().unwrap(); - AnyType::Primative(PrimativeType::Data(Some(length))) - } else { - AnyType::Primative(PrimativeType::Data(None)) - } - } - Rule::enum_t => parse_enum(pair), - Rule::list_t => parse_list(registry, pair), - Rule::struct_t => parse_struct(registry, pair), - Rule::map_t => parse_map(registry, pair), - Rule::union_t => parse_union(registry, pair), - Rule::optional_t => { - let inner_type = pair.into_inner().next().unwrap(); - AnyType::Optional(Box::new(parse_any_type(registry, inner_type))) - } - Rule::user_type_name => { - let user_type = pair.as_str(); - if registry.contains_key(user_type) { - AnyType::TypeReference(user_type.into()) - } else { - panic!("User type {user_type} has not been defined yet."); - } - } - x => panic!("Unreachable: {x:?}"), - } -} - -fn parse_unsigned_int(pair: Pair<'_, Rule>) -> AnyType { - assert!(pair.as_rule() == Rule::unsigned_t); - AnyType::Primative(match pair.as_str() { - "uint" => PrimativeType::UInt, - "u64" => PrimativeType::U64, - "u32" => PrimativeType::U32, - "u16" => PrimativeType::U16, - "u8" => PrimativeType::U8, - _ => unreachable!(), - }) -} - -fn parse_signed_int(pair: Pair<'_, Rule>) -> AnyType { - assert!(pair.as_rule() == Rule::signed_t); - AnyType::Primative(match pair.as_str() { - "int" => PrimativeType::Int, - "i64" => PrimativeType::I64, - "i32" => PrimativeType::I32, - "i16" => PrimativeType::I16, - "i8" => PrimativeType::I8, - _ => unreachable!(), - }) -} - -fn parse_enum(pair: Pair<'_, Rule>) -> AnyType { - let mut members: Vec<(String, Option)> = Vec::new(); - for enum_value in pair.into_inner() { - assert!(enum_value.as_rule() == Rule::enum_value); - let mut e = enum_value.into_inner(); - let enum_value_name = e.next().unwrap(); - let value: Option = e.next().and_then(|e| Some(e.as_str().parse().unwrap())); - members.push((enum_value_name.as_str().into(), value)); - } - AnyType::Enum(members) -} - -fn parse_list(registry: &BTreeMap, pair: Pair<'_, Rule>) -> AnyType { - let mut list = pair.into_inner(); - let list_type = list.next().unwrap(); - let inner = parse_any_type(registry, list_type); - let length: Option = list - .next() - .and_then(|e: Pair<'_, Rule>| Some(e.as_str().parse().unwrap())); - AnyType::List { - inner: Box::new(inner), - length, - } -} - -fn parse_struct(registry: &BTreeMap, pair: Pair<'_, Rule>) -> AnyType { - let mut st = pair.into_inner(); - let mut fields: Vec = Vec::new(); - while let Some(struct_t) = st.next() { - let mut struct_field = struct_t.into_inner(); - let field_name = struct_field.next().unwrap(); - let field_type = struct_field.next().unwrap(); - let ft = parse_any_type(registry, field_type); - fields.push(StructField { - name: field_name.as_str().to_string(), - type_r: ft, - }) - } - AnyType::Struct(fields) -} -fn parse_map(registry: &BTreeMap, pair: Pair<'_, Rule>) -> AnyType { - let mut map = pair.into_inner(); - let key_t = map.next().unwrap(); - let value_t = map.next().unwrap(); - let key = parse_any_type(registry, key_t); - let value = parse_any_type(registry, value_t); - AnyType::Map { - key: Box::new(key), - value: Box::new(value), - } -} -fn parse_union(registry: &BTreeMap, pair: Pair<'_, Rule>) -> AnyType { - let union_t = pair.into_inner(); - let mut members: Vec = Vec::new(); - for union_member in union_t { - let t = parse_any_type(registry, union_member); - members.push(t); - } - AnyType::Union(members) -} - -fn parse_float(pair: Pair<'_, Rule>) -> AnyType { - assert!(pair.as_rule() == Rule::float_t); - AnyType::Primative(match pair.as_str() { - "f32" => PrimativeType::F32, - "f64" => PrimativeType::F64, - _ => unreachable!(), - }) -} - -#[cfg(test)] -mod test { - use std::fs::read_to_string; - - use super::*; - - #[test] - fn basic() { - let file = read_to_string("./src/example.bare").unwrap(); - let user_type_registry: BTreeMap = parse_string(&file); - - for (key, value) in user_type_registry.iter() { - println!("{} = {:?}", key, value); - } - } -} diff --git a/sdks/rust/data/Cargo.toml b/sdks/rust/data/Cargo.toml index 3282e73918..c0a572ee7b 100644 --- a/sdks/rust/data/Cargo.toml +++ b/sdks/rust/data/Cargo.toml @@ -12,11 +12,7 @@ rivet-runner-protocol.workspace = true rivet-util.workspace = true serde_bare.workspace = true serde.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true [build-dependencies] -bare_gen.workspace = true -indoc.workspace = true -prettyplease.workspace = true -serde_json.workspace = true -syn.workspace = true +vbare-compiler.workspace = true diff --git a/sdks/rust/data/build.rs b/sdks/rust/data/build.rs index e6b18ab845..85750eb2a2 100644 --- a/sdks/rust/data/build.rs +++ b/sdks/rust/data/build.rs @@ -1,69 +1,15 @@ -use std::{env, fs, path::Path}; +use std::path::Path; -use indoc::formatdoc; - -mod rust { - use super::*; - - pub fn generate_sdk(schema_dir: &Path) { - let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = Path::new(&out_dir); - let mut all_names = Vec::new(); - - for entry in fs::read_dir(schema_dir).unwrap().flatten() { - let path = entry.path(); - - if path.is_dir() { - continue; - } - - let bare_name = path - .file_name() - .unwrap() - .to_str() - .unwrap() - .rsplit_once('.') - .unwrap() - .0 - .replace(".", "_"); - - let content = - prettyplease::unparse(&syn::parse2(bare_gen::bare_schema(&path)).unwrap()); - fs::write(out_path.join(format!("{bare_name}_generated.rs")), content).unwrap(); - - all_names.push(bare_name.to_string()); - } - - let mut mod_content = String::new(); - mod_content.push_str("// Auto-generated module file for BARE schemas\n\n"); - - // Generate module declarations for each version - for name in all_names { - mod_content.push_str(&formatdoc!( - r#" - pub mod {name} {{ - include!(concat!(env!("OUT_DIR"), "/{name}_generated.rs")); - }} - "#, - )); - } - - let mod_file_path = out_path.join("combined_imports.rs"); - fs::write(&mod_file_path, mod_content).expect("Failed to write combined_imports.rs"); - } -} - -fn main() { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); +fn main() -> Result<(), Box> { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?; let workspace_root = Path::new(&manifest_dir) .parent() .and_then(|p| p.parent()) .and_then(|p| p.parent()) - .expect("Failed to find workspace root"); + .ok_or("Failed to find workspace root")?; let schema_dir = workspace_root.join("sdks").join("schemas").join("data"); - println!("cargo:rerun-if-changed={}", schema_dir.display()); - - rust::generate_sdk(&schema_dir); + let cfg = vbare_compiler::Config::with_hashable_map(); + vbare_compiler::process_schemas_with_config(&schema_dir, &cfg) } diff --git a/sdks/rust/data/src/versioned.rs b/sdks/rust/data/src/versioned.rs index b898f38096..35d827211a 100644 --- a/sdks/rust/data/src/versioned.rs +++ b/sdks/rust/data/src/versioned.rs @@ -1,5 +1,5 @@ use anyhow::{Ok, Result, bail}; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; use crate::generated::*; diff --git a/sdks/rust/epoxy-protocol/Cargo.toml b/sdks/rust/epoxy-protocol/Cargo.toml index a542d779ae..e135f1ee4f 100644 --- a/sdks/rust/epoxy-protocol/Cargo.toml +++ b/sdks/rust/epoxy-protocol/Cargo.toml @@ -10,11 +10,8 @@ anyhow.workspace = true rivet-util.workspace = true serde_bare.workspace = true serde.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true [build-dependencies] -bare_gen.workspace = true -indoc.workspace = true -prettyplease.workspace = true -serde_json.workspace = true -syn.workspace = true +vbare-compiler.workspace = true + diff --git a/sdks/rust/epoxy-protocol/build.rs b/sdks/rust/epoxy-protocol/build.rs index ade0e18814..ad71a942fa 100644 --- a/sdks/rust/epoxy-protocol/build.rs +++ b/sdks/rust/epoxy-protocol/build.rs @@ -1,69 +1,18 @@ -use std::{env, fs, path::Path}; +use std::path::Path; -use indoc::formatdoc; - -mod rust { - use super::*; - - pub fn generate_sdk(schema_dir: &Path) { - let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = Path::new(&out_dir); - let mut all_names = Vec::new(); - - for entry in fs::read_dir(schema_dir).unwrap().flatten() { - let path = entry.path(); - - if path.is_dir() { - continue; - } - - let bare_name = path - .file_name() - .unwrap() - .to_str() - .unwrap() - .rsplit_once('.') - .unwrap() - .0; - - let content = - prettyplease::unparse(&syn::parse2(bare_gen::bare_schema(&path)).unwrap()); - fs::write(out_path.join(format!("{bare_name}_generated.rs")), content).unwrap(); - - all_names.push(bare_name.to_string()); - } - - let mut mod_content = String::new(); - mod_content.push_str("// Auto-generated module file for BARE schemas\n\n"); - - // Generate module declarations for each version - for name in all_names { - mod_content.push_str(&formatdoc!( - r#" - pub mod {name} {{ - include!(concat!(env!("OUT_DIR"), "/{name}_generated.rs")); - }} - "#, - )); - } - - let mod_file_path = out_path.join("combined_imports.rs"); - fs::write(&mod_file_path, mod_content).expect("Failed to write combined_imports.rs"); - } -} - -fn main() { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let schema_dir = Path::new(&manifest_dir) +fn main() -> Result<(), Box> { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?; + let workspace_root = Path::new(&manifest_dir) .parent() .and_then(|p| p.parent()) .and_then(|p| p.parent()) - .expect("Failed to find workspace root") + .ok_or("Failed to find workspace root")?; + + let schema_dir = workspace_root .join("sdks") .join("schemas") .join("epoxy-protocol"); - println!("cargo:rerun-if-changed={}", schema_dir.display()); - - rust::generate_sdk(&schema_dir); + let cfg = vbare_compiler::Config::with_hashable_map(); + vbare_compiler::process_schemas_with_config(&schema_dir, &cfg) } diff --git a/sdks/rust/epoxy-protocol/src/versioned.rs b/sdks/rust/epoxy-protocol/src/versioned.rs index 169511da26..8475286679 100644 --- a/sdks/rust/epoxy-protocol/src/versioned.rs +++ b/sdks/rust/epoxy-protocol/src/versioned.rs @@ -1,5 +1,5 @@ use anyhow::{Ok, Result, bail}; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; use crate::{PROTOCOL_VERSION, generated::v1}; diff --git a/sdks/rust/runner-protocol/Cargo.toml b/sdks/rust/runner-protocol/Cargo.toml index eac3d00bb8..65d781284f 100644 --- a/sdks/rust/runner-protocol/Cargo.toml +++ b/sdks/rust/runner-protocol/Cargo.toml @@ -13,11 +13,7 @@ rivet-util.workspace = true serde_bare.workspace = true serde.workspace = true utoipa.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true [build-dependencies] -bare_gen.workspace = true -indoc.workspace = true -prettyplease.workspace = true -serde_json.workspace = true -syn.workspace = true +vbare-compiler.workspace = true diff --git a/sdks/rust/runner-protocol/build.rs b/sdks/rust/runner-protocol/build.rs index 1394b01064..4f1bb3902a 100644 --- a/sdks/rust/runner-protocol/build.rs +++ b/sdks/rust/runner-protocol/build.rs @@ -1,66 +1,45 @@ use std::{ - env, fs, + fs, path::{Path, PathBuf}, process::Command, }; -use indoc::formatdoc; - -mod rust { - use super::*; - - pub fn generate_sdk(schema_dir: &Path) { - let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = Path::new(&out_dir); - let mut all_names = Vec::new(); - - for entry in fs::read_dir(schema_dir).unwrap().flatten() { - let path = entry.path(); - - if path.is_dir() { - continue; - } - - let bare_name = path - .file_name() - .unwrap() - .to_str() - .unwrap() - .rsplit_once('.') - .unwrap() - .0; - - let content = - prettyplease::unparse(&syn::parse2(bare_gen::bare_schema(&path)).unwrap()); - fs::write(out_path.join(format!("{bare_name}_generated.rs")), content).unwrap(); +fn main() -> Result<(), Box> { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?; + let workspace_root = Path::new(&manifest_dir) + .parent() + .and_then(|p| p.parent()) + .and_then(|p| p.parent()) + .ok_or("Failed to find workspace root")?; - all_names.push(bare_name.to_string()); - } + let schema_dir = workspace_root + .join("sdks") + .join("schemas") + .join("runner-protocol"); - let mut mod_content = String::new(); - mod_content.push_str("// Auto-generated module file for BARE schemas\n\n"); - - // Generate module declarations for each version - for name in all_names { - mod_content.push_str(&formatdoc!( - r#" - pub mod {name} {{ - include!(concat!(env!("OUT_DIR"), "/{name}_generated.rs")); - }} - "#, - )); - } + // Rust SDK generation + let cfg = vbare_compiler::Config::with_hashable_map(); + vbare_compiler::process_schemas_with_config(&schema_dir, &cfg)?; - let mod_file_path = out_path.join("combined_imports.rs"); - fs::write(&mod_file_path, mod_content).expect("Failed to write combined_imports.rs"); + // TypeScript SDK generation + let cli_js_path = workspace_root.join("node_modules/@bare-ts/tools/dist/bin/cli.js"); + if cli_js_path.exists() { + typescript::generate_sdk(&schema_dir); + } else { + println!( + "cargo:warning=TypeScript SDK generation skipped: cli.js not found at {}. Run `pnpm install` to install.", + cli_js_path.display() + ); } + + Ok(()) } mod typescript { use super::*; pub fn generate_sdk(schema_dir: &Path) { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let workspace_root = Path::new(&manifest_dir) .parent() .and_then(|p| p.parent()) @@ -127,32 +106,3 @@ fn find_highest_version(schema_dir: &Path) -> PathBuf { highest_version_path } - -fn main() { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let workspace_root = Path::new(&manifest_dir) - .parent() - .and_then(|p| p.parent()) - .and_then(|p| p.parent()) - .expect("Failed to find workspace root"); - - let schema_dir = workspace_root - .join("sdks") - .join("schemas") - .join("runner-protocol"); - - println!("cargo:rerun-if-changed={}", schema_dir.display()); - - rust::generate_sdk(&schema_dir); - - // Check if cli.js exists before attempting TypeScript generation - let cli_js_path = workspace_root.join("node_modules/@bare-ts/tools/dist/bin/cli.js"); - if cli_js_path.exists() { - typescript::generate_sdk(&schema_dir); - } else { - println!( - "cargo:warning=TypeScript SDK generation skipped: cli.js not found at {}. Run `pnpm install` to install.", - cli_js_path.display() - ); - } -} diff --git a/sdks/rust/runner-protocol/src/versioned.rs b/sdks/rust/runner-protocol/src/versioned.rs index dca8eb7858..d4395abdc9 100644 --- a/sdks/rust/runner-protocol/src/versioned.rs +++ b/sdks/rust/runner-protocol/src/versioned.rs @@ -1,5 +1,5 @@ use anyhow::{Ok, Result, bail}; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; use crate::{PROTOCOL_VERSION, generated::v1}; diff --git a/sdks/rust/ups-protocol/Cargo.toml b/sdks/rust/ups-protocol/Cargo.toml index 17cdbee161..ec5fba6eca 100644 --- a/sdks/rust/ups-protocol/Cargo.toml +++ b/sdks/rust/ups-protocol/Cargo.toml @@ -11,11 +11,7 @@ base64.workspace = true rivet-util.workspace = true serde_bare.workspace = true serde.workspace = true -versioned-data-util.workspace = true +vbare.workspace = true [build-dependencies] -bare_gen.workspace = true -indoc.workspace = true -prettyplease.workspace = true -serde_json.workspace = true -syn.workspace = true \ No newline at end of file +vbare-compiler.workspace = true diff --git a/sdks/rust/ups-protocol/build.rs b/sdks/rust/ups-protocol/build.rs index 6c5936b1e0..0ea405c831 100644 --- a/sdks/rust/ups-protocol/build.rs +++ b/sdks/rust/ups-protocol/build.rs @@ -1,71 +1,18 @@ -use std::{env, fs, path::Path}; +use std::path::Path; -use indoc::formatdoc; - -mod rust { - use super::*; - - pub fn generate_sdk(schema_dir: &Path) { - let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = Path::new(&out_dir); - let mut all_names = Vec::new(); - - for entry in fs::read_dir(schema_dir).unwrap().flatten() { - let path = entry.path(); - - if path.is_dir() { - continue; - } - - let bare_name = path - .file_name() - .unwrap() - .to_str() - .unwrap() - .rsplit_once('.') - .unwrap() - .0; - - let content = - prettyplease::unparse(&syn::parse2(bare_gen::bare_schema(&path)).unwrap()); - fs::write(out_path.join(format!("{bare_name}_generated.rs")), content).unwrap(); - - all_names.push(bare_name.to_string()); - } - - let mut mod_content = String::new(); - mod_content.push_str("// Auto-generated module file for BARE schemas\n\n"); - - // Generate module declarations for each version - for name in all_names { - mod_content.push_str(&formatdoc!( - r#" - pub mod {name} {{ - include!(concat!(env!("OUT_DIR"), "/{name}_generated.rs")); - }} - "#, - )); - } - - let mod_file_path = out_path.join("combined_imports.rs"); - fs::write(&mod_file_path, mod_content).expect("Failed to write combined_imports.rs"); - } -} - -fn main() { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); +fn main() -> Result<(), Box> { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?; let workspace_root = Path::new(&manifest_dir) .parent() .and_then(|p| p.parent()) .and_then(|p| p.parent()) - .expect("Failed to find workspace root"); + .ok_or("Failed to find workspace root")?; let schema_dir = workspace_root .join("sdks") .join("schemas") .join("ups-protocol"); - println!("cargo:rerun-if-changed={}", schema_dir.display()); - - rust::generate_sdk(&schema_dir); + let cfg = vbare_compiler::Config::with_hashable_map(); + vbare_compiler::process_schemas_with_config(&schema_dir, &cfg) } diff --git a/sdks/rust/ups-protocol/src/versioned.rs b/sdks/rust/ups-protocol/src/versioned.rs index 4a739b2f2e..a4cb0fb07e 100644 --- a/sdks/rust/ups-protocol/src/versioned.rs +++ b/sdks/rust/ups-protocol/src/versioned.rs @@ -1,5 +1,5 @@ use anyhow::{Ok, Result, bail}; -use versioned_data_util::OwnedVersionedData; +use vbare::OwnedVersionedData; use crate::{PROTOCOL_VERSION, generated::v1};