generic_pagination_example/
generic_pagination_example.rs

1use tushare_api::{TushareClient, Api, request, TushareEntityList};
2use tushare_api::DeriveFromTushareData;
3
4#[derive(Debug, Clone, DeriveFromTushareData)]
5pub struct Stock {
6    pub ts_code: String,
7    pub name: String,
8    pub area: Option<String>,
9}
10
11#[tokio::main]
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create a mock TushareResponse to test the new generic pagination container
14    use tushare_api::{TushareResponse, TushareData};
15    use serde_json::json;
16    
17    let mock_response = TushareResponse {
18        request_id: "test123".to_string(),
19        code: 0,
20        msg: None,
21        data: Some(TushareData {
22            fields: vec!["ts_code".to_string(), "name".to_string(), "area".to_string()],
23            items: vec![
24                vec![json!("000001.SZ"), json!("平安银行"), json!("深圳")],
25                vec![json!("000002.SZ"), json!("万科A"), json!("深圳")],
26                vec![json!("600000.SH"), json!("浦发银行"), json!("上海")],
27            ],
28            has_more: true,
29            count: 4500,
30        }),
31    };
32    
33    // Test the new TushareEntityList conversion
34    let stocks: TushareEntityList<Stock> = TushareEntityList::try_from(mock_response)?;
35    
36    println!("=== New Generic Pagination Container Demo ===");
37    println!("Current page: {} stocks", stocks.len());
38    println!("Total available: {} stocks", stocks.count());
39    println!("Has more pages: {}", stocks.has_more());
40    println!();
41    
42    println!("Stocks in current page:");
43    for (i, stock) in stocks.iter().enumerate() {
44        println!("  {}: {} - {} ({})", 
45                 i + 1,
46                 stock.ts_code, 
47                 stock.name, 
48                 stock.area.as_deref().unwrap_or("Unknown"));
49    }
50    println!();
51    
52    // Test direct iteration
53    println!("Direct iteration:");
54    for stock in &stocks {
55        println!("  {}: {}", stock.ts_code, stock.name);
56    }
57    println!();
58    
59    // Test accessing items directly
60    let first_stock = &stocks.items()[0];
61    println!("First stock via items(): {} - {}", first_stock.ts_code, first_stock.name);
62    
63    // Test Deref functionality (accessing Vec<T> methods directly)
64    println!("Is empty: {}", stocks.is_empty());
65    println!("Length via deref: {}", stocks.len());
66    
67    // Test conversion to Vec
68    let items_vec = stocks.clone().into_items();
69    println!("Converted to Vec<Stock> with {} items", items_vec.len());
70    
71    println!("\n=== API Usage Comparison ===");
72    
73    // Old way (would be):
74    // let stocks: StockList = client.call_api_as<StockList>(request).await?;
75    println!("❌ Old way: let stocks: StockList = client.call_api_as<StockList>(request).await?;");
76    println!("   Problem: Need to remember StockList type name, not clear what's inside");
77    
78    // New way:
79    // let stocks: TushareEntityList<Stock> = client.call_api_as<Stock>(request).await?;
80    println!("✅ New way: let stocks: TushareEntityList<Stock> = client.call_api_as<Stock>(request).await?;");
81    println!("   Benefit: Clear, intuitive, shows exactly what entity type is contained");
82    
83    Ok(())
84}