🔧 chore: 初始化番茄小说 API 项目结构
新增项目基础框架,包含核心 API 实现、算法模块、HTTP 处理器等完整功能模块
This commit is contained in:
commit
6981148727
107 files changed
+12463
No files matched your search
@@ -0,0 +1,404 @@
|
||||
package algos
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ProtoFieldType 协议字段类型
|
||||
type ProtoFieldType int
|
||||
|
||||
const (
|
||||
ProtoFieldTypeVARINT ProtoFieldType = 0
|
||||
ProtoFieldTypeINT64 ProtoFieldType = 1
|
||||
ProtoFieldTypeSTRING ProtoFieldType = 2
|
||||
ProtoFieldTypeGROUPSTART ProtoFieldType = 3
|
||||
ProtoFieldTypeGROUPEND ProtoFieldType = 4
|
||||
ProtoFieldTypeINT32 ProtoFieldType = 5
|
||||
ProtoFieldTypeERROR1 ProtoFieldType = 6
|
||||
ProtoFieldTypeERROR2 ProtoFieldType = 7
|
||||
)
|
||||
|
||||
// ProtoField 协议字段
|
||||
type ProtoField struct {
|
||||
Idx int
|
||||
Type ProtoFieldType
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
// NewProtoField 创建新的协议字段
|
||||
func NewProtoField(idx int, fieldType ProtoFieldType, val interface{}) *ProtoField {
|
||||
return &ProtoField{
|
||||
Idx: idx,
|
||||
Type: fieldType,
|
||||
Val: val,
|
||||
}
|
||||
}
|
||||
|
||||
// IsAsciiStr 检查是否为ASCII字符串
|
||||
func (pf *ProtoField) IsAsciiStr() bool {
|
||||
if data, ok := pf.Val.([]byte); ok {
|
||||
for _, b := range data {
|
||||
if b < 0x20 || b > 0x7E {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ProtoReader 协议读取器
|
||||
type ProtoReader struct {
|
||||
data []byte
|
||||
pos int
|
||||
}
|
||||
|
||||
// NewProtoReader 创建新的协议读取器
|
||||
func NewProtoReader(data []byte) *ProtoReader {
|
||||
return &ProtoReader{
|
||||
data: data,
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Seek 设置位置
|
||||
func (pr *ProtoReader) Seek(pos int) {
|
||||
pr.pos = pos
|
||||
}
|
||||
|
||||
// IsRemain 检查是否还有剩余数据
|
||||
func (pr *ProtoReader) IsRemain(length int) bool {
|
||||
return pr.pos+length <= len(pr.data)
|
||||
}
|
||||
|
||||
// Read0 读取一个字节
|
||||
func (pr *ProtoReader) Read0() byte {
|
||||
if !pr.IsRemain(1) {
|
||||
panic("buffer overflow")
|
||||
}
|
||||
ret := pr.data[pr.pos]
|
||||
pr.pos++
|
||||
return ret & 0xFF
|
||||
}
|
||||
|
||||
// Read 读取指定长度的字节
|
||||
func (pr *ProtoReader) Read(length int) []byte {
|
||||
if !pr.IsRemain(length) {
|
||||
panic("buffer overflow")
|
||||
}
|
||||
ret := pr.data[pr.pos : pr.pos+length]
|
||||
pr.pos += length
|
||||
return ret
|
||||
}
|
||||
|
||||
// ReadInt32 读取32位整数
|
||||
func (pr *ProtoReader) ReadInt32() uint32 {
|
||||
bytes := pr.Read(4)
|
||||
return uint32(bytes[0]) | uint32(bytes[1])<<8 | uint32(bytes[2])<<16 | uint32(bytes[3])<<24
|
||||
}
|
||||
|
||||
// ReadInt64 读取64位整数
|
||||
func (pr *ProtoReader) ReadInt64() uint64 {
|
||||
bytes := pr.Read(8)
|
||||
return uint64(bytes[0]) | uint64(bytes[1])<<8 | uint64(bytes[2])<<16 | uint64(bytes[3])<<24 |
|
||||
uint64(bytes[4])<<32 | uint64(bytes[5])<<40 | uint64(bytes[6])<<48 | uint64(bytes[7])<<56
|
||||
}
|
||||
|
||||
// ReadVarint 读取可变长度整数
|
||||
func (pr *ProtoReader) ReadVarint() uint64 {
|
||||
vint := uint64(0)
|
||||
n := 0
|
||||
for {
|
||||
b := pr.Read0()
|
||||
vint |= uint64(b&0x7F) << (7 * n)
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
n++
|
||||
}
|
||||
return vint
|
||||
}
|
||||
|
||||
// ReadString 读取字符串
|
||||
func (pr *ProtoReader) ReadString() []byte {
|
||||
length := pr.ReadVarint()
|
||||
return pr.Read(int(length))
|
||||
}
|
||||
|
||||
// ProtoWriter 协议写入器
|
||||
type ProtoWriter struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
// NewProtoWriter 创建新的协议写入器
|
||||
func NewProtoWriter() *ProtoWriter {
|
||||
return &ProtoWriter{
|
||||
data: make([]byte, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Write0 写入一个字节
|
||||
func (pw *ProtoWriter) Write0(b byte) {
|
||||
pw.data = append(pw.data, b&0xFF)
|
||||
}
|
||||
|
||||
// Write 写入字节数组
|
||||
func (pw *ProtoWriter) Write(bytes []byte) {
|
||||
pw.data = append(pw.data, bytes...)
|
||||
}
|
||||
|
||||
// WriteInt32 写入32位整数
|
||||
func (pw *ProtoWriter) WriteInt32(val uint32) {
|
||||
bs := []byte{
|
||||
byte(val & 0xFF),
|
||||
byte((val >> 8) & 0xFF),
|
||||
byte((val >> 16) & 0xFF),
|
||||
byte((val >> 24) & 0xFF),
|
||||
}
|
||||
pw.Write(bs)
|
||||
}
|
||||
|
||||
// WriteInt64 写入64位整数
|
||||
func (pw *ProtoWriter) WriteInt64(val uint64) {
|
||||
bs := []byte{
|
||||
byte(val & 0xFF),
|
||||
byte((val >> 8) & 0xFF),
|
||||
byte((val >> 16) & 0xFF),
|
||||
byte((val >> 24) & 0xFF),
|
||||
byte((val >> 32) & 0xFF),
|
||||
byte((val >> 40) & 0xFF),
|
||||
byte((val >> 48) & 0xFF),
|
||||
byte((val >> 56) & 0xFF),
|
||||
}
|
||||
pw.Write(bs)
|
||||
}
|
||||
|
||||
// WriteVarint 写入可变长度整数
|
||||
func (pw *ProtoWriter) WriteVarint(vint uint64) {
|
||||
vint = vint & 0xFFFFFFFF
|
||||
for vint > 0x80 {
|
||||
pw.Write0(byte((vint & 0x7F) | 0x80))
|
||||
vint >>= 7
|
||||
}
|
||||
pw.Write0(byte(vint & 0x7F))
|
||||
}
|
||||
|
||||
// WriteString 写入字符串
|
||||
func (pw *ProtoWriter) WriteString(bytes []byte) {
|
||||
pw.WriteVarint(uint64(len(bytes)))
|
||||
pw.Write(bytes)
|
||||
}
|
||||
|
||||
// ToBytes 转换为字节数组
|
||||
func (pw *ProtoWriter) ToBytes() []byte {
|
||||
return pw.data
|
||||
}
|
||||
|
||||
// ProtoBuf 协议缓冲区
|
||||
type ProtoBuf struct {
|
||||
fields []*ProtoField
|
||||
}
|
||||
|
||||
// NewProtoBuf 创建新的协议缓冲区
|
||||
func NewProtoBuf(data interface{}) *ProtoBuf {
|
||||
pb := &ProtoBuf{
|
||||
fields: make([]*ProtoField, 0),
|
||||
}
|
||||
|
||||
if data != nil {
|
||||
switch v := data.(type) {
|
||||
case []byte:
|
||||
if len(v) > 0 {
|
||||
pb.parseBuf(v)
|
||||
}
|
||||
case map[int]interface{}:
|
||||
if len(v) > 0 {
|
||||
pb.parseDict(v)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported type(%T) to protobuf", data))
|
||||
}
|
||||
}
|
||||
|
||||
return pb
|
||||
}
|
||||
|
||||
// parseBuf 解析字节数组
|
||||
func (pb *ProtoBuf) parseBuf(bytes []byte) {
|
||||
reader := NewProtoReader(bytes)
|
||||
for reader.IsRemain(1) {
|
||||
key := reader.ReadVarint()
|
||||
fieldType := ProtoFieldType(key & 0x7)
|
||||
fieldIdx := int(key >> 3)
|
||||
|
||||
if fieldIdx == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
switch fieldType {
|
||||
case ProtoFieldTypeINT32:
|
||||
pb.Put(NewProtoField(fieldIdx, fieldType, reader.ReadInt32()))
|
||||
case ProtoFieldTypeINT64:
|
||||
pb.Put(NewProtoField(fieldIdx, fieldType, reader.ReadInt64()))
|
||||
case ProtoFieldTypeVARINT:
|
||||
pb.Put(NewProtoField(fieldIdx, fieldType, reader.ReadVarint()))
|
||||
case ProtoFieldTypeSTRING:
|
||||
pb.Put(NewProtoField(fieldIdx, fieldType, reader.ReadString()))
|
||||
default:
|
||||
panic(fmt.Sprintf("parse protobuf error, unexpected field type: %d", fieldType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ToBuf 转换为字节数组
|
||||
func (pb *ProtoBuf) ToBuf() []byte {
|
||||
writer := NewProtoWriter()
|
||||
for _, field := range pb.fields {
|
||||
key := uint64((field.Idx << 3) | int(field.Type&7))
|
||||
writer.WriteVarint(key)
|
||||
|
||||
switch field.Type {
|
||||
case ProtoFieldTypeINT32:
|
||||
writer.WriteInt32(field.Val.(uint32))
|
||||
case ProtoFieldTypeINT64:
|
||||
writer.WriteInt64(field.Val.(uint64))
|
||||
case ProtoFieldTypeVARINT:
|
||||
writer.WriteVarint(field.Val.(uint64))
|
||||
case ProtoFieldTypeSTRING:
|
||||
writer.WriteString(field.Val.([]byte))
|
||||
default:
|
||||
panic(fmt.Sprintf("encode to protobuf error, unexpected field type: %d", field.Type))
|
||||
}
|
||||
}
|
||||
return writer.ToBytes()
|
||||
}
|
||||
|
||||
// Get 获取字段
|
||||
func (pb *ProtoBuf) Get(idx int) *ProtoField {
|
||||
for _, field := range pb.fields {
|
||||
if field.Idx == idx {
|
||||
return field
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetList 获取字段列表
|
||||
func (pb *ProtoBuf) GetList(idx int) []*ProtoField {
|
||||
result := make([]*ProtoField, 0)
|
||||
for _, field := range pb.fields {
|
||||
if field.Idx == idx {
|
||||
result = append(result, field)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetInt 获取整数
|
||||
func (pb *ProtoBuf) GetInt(idx int) uint64 {
|
||||
pf := pb.Get(idx)
|
||||
if pf == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
switch pf.Type {
|
||||
case ProtoFieldTypeINT32:
|
||||
return uint64(pf.Val.(uint32))
|
||||
case ProtoFieldTypeINT64:
|
||||
return pf.Val.(uint64)
|
||||
case ProtoFieldTypeVARINT:
|
||||
return pf.Val.(uint64)
|
||||
default:
|
||||
panic(fmt.Sprintf("getInt(%d) -> %d", idx, pf.Type))
|
||||
}
|
||||
}
|
||||
|
||||
// GetBytes 获取字节数组
|
||||
func (pb *ProtoBuf) GetBytes(idx int) []byte {
|
||||
pf := pb.Get(idx)
|
||||
if pf == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if pf.Type == ProtoFieldTypeSTRING {
|
||||
return pf.Val.([]byte)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("getBytes(%d) -> %d", idx, pf.Type))
|
||||
}
|
||||
|
||||
// GetUTF8 获取UTF8字符串
|
||||
func (pb *ProtoBuf) GetUTF8(idx int) string {
|
||||
bs := pb.GetBytes(idx)
|
||||
if bs == nil {
|
||||
return ""
|
||||
}
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
// GetProtoBuf 获取嵌套的ProtoBuf
|
||||
func (pb *ProtoBuf) GetProtoBuf(idx int) *ProtoBuf {
|
||||
bs := pb.GetBytes(idx)
|
||||
if bs == nil {
|
||||
return nil
|
||||
}
|
||||
return NewProtoBuf(bs)
|
||||
}
|
||||
|
||||
// Put 添加字段
|
||||
func (pb *ProtoBuf) Put(field *ProtoField) {
|
||||
pb.fields = append(pb.fields, field)
|
||||
}
|
||||
|
||||
// PutInt32 添加32位整数
|
||||
func (pb *ProtoBuf) PutInt32(idx int, val uint32) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeINT32, val))
|
||||
}
|
||||
|
||||
// PutInt64 添加64位整数
|
||||
func (pb *ProtoBuf) PutInt64(idx int, val uint64) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeINT64, val))
|
||||
}
|
||||
|
||||
// PutVarint 添加可变长度整数
|
||||
func (pb *ProtoBuf) PutVarint(idx int, val uint64) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeVARINT, val))
|
||||
}
|
||||
|
||||
// PutBytes 添加字节数组
|
||||
func (pb *ProtoBuf) PutBytes(idx int, data []byte) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeSTRING, data))
|
||||
}
|
||||
|
||||
// PutUTF8 添加UTF8字符串
|
||||
func (pb *ProtoBuf) PutUTF8(idx int, data string) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeSTRING, []byte(data)))
|
||||
}
|
||||
|
||||
// PutProtoBuf 添加嵌套的ProtoBuf
|
||||
func (pb *ProtoBuf) PutProtoBuf(idx int, data *ProtoBuf) {
|
||||
pb.Put(NewProtoField(idx, ProtoFieldTypeSTRING, data.ToBuf()))
|
||||
}
|
||||
|
||||
// parseDict 解析字典
|
||||
func (pb *ProtoBuf) parseDict(data map[int]interface{}) {
|
||||
for k, v := range data {
|
||||
switch val := v.(type) {
|
||||
case int:
|
||||
pb.PutVarint(k, uint64(val))
|
||||
case uint64:
|
||||
pb.PutVarint(k, val)
|
||||
case int64:
|
||||
pb.PutVarint(k, uint64(val))
|
||||
case string:
|
||||
pb.PutUTF8(k, val)
|
||||
case []byte:
|
||||
pb.PutBytes(k, val)
|
||||
case map[int]interface{}:
|
||||
pb.PutProtoBuf(k, NewProtoBuf(val))
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported type(%T) to protobuf", v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user