Initial Commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 4,
|
||||||
|
"rust-analyzer.check.command": "clippy",
|
||||||
|
}
|
||||||
154
Cargo.lock
generated
Normal file
154
Cargo.lock
generated
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.104"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "protobuf"
|
||||||
|
version = "3.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"protobuf-support",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "protobuf-support"
|
||||||
|
version = "3.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "protoc-gen-jsonregistry"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"protobuf",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.148"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.111"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f4a4e8e9dc5c62d159f04fcdbe07f4c3fb710415aab4754bf11505501e3251d"
|
||||||
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "protoc-gen-jsonregistry"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
protobuf = "3.7.2"
|
||||||
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
serde_json = "1.0.148"
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 amizing25
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
1
README.md
Normal file
1
README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
generate the json registry used for [DynamicProtobuf](https://github.com/ex-RushiaLover/DynamicProtobuf.Runtime)
|
||||||
114
src/generator/json_registry.rs
Normal file
114
src/generator/json_registry.rs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
use protobuf::{
|
||||||
|
Message, UnknownValueRef, descriptor::DescriptorProto, descriptor::field_descriptor_proto::Type,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
const COMMAND_ID_FIELD_NUMBER: u32 = 50_000;
|
||||||
|
const XOR_CONST_FIELD_NUMBER: u32 = 50_001;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ProtoJsonRegistry {
|
||||||
|
pub messages: HashMap<String, HashMap<String, MessageField>>,
|
||||||
|
pub command_ids: HashMap<String, u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct MessageField {
|
||||||
|
pub field_number: u32,
|
||||||
|
pub wire_type: WireType,
|
||||||
|
pub xor_const: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
|
||||||
|
pub enum WireType {
|
||||||
|
#[default]
|
||||||
|
Varint = 0,
|
||||||
|
Fixed64 = 1,
|
||||||
|
LengthDelimited = 2,
|
||||||
|
StartGroup = 3,
|
||||||
|
EndGroup = 4,
|
||||||
|
Fixed32 = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Type> for WireType {
|
||||||
|
fn from(value: Type) -> Self {
|
||||||
|
match value {
|
||||||
|
Type::TYPE_INT32
|
||||||
|
| Type::TYPE_INT64
|
||||||
|
| Type::TYPE_UINT32
|
||||||
|
| Type::TYPE_UINT64
|
||||||
|
| Type::TYPE_SINT32
|
||||||
|
| Type::TYPE_SINT64
|
||||||
|
| Type::TYPE_ENUM
|
||||||
|
| Type::TYPE_BOOL => Self::Varint,
|
||||||
|
Type::TYPE_FLOAT | Type::TYPE_SFIXED32 | Type::TYPE_FIXED32 => Self::Fixed32,
|
||||||
|
Type::TYPE_DOUBLE | Type::TYPE_FIXED64 | Type::TYPE_SFIXED64 => Self::Fixed64,
|
||||||
|
Type::TYPE_GROUP => Self::StartGroup,
|
||||||
|
Type::TYPE_STRING | Type::TYPE_MESSAGE | Type::TYPE_BYTES => Self::LengthDelimited,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate json registry from given messages
|
||||||
|
pub fn generate_json_registry(
|
||||||
|
messages: &[DescriptorProto],
|
||||||
|
package: &str,
|
||||||
|
parent_path: Option<&str>,
|
||||||
|
out: &mut ProtoJsonRegistry,
|
||||||
|
) {
|
||||||
|
for message in messages {
|
||||||
|
if message.options.map_entry() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let local_name = message.name();
|
||||||
|
|
||||||
|
let scoped_name = match parent_path {
|
||||||
|
Some(parent) => format!("{parent}.{local_name}"),
|
||||||
|
None => local_name.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let full_name = if package.is_empty() {
|
||||||
|
scoped_name.clone()
|
||||||
|
} else {
|
||||||
|
format!("{package}.{scoped_name}")
|
||||||
|
};
|
||||||
|
|
||||||
|
// iterate nested types
|
||||||
|
if !message.nested_type.is_empty() {
|
||||||
|
generate_json_registry(&message.nested_type, package, Some(&scoped_name), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect xor constants
|
||||||
|
for field in &message.field {
|
||||||
|
let xor_const_field = if let Some(xor_const_field) =
|
||||||
|
field.options.unknown_fields().get(XOR_CONST_FIELD_NUMBER)
|
||||||
|
&& let UnknownValueRef::Varint(varint) = xor_const_field
|
||||||
|
{
|
||||||
|
Some(varint as u32)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
out.messages.entry(full_name.clone()).or_default().insert(
|
||||||
|
field.name().to_string(),
|
||||||
|
MessageField {
|
||||||
|
field_number: field.number() as u32,
|
||||||
|
wire_type: field.type_().into(),
|
||||||
|
xor_const: xor_const_field,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect command ids
|
||||||
|
if let Some(command_id_field) = message
|
||||||
|
.options
|
||||||
|
.unknown_fields()
|
||||||
|
.get(COMMAND_ID_FIELD_NUMBER)
|
||||||
|
&& let UnknownValueRef::Varint(varint) = command_id_field
|
||||||
|
{
|
||||||
|
out.command_ids.insert(full_name, varint as u16);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/generator/mod.rs
Normal file
36
src/generator/mod.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use protobuf::{
|
||||||
|
Message,
|
||||||
|
plugin::{
|
||||||
|
CodeGeneratorRequest, CodeGeneratorResponse,
|
||||||
|
code_generator_response::{Feature, File},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use crate::generator::json_registry::{ProtoJsonRegistry, generate_json_registry};
|
||||||
|
|
||||||
|
mod json_registry;
|
||||||
|
|
||||||
|
pub fn generate(input: &[u8]) -> io::Result<CodeGeneratorResponse> {
|
||||||
|
let codegen_request = CodeGeneratorRequest::parse_from_bytes(input)?;
|
||||||
|
let mut codegen_response = CodeGeneratorResponse::new();
|
||||||
|
|
||||||
|
codegen_response.set_supported_features(Feature::FEATURE_PROTO3_OPTIONAL as u64);
|
||||||
|
|
||||||
|
for proto in codegen_request.proto_file {
|
||||||
|
// skips protobuf import
|
||||||
|
if proto.name().starts_with("google/protobuf") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out = ProtoJsonRegistry::default();
|
||||||
|
generate_json_registry(&proto.message_type, proto.package(), None, &mut out);
|
||||||
|
|
||||||
|
let mut json_file = File::new();
|
||||||
|
json_file.set_content(serde_json::to_string_pretty(&out).unwrap());
|
||||||
|
json_file.set_name(format!("{}.registry.json", proto.name()));
|
||||||
|
codegen_response.file.push(json_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(codegen_response)
|
||||||
|
}
|
||||||
17
src/main.rs
Normal file
17
src/main.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use protobuf::Message;
|
||||||
|
use std::io::{self, Read as _, Write};
|
||||||
|
|
||||||
|
mod generator;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
io::stdin().read_to_end(&mut buf)?;
|
||||||
|
|
||||||
|
let result = generator::generate(&buf)?;
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
result.write_to_vec(&mut buf)?;
|
||||||
|
io::stdout().write_all(&buf)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user