410 lines
9.7 KiB
JavaScript
410 lines
9.7 KiB
JavaScript
const protobuf = require('protobufjs');
|
|
const parseArgs = require('minimist');
|
|
const fs = require('fs');
|
|
const assert = require('assert');
|
|
|
|
class PBTools {
|
|
|
|
constructor() {
|
|
this.csMsgIdPb = null;
|
|
this.csProtoPb = null;
|
|
this.ssMsgIdPb = null;
|
|
this.ssProtoPb = null;
|
|
this.mtPb = null;
|
|
this.protoDir = './proto/';
|
|
}
|
|
|
|
async init() {
|
|
{
|
|
this.csProtoPb = await (new protobuf.Root()).load(
|
|
this.protoDir + 'cs_proto.proto',
|
|
{
|
|
'keepCase': true
|
|
}
|
|
);
|
|
}
|
|
{
|
|
this.csMsgIdPb = await (new protobuf.Root()).load(
|
|
this.protoDir + 'cs_msgid.proto',
|
|
{
|
|
'keepCase': true
|
|
}
|
|
);
|
|
this.csCmMsgId = this.csMsgIdPb.lookup('CMMessageId_e');
|
|
this.csSmMsgId = this.csMsgIdPb.lookup('SMMessageId_e');
|
|
}
|
|
/*
|
|
{
|
|
this.ssProtoPb = await (new protobuf.Root()).load(
|
|
this.protoDir + 'ss_proto.proto',
|
|
{
|
|
'keepCase': true
|
|
}
|
|
);
|
|
}
|
|
{
|
|
this.ssMsgIdPb = await (new protobuf.Root()).load(
|
|
this.protoDir + 'ss_msgid.proto',
|
|
{
|
|
'keepCase': true
|
|
}
|
|
);
|
|
this.ssSSmMsgId = this.ssMsgIdPb.lookup('SSMMessageId_e');
|
|
}*/
|
|
{
|
|
this.mtPb = await (new protobuf.Root()).load(
|
|
this.protoDir + 'mt.proto',
|
|
{
|
|
'keepCase': true
|
|
}
|
|
);
|
|
}
|
|
await this.genCsAutoGen();
|
|
await this.genMtbAutoGen();
|
|
//await this.genSsAutoGen();
|
|
}
|
|
|
|
async genCsAutoGen() {
|
|
let data =
|
|
`use std::rc::{Rc, Weak};
|
|
use std::cell::RefCell;
|
|
use crate::cs::cs_proto as cs;
|
|
use crate::cs::cs_msgid as cs_msgid;
|
|
|
|
pub struct Handler {
|
|
msg_id: i32,
|
|
handler_id: i32,
|
|
cb: Box::<dyn FnMut (&f9::MsgHdr, &dyn MsgHandler)>,
|
|
}
|
|
|
|
static mut HANDLERS: Vec<Option<Handler>> = Vec::new();
|
|
|
|
pub fn get_net_msg_handler(msg_id: u16) -> &'static Option<Handler> {
|
|
unsafe {
|
|
if (msg_id as usize) < HANDLERS.len() {
|
|
return &HANDLERS[msg_id as usize];
|
|
} else {
|
|
return &None;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn reg_handler_id(msg_id: u16, handler_id: i32){
|
|
unsafe {
|
|
if (msg_id as usize) < HANDLERS.len() {
|
|
match &mut HANDLERS[msg_id as usize] {
|
|
Some(v) => {
|
|
v.handler_id = handler_id;
|
|
}
|
|
None => {
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
func DispatchMsg(handler *CsNetMsgHandler, hdr *f5.MsgHdr, msgHandler MsgHandler) {
|
|
handler.Cb(hdr, msgHandler)
|
|
}
|
|
|
|
func ParsePb(msgId uint16, data []byte) interface{} {
|
|
handler := handlers[msgId]
|
|
if handler == nil {
|
|
return nil
|
|
}
|
|
return handler.ParseCb(data)
|
|
}*/
|
|
`;
|
|
data += `
|
|
pub trait MsgHandler {`;
|
|
this.csProtoPb.nested.cs.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'C' &&
|
|
item.name[1] == 'M') {
|
|
const finalyName = this.converLowCaseName(item.name);
|
|
data += `
|
|
|
|
fn ${finalyName}(&self, _: &f9::MsgHdr, _: Rc::<RefCell::<cs::${item.name}>>) {
|
|
panic!("not implement");
|
|
}
|
|
`;
|
|
}
|
|
});
|
|
data += `
|
|
}
|
|
`;
|
|
data += `
|
|
pub fn registe_handlers() {
|
|
unsafe {
|
|
HANDLERS.reserve(2000);
|
|
for i in 0..1999 {
|
|
HANDLERS.push(None);
|
|
}
|
|
`;
|
|
this.csProtoPb.nested.cs.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'C' &&
|
|
item.name[1] == 'M') {
|
|
data += `
|
|
HANDLERS[cs_msgid::CMMessageId_e::_${item.name} as usize] = Some(
|
|
Handler {
|
|
msg_id: cs_msgid::CMMessageId_e::_${item.name} as i32,
|
|
handler_id: 0,
|
|
cb: Box::new(|_: &f9::MsgHdr, _: &dyn MsgHandler| {
|
|
}),
|
|
});
|
|
`;
|
|
}
|
|
});
|
|
data += `
|
|
}
|
|
}`;
|
|
fs.writeFileSync('./src/cs/cs_auto_gen.rs', data);
|
|
}
|
|
|
|
async genSsAutoGen() {
|
|
let data = `package ss
|
|
|
|
import (
|
|
"f5"
|
|
proto "github.com/golang/protobuf/proto"
|
|
)
|
|
|
|
type SsNetMsgHandler f5.NetMsgHandler[MsgHandler];
|
|
|
|
type MsgHandlerImpl struct {
|
|
}
|
|
|
|
var handlers [2000]*SsNetMsgHandler
|
|
|
|
func GetNetMsgHandler(msgId uint16) *SsNetMsgHandler {
|
|
handler := handlers[msgId]
|
|
return handler
|
|
}
|
|
|
|
func DispatchMsg(handler *SsNetMsgHandler, hdr *f5.MsgHdr, msgHandler MsgHandler) {
|
|
handler.Cb(hdr, msgHandler)
|
|
}
|
|
|
|
func RegHandlerId(msgId int, handlerId int) {
|
|
handler := handlers[msgId]
|
|
handler.HandlerId = handlerId
|
|
}
|
|
|
|
func ParsePb(msgId uint16, data []byte) interface{} {
|
|
handler := handlers[msgId]
|
|
if handler == nil {
|
|
return nil
|
|
}
|
|
return handler.ParseCb(data)
|
|
}
|
|
`;
|
|
data += `
|
|
type MsgHandler interface {`;
|
|
this.ssProtoPb.nested.ss.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'S' &&
|
|
item.name[1] == 'S') {
|
|
data += `
|
|
${item.name}(*f5.MsgHdr, *${item.name})`;
|
|
}
|
|
});
|
|
data += `
|
|
}
|
|
`;
|
|
this.ssProtoPb.nested.ss.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'S' &&
|
|
item.name[1] == 'S') {
|
|
data += `
|
|
func (this *MsgHandlerImpl) ${item.name}(hdr *f5.MsgHdr, msg *${item.name}) {
|
|
}
|
|
`;
|
|
}
|
|
});
|
|
this.ssProtoPb.nested.ss.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'S' &&
|
|
item.name[1] == 'S') {
|
|
data += `
|
|
func (this *${item.name}) GetNetMsgId() uint16 {
|
|
return uint16(SSMessageIdE__${item.name})
|
|
}
|
|
`;
|
|
} else if (item.name[0] == 'S' &&
|
|
item.name[1] == 'M') {
|
|
data += `
|
|
func (this *${item.name}) GetNetMsgId() uint16 {
|
|
return uint16(SMMessageIdE__${item.name})
|
|
}
|
|
`;
|
|
}
|
|
});
|
|
data += `
|
|
func init() {
|
|
`;
|
|
this.ssProtoPb.nested.ss.nestedArray.forEach(
|
|
(item) => {
|
|
if (item.name[0] == 'S' &&
|
|
item.name[1] == 'S') {
|
|
data += `
|
|
handlers[int(SSMessageIdE__${item.name})] = &SsNetMsgHandler{
|
|
MsgId: int(SSMessageIdE__${item.name}),
|
|
ParseCb: func (data []byte) interface{} {
|
|
msg := &${item.name}{}
|
|
proto.Unmarshal(data, msg)
|
|
return msg
|
|
},
|
|
Cb: func (hdr *f5.MsgHdr, handler MsgHandler) {
|
|
handler.${item.name}(hdr, hdr.Msg.(*${item.name}))
|
|
},
|
|
}
|
|
`;
|
|
}
|
|
});
|
|
data += `
|
|
}`;
|
|
fs.writeFileSync('./ss/ss.auto_gen.go', data);
|
|
}
|
|
|
|
async genMtbAutoGen() {
|
|
let data = `use std::rc::{Rc, Weak};
|
|
use std::cell::RefCell;
|
|
|
|
`;
|
|
this.mtPb.nested.mt.nestedArray.forEach(
|
|
(item) => {
|
|
data += `pub struct ${item.name} {\n`;
|
|
item.fieldsArray.forEach
|
|
(
|
|
(item2, index) => {
|
|
assert(item2.id <= 127);
|
|
data += ` ${item2.name}: ` + this.dumpClassField(item, item2, index) + `,\n`;
|
|
}
|
|
);
|
|
data += `}
|
|
|
|
`;
|
|
}
|
|
);
|
|
data += '';
|
|
/*
|
|
this.mtPb.nested.mt.nestedArray.forEach(
|
|
(item) => {
|
|
item.fieldsArray.forEach
|
|
(
|
|
(item2, index) => {
|
|
const newName = this.converUpperCamelCaseName(item2.name);
|
|
data += `func (this *${item.name}) Get${newName}() ` +
|
|
this.dumpClassField(item, item2, index) + ` {\n`;
|
|
data += ` return this.${item2.name}\n`;
|
|
data += `}\n\n`;
|
|
data += `func (this *${item.name}) Has${newName}() bool {\n`;
|
|
if (item2.id < 64) {
|
|
data += ` return (this._flags1_ & (uint64(1) << ${item2.id})) > 0\n`;
|
|
} else {
|
|
data += ` return (this._flags2_ & (uint64(1) << (${item2.id} - 64))) > 0\n`;
|
|
}
|
|
data += `}\n\n`;
|
|
}
|
|
);
|
|
}
|
|
);
|
|
this.mtPb.nested.mt.nestedArray.forEach(
|
|
(item) => {
|
|
data += `
|
|
func (this *${item.name}) LoadFromKv(kv map[string]interface{}) {
|
|
`;
|
|
item.fieldsArray.forEach
|
|
(
|
|
(item2, index) => {
|
|
if (item2.id < 64) {
|
|
data += ` f5.ReadMetaTableField(&this.${item2.name}, "${item2.name}", &this._flags1_, ${item2.id}, kv)\n`;
|
|
} else {
|
|
data += ` f5.ReadMetaTableField(&this.${item2.name}, "${item2.name}", &this._flags2_, ${item2.id} - 64, kv)\n`;
|
|
}
|
|
}
|
|
);
|
|
data += '}\n';
|
|
}
|
|
);*/
|
|
fs.writeFileSync('./src/mtb/mtb_auto_gen.rs', data);
|
|
}
|
|
|
|
dumpClassField(cls, field, index) {
|
|
const fieldName = field.name;
|
|
switch (field.type) {
|
|
case 'int32':
|
|
{
|
|
return `Option<i32>`;
|
|
}
|
|
break;
|
|
case 'int64':
|
|
{
|
|
return `Option<i64>`;
|
|
}
|
|
break;
|
|
case 'float':
|
|
{
|
|
return `Option<f32>`;
|
|
}
|
|
break;
|
|
case 'double':
|
|
{
|
|
return `Option<f64>`;
|
|
}
|
|
break;
|
|
case 'string':
|
|
{
|
|
return `Option<String>`;
|
|
}
|
|
break;
|
|
default:
|
|
console.log(field);
|
|
assert(false, 'error field type:' + field.type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
converUpperCamelCaseName(name) {
|
|
let newName = '';
|
|
let preIs_ = false;
|
|
for (let i = 0; i < name.length; ++i) {
|
|
if (i == 0) {
|
|
newName += name[i].toUpperCase();
|
|
preIs_ = name[i] == '_';
|
|
} else {
|
|
if (preIs_) {
|
|
if (name[i] != '_') {
|
|
newName += name[i].toUpperCase();
|
|
}
|
|
} else {
|
|
if (name[i] != '_') {
|
|
newName += name[i];
|
|
}
|
|
}
|
|
preIs_ = name[i] == '_';
|
|
}
|
|
}
|
|
return newName;
|
|
}
|
|
|
|
converLowCaseName(name) {
|
|
let newName = 'cm';
|
|
let preIs_ = false;
|
|
for (let i = 2; i < name.length; ++i) {
|
|
if (name[i].charCodeAt(0) >= 65 && name[i].charCodeAt(0) <= 90) {
|
|
newName += '_' + name[i].toLowerCase();
|
|
} else {
|
|
newName += name[i];
|
|
}
|
|
}
|
|
return newName;
|
|
}
|
|
|
|
}
|
|
|
|
(new PBTools).init();
|