Skip to main content

complete_api/
complete_api.rs

1//! Comprehensive example demonstrating the complete public API.
2//!
3//! This example showcases all public types and methods available in the dice-parser crate.
4
5use dice_parser::{DiceError, DiceExpr, ExprResult, Keep, RollSpec};
6use rand::{SeedableRng, rngs::StdRng};
7
8fn main() {
9    // ========================================
10    // 1. DiceExpr - The main expression type
11    // ========================================
12
13    // 1.1 Parsing from string
14    println!("1. Parsing and expressions");
15    let parsed = DiceExpr::parse("2d6+3").unwrap();
16    println!("  1.1 Parsing e.g. \"2d6+3\" yields:");
17    println!("    {:?}", parsed);
18
19    // 1.2 DiceExpr variants - all publicly accessible
20    let literal = DiceExpr::Literal(5);
21    println!("  1.2 A literal expression \"5\": ");
22    println!("    {:?}", literal);
23
24    let roll = DiceExpr::Roll(RollSpec::new(2, 6, None));
25    println!("  1.3 A single roll expression corresponding to 2d6:",);
26    println!("    {:?}", roll);
27
28    let sum = DiceExpr::Sum(Box::new(roll.clone()), Box::new(literal.clone()));
29    println!("  1.4 A sum of two expression, e.g. \"2d6+5\":");
30    println!("    {:?}", sum);
31
32    let _diff = DiceExpr::Difference(Box::new(roll.clone()), Box::new(DiceExpr::Literal(1)));
33    println!("  1.5 A difference of two expressions, e.g. \"2d6-1\":",);
34    println!("    {:?}", _diff);
35
36    // 1.3 Rolling methods
37    println!("\n  1.6 DiceExpr::roll() - Rolling expressions");
38    let result1 = parsed.roll().unwrap();
39    println!("    An expression, 2d6+3: {}", result1.total);
40    let result2 = literal.roll().unwrap();
41    println!("    A literal 5: {}", result2.total);
42    let result3 = roll.roll().unwrap();
43    println!("    A single roll 2d6: {}", result3.total);
44    let result4 = sum.roll().unwrap();
45    println!("    A manual sum, 2d6+5: {}", result4.total);
46    let result5 = _diff.roll().unwrap();
47    println!("    A manual diff, 2d6-1: {}", result5.total);
48
49    println!("\n   1.7 DiceExpr::roll_with_rng() - Roll with custom RNG");
50    let rng = StdRng::seed_from_u64(42);
51    let result6 = DiceExpr::parse("1d20").unwrap().roll_with_rng(rng).unwrap();
52    println!("       Rolling 1d20: {}", result6.total);
53
54    // ========================================
55    // 2. RollSpec - Dice roll specification
56    // ========================================
57    println!("\n2. RollSpec Usage:");
58    println!("   Struct with public fields and constructor\n");
59
60    let spec = RollSpec::new(4, 6, Some(Keep::Highest(3)));
61    println!("   RollSpec::new(4, 6, Some(Keep::Highest(3)))");
62    println!("   - count: {}", spec.count);
63    println!("   - sides: {}", spec.sides);
64    println!("   - keep: {:?}", spec.keep);
65
66    // ========================================
67    // 3. Keep - Keep modifier enum
68    // ========================================
69    println!("\n3. Keep Usage:");
70    println!("   Enum with public variants\n");
71
72    let _keep_high = Keep::Highest(3);
73    println!("   {:?} - Keep 3 highest dice", _keep_high);
74
75    let _keep_low = Keep::Lowest(1);
76    println!("   {:?} - Keep 1 lowest die", _keep_high);
77
78    // Use in RollSpec
79    let _advantage = RollSpec::new(2, 20, Some(Keep::Highest(1)));
80    let _disadvantage = RollSpec::new(2, 20, Some(Keep::Lowest(1)));
81    println!("\n  Example with Advantage:");
82    println!(
83        "    {:?}, result: {}",
84        _advantage,
85        DiceExpr::Roll(_advantage.clone()).roll().unwrap().total
86    );
87    println!("\n  Example with Disadvantage:");
88    println!(
89        "    {:?}, result: {}",
90        _disadvantage,
91        DiceExpr::Roll(_disadvantage.clone()).roll().unwrap().total
92    );
93
94    // ========================================
95    // 4. ExprResult - Roll result
96    // ========================================
97    println!("\n4. ExprResult Usage:");
98    println!("   Struct with public fields\n");
99
100    let expr = DiceExpr::parse("2d6+3").unwrap();
101    let result: ExprResult = expr.roll().unwrap();
102
103    println!("   ExprResult from rolling 2d6+3:");
104    println!("   - total: {} (final result)", result.total);
105    println!("   - rolls: {:?} (individual dice)", result.rolls);
106    println!("   - modifier: {} (constant modifiers)", result.modifier);
107
108    // ========================================
109    // 5. DiceError - Error handling
110    // ========================================
111    println!("\n5. DiceError Usage:");
112    println!("   Enum with public variants for error handling\n");
113
114    // ParseError variant
115    if let Err(DiceError::ParseError {
116        kind,
117        input,
118        start,
119        stop: _,
120    }) = DiceExpr::parse("invalid")
121    {
122        println!("   DiceError::ParseError:");
123        println!("   - kind: {:?}", kind);
124        println!("   - input: {}", input);
125        println!("   - start: {}", start);
126    }
127
128    // SyntaxError variant
129    if let Err(DiceError::SyntaxError { expected, .. }) = DiceExpr::parse("-2d6") {
130        println!("\n   DiceError::SyntaxError:");
131        if let Some(exp) = expected {
132            println!("   - expected: {}", exp);
133        }
134    }
135
136    // TrailingInput variant
137    if let Err(DiceError::TrailingInput { pos, .. }) = DiceExpr::parse("2d6 extra") {
138        println!("\n   DiceError::TrailingInput:");
139        println!("   - pos: {}", pos);
140    }
141
142    // InvalidSpec variant
143    let bad_spec = RollSpec::new(2, 6, Some(Keep::Highest(5)));
144    if let Err(DiceError::InvalidSpec(spec, msg)) = DiceExpr::Roll(bad_spec).roll() {
145        println!("\n   DiceError::InvalidSpec:");
146        println!("   - spec: {:?}", spec);
147        println!("   - message: {}", msg);
148    }
149
150    // ========================================
151    // 6. Complete Example
152    // ========================================
153    println!("\n6. Complete Example:");
154    println!("   Building a complex expression with all features\n");
155
156    // Character creation: 6 abilities, each 4d6 keep highest 3
157    println!("   Rolling D&D ability scores (4d6 drop lowest):");
158    let ability_roll = DiceExpr::Roll(RollSpec::new(4, 6, Some(Keep::Highest(3))));
159
160    for i in 1..=6 {
161        if let Ok(result) = ability_roll.roll() {
162            println!(
163                "   Ability {}: {} (rolls: {:?})",
164                i, result.total, result.rolls
165            );
166        }
167    }
168}