pub struct RollSpec {
pub count: u32,
pub sides: u32,
pub keep: Option<Keep>,
}Expand description
A specification for rolling one or more dice.
This struct defines how many dice to roll, how many sides each die has, and optionally which dice to keep (for advantage/disadvantage mechanics).
§Fields
count: The number of dice to rollsides: The number of sides on each diekeep: Optional keep modifier (keep highest N or lowest N)
§Examples
§Basic dice roll
use dice_parser::RollSpec;
// Roll 2 six-sided dice
let spec = RollSpec::new(2, 6, None);§Keep highest (advantage)
use dice_parser::{RollSpec, Keep};
// Roll 4d6, keep highest 3 (common for D&D ability scores)
let spec = RollSpec::new(4, 6, Some(Keep::Highest(3)));§Keep lowest (disadvantage)
use dice_parser::{RollSpec, Keep};
// Roll 2d20, keep lowest 1 (disadvantage in D&D)
let spec = RollSpec::new(2, 20, Some(Keep::Lowest(1)));Fields§
§count: u32The number of dice to roll.
sides: u32The number of sides on each die.
keep: Option<Keep>Optional modifier to keep only highest or lowest N dice.
Implementations§
Source§impl RollSpec
impl RollSpec
Sourcepub fn new(count: u32, sides: u32, keep: Option<Keep>) -> Self
pub fn new(count: u32, sides: u32, keep: Option<Keep>) -> Self
Create a new roll specification.
§Parameters
count: The number of dice to rollsides: The number of sides on each diekeep: Optional keep modifier
§Examples
use dice_parser::{RollSpec, Keep};
// Simple 2d6 roll
let spec = RollSpec::new(2, 6, None);
// 4d6 keep highest 3
let spec = RollSpec::new(4, 6, Some(Keep::Highest(3)));Examples found in repository?
examples/error_handling.rs (line 35)
5fn main() {
6 println!("=== Error Handling Examples ===\n");
7
8 // Parse error - invalid syntax
9 println!("1. Parse error (missing sides):");
10 match DiceExpr::parse("2d") {
11 Ok(_) => println!(" Unexpectedly succeeded!"),
12 Err(e) => println!(" Error: {}", e),
13 }
14 println!();
15
16 // Syntax error - negative dice count
17 println!("2. Syntax error (negative dice count):");
18 match DiceExpr::parse("-2d6") {
19 Ok(_) => println!(" Unexpectedly succeeded!"),
20 Err(e) => println!(" Error: {}", e),
21 }
22 println!();
23
24 // Trailing input error
25 println!("3. Trailing input error:");
26 match DiceExpr::parse("2d6 extra") {
27 Ok(_) => println!(" Unexpectedly succeeded!"),
28 Err(e) => println!(" Error: {}", e),
29 }
30 println!();
31
32 // Invalid spec error (keep more than rolled)
33 println!("4. Invalid roll specification:");
34 use dice_parser::{RollSpec, Keep};
35 let spec = RollSpec::new(2, 6, Some(Keep::Highest(5))); // Try to keep 5 dice when only rolling 2
36 let expr = DiceExpr::Roll(spec);
37 match expr.roll() {
38 Ok(_) => println!(" Unexpectedly succeeded!"),
39 Err(e) => println!(" Error: {}", e),
40 }
41 println!();
42
43 // Pattern matching on error types
44 println!("5. Pattern matching on DiceError:");
45 let result = DiceExpr::parse("abc");
46 match result {
47 Ok(_) => println!(" Unexpectedly succeeded!"),
48 Err(DiceError::ParseError { kind, input, start, stop: _ }) => {
49 println!(" Parse error at position {}: {:?}", start, kind);
50 println!(" Input: {}", input);
51 }
52 Err(e) => println!(" Other error: {}", e),
53 }
54}More examples
examples/basic_usage.rs (line 16)
5fn main() {
6 println!("=== Basic Parsing and Rolling ===");
7 let expr = DiceExpr::parse("2d6+3").unwrap();
8 let result = expr.roll().unwrap();
9 println!("Expression: 2d6+3");
10 println!("Total: {}", result.total);
11 println!("Rolls: {:?}", result.rolls);
12 println!("Modifier: {}", result.modifier);
13 println!();
14
15 println!("=== Manual Construction ===");
16 let roll_spec = RollSpec::new(4, 6, Some(Keep::Highest(3)));
17 let expr = DiceExpr::Roll(roll_spec);
18 let result = expr.roll().unwrap();
19 println!("Expression: 4d6 keep highest 3");
20 println!("Total: {}", result.total);
21 println!("All rolls: {:?}", result.rolls);
22 println!();
23
24 println!("=== Complex Expression ===");
25 let d2d6 = DiceExpr::Roll(RollSpec::new(2, 6, None));
26 let d1d4 = DiceExpr::Roll(RollSpec::new(1, 4, None));
27 let modifier = DiceExpr::Literal(2);
28 let sum = DiceExpr::Sum(Box::new(d2d6), Box::new(d1d4));
29 let expr = DiceExpr::Difference(Box::new(sum), Box::new(modifier));
30 let result = expr.roll().unwrap();
31 println!("Expression: (2d6 + 1d4) - 2");
32 println!("Total: {}", result.total);
33 println!();
34
35 println!("=== D&D 5e Advantage ===");
36 let advantage = DiceExpr::Roll(RollSpec::new(2, 20, Some(Keep::Highest(1))));
37 let result = advantage.roll().unwrap();
38 println!("Expression: 2d20 keep highest 1 (advantage)");
39 println!("Rolls: {:?}", result.rolls);
40 println!("Result: {}", result.total);
41 println!();
42
43 println!("=== D&D 5e Disadvantage ===");
44 let disadvantage = DiceExpr::Roll(RollSpec::new(2, 20, Some(Keep::Lowest(1))));
45 let result = disadvantage.roll().unwrap();
46 println!("Expression: 2d20 keep lowest 1 (disadvantage)");
47 println!("Rolls: {:?}", result.rolls);
48 println!("Result: {}", result.total);
49 println!();
50
51 println!("=== Character Ability Scores ===");
52 println!("Rolling 4d6 drop lowest for 6 abilities:");
53 let ability_roll = DiceExpr::Roll(RollSpec::new(4, 6, Some(Keep::Highest(3))));
54 for i in 0..6 {
55 let result = ability_roll.roll().unwrap();
56 println!(" Ability {}: {} (rolls: {:?})", i + 1, result.total, result.rolls);
57 }
58}examples/complete_api.rs (line 24)
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}Trait Implementations§
Auto Trait Implementations§
impl Freeze for RollSpec
impl RefUnwindSafe for RollSpec
impl Send for RollSpec
impl Sync for RollSpec
impl Unpin for RollSpec
impl UnwindSafe for RollSpec
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more