rustdx-complete 0.6.3

功能完整的 A 股数据获取库,完全对标 pytdx
# 修复记录

本文档记录了对 rustdx 项目的所有修复和改进。

## 📅 修复日期:2025-12-30

## 🔧 主要修复

### 1. 中文编码显示问题

**问题描述:**
- 股票名称、指数名称等中文数据显示为乱码(`�������`- 根因:通达信服务器返回 GBK 编码数据,但代码错误地使用 UTF-8 解码

**修复内容:**
- `src/tcp/helper.rs` 中添加 GBK 解码辅助函数:
  ```rust
  pub fn gbk_to_string(bytes: &[u8]) -> String {
      encoding_rs::GBK.decode(bytes).0.to_string()
  }

  pub fn gbk_to_string_trim_null(bytes: &[u8]) -> String {
      let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
      gbk_to_string(&bytes[..end])
  }
  ```

- 更新 `src/tcp/stock/security_list.rs` 使用 GBK 解码:
  ```rust
  // 修复前:
  let name = String::from_utf8_lossy(name_bytes)
      .trim_end_matches('\x00')
      .to_string();

  // 修复后:
  let name = crate::tcp::helper::gbk_to_string_trim_null(name_bytes);
  ```

**验证结果:**
- ✅ "主板A股" 正确显示
- ✅ "上证指数" 正确显示
- ✅ 所有中文数据正确显示

### 2. 服务器连接问题

**问题描述:**
- 默认服务器 `39.100.68.59:7709` 不能返回数据(返回 0 字节)
- 所有示例程序都无法获取到任何数据

**修复内容:**
- `src/tcp/ip.rs` 中调整服务器 IP 顺序
- 将可用的服务器 `115.238.56.198:7709` 移到第一位
- 将不可用的服务器 `39.100.68.59:7709` 移到后面

**验证结果:**
- ✅ 股票行情:成功获取 3 只股票数据
- ✅ 指数行情:成功获取 2 个指数数据
- ✅ 财务信息:成功获取完整财务数据
- ✅ 股票列表:成功获取 1000 只股票

### 3. 内存安全问题

**问题描述:**
- 代码中大量使用 `unsafe { slice.get_unchecked() }` 操作
- 当数据长度不足时会触发 panic
- 违反了 Rust 的安全原则

**修复内容:**

**a) `src/bytes_helper.rs` - 移除所有 unsafe 代码:**
```rust
// 修复前:
pub fn into_arr4(slice: &[u8], pos: usize) -> [u8; 4] {
    let mut arr = [0; 4];
    arr.copy_from_slice(unsafe { slice.get_unchecked(pos..pos + 4) });
    arr
}

// 修复后:
pub fn into_arr4(slice: &[u8], pos: usize) -> [u8; 4] {
    let mut arr = [0; 4];
    if pos + 4 <= slice.len() {
        arr.copy_from_slice(&slice[pos..pos + 4]);
    }
    arr
}
```

**b) `src/tcp/stock/security_list.rs` - 添加数据长度验证:**
```rust
fn parse(&mut self, v: Vec<u8>) {
    // 检查最小长度
    if v.len() < 2 {
        eprintln!("⚠️  股票列表数据长度不足: {} 字节", v.len());
        self.response = v;
        self.data = Vec::new();
        return;
    }

    // 检查数据完整性
    let expected_len = 2 + (num_stocks as usize) * 29;
    if v.len() < expected_len {
        eprintln!("⚠️  股票列表数据长度不足");
        // 只解析能完整解析的股票数量
        let available_stocks = (v.len() - 2) / 29;
        // ... 优雅降级处理
    }
}
```

**c) `src/tcp/stock/finance_info.rs` - 添加数据长度验证:**
```rust
fn parse(&mut self, v: Vec<u8>) {
    // 检查最小长度:137 字节
    if v.len() < 137 {
        eprintln!("⚠️  财务信息数据长度不足");
        self.response = v;
        self.data = Vec::new();
        return;
    }
    // ...
}
```

**d) `src/tcp/stock/quotes.rs` - 添加数据长度验证:**
```rust
fn parse(&mut self, v: Vec<u8>) {
    // 检查最小长度
    if v.len() < 4 {
        eprintln!("⚠️  行情数据长度不足");
        self.response = v;
        self.data = Vec::new();
        return;
    }

    for i in 0..num_stocks {
        // 检查是否还有足够的数据
        if pos + 100 > v.len() {
            eprintln!("⚠️  行情数据不完整,只解析了 {}/{} 只股票", i, num_stocks);
            break;
        }
        // ...
    }
}
```

**验证结果:**
- ✅ 不再出现 panic
- ✅ 数据不完整时优雅降级
- ✅ 提供清晰的错误提示

### 4. 示例代码修复

**问题描述:**
- 示例代码使用了错误的 crate 名称 `rustdx`
- 实际的 crate 名称是 `rustdx_complete`

**修复内容:**

**a) `examples/test_tcp_connection.rs`:**
```rust
// 修复前:
use rustdx_complete::tcp::{Tcp, Tdx};
println!("   服务器: {}", rustdx::tcp::ip::STOCK_IP[0]);
let mut list = rustdx::tcp::SecurityList::new(0, 0);

// 修复后:
use rustdx_complete::tcp::{Tcp, Tdx};
use rustdx_complete::tcp::ip::STOCK_IP;
use rustdx_complete::tcp::stock::SecurityList;
println!("   服务器: {}", STOCK_IP[0]);
let mut list = SecurityList::new(0, 0);
```

**b) README.md 文档更新:**
- 更新所有代码示例使用 `rustdx_complete`
- 添加最新更新日志部分
- 更新项目链接指向正确的 crate

**验证结果:**
- ✅ 所有 10 个示例程序编译通过
- ✅ 所有示例程序运行正常
- ✅ 文档中的代码示例可直接使用

## 📊 修复统计

- **修复文件数量:** 7 个
  - `src/bytes_helper.rs` - 移除 unsafe 代码
  - `src/tcp/helper.rs` - 添加 GBK 解码
  - `src/tcp/ip.rs` - 调整服务器顺序
  - `src/tcp/stock/security_list.rs` - 添加边界检查和 GBK 解码
  - `src/tcp/stock/finance_info.rs` - 添加边界检查
  - `src/tcp/stock/quotes.rs` - 添加边界检查
  - `examples/test_tcp_connection.rs` - 修正导入
  - `README.md` - 更新文档

- **修复代码行数:** 约 150 行
- **添加新功能:** GBK 解码辅助函数
- **安全问题:** 修复所有 unsafe 代码导致的 panic 风险

## ✅ 测试验证

所有示例程序测试结果:

1. `test_tcp_connection` - TCP 连接测试
2.`test_security_quotes` - 股票行情查询
3.`test_index_quotes` - 指数行情查询
4.`test_finance_info` - 财务信息查询
5.`test_minute_time` - 分时数据查询
6.`test_transaction` - 逐笔成交查询
7.`test_security_list` - 股票列表查询
8.`test_chinese_encoding` - 中文编码测试(新增)

## 🎯 影响范围

**用户影响:**
- 所有使用中文显示的功能现在都能正确工作
- 程序不再因数据不完整而崩溃
- 示例代码可以直接运行

**API 兼容性:**
- ✅ 完全向后兼容
- ✅ 不需要修改用户代码
- ✅ 所有现有代码正常工作

## 📝 相关资源

- 项目仓库:https://github.com/jackluo2012/rustdx
- crates.io:https://crates.io/crates/rustdx-complete
- docs.rs:https://docs.rs/rustdx-complete

## 🙏 致谢

感谢原项目作者 [zjp-CN](https://github.com/zjp-CN) 创建了这个优秀的库。