Skip to content

Commit fbd73b4

Browse files
committed
fix: metadata servings scale
1 parent dd9a84c commit fbd73b4

11 files changed

Lines changed: 163 additions & 37 deletions

File tree

bindings/src/lib.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ pub fn parse_metadata(input: String, scaling_factor: f64) -> CooklangMetadata {
2424
let mut metadata = CooklangMetadata::new();
2525
let parser = cooklang::CooklangParser::canonical();
2626

27-
let (parsed, _warnings) = parser.parse(&input)
28-
.into_result()
29-
.unwrap();
27+
let (parsed, _warnings) = parser.parse(&input).into_result().unwrap();
3028

3129
let scaled = parsed.scale(scaling_factor, parser.converter());
3230

@@ -132,7 +130,7 @@ mod tests {
132130
a test @step @salt{1%mg} more text
133131
"#
134132
.to_string(),
135-
1.0
133+
1.0,
136134
);
137135

138136
assert_eq!(
@@ -209,7 +207,7 @@ source: https://google.com
209207
a test @step @salt{1%mg} more text
210208
"#
211209
.to_string(),
212-
1.0
210+
1.0,
213211
);
214212

215213
assert_eq!(
@@ -357,7 +355,7 @@ dried oregano
357355
Cook @onions{3%large} until brown
358356
"#
359357
.to_string(),
360-
1.0
358+
1.0,
361359
);
362360

363361
let first_section = recipe
@@ -416,7 +414,7 @@ add @tomatoes{400%g}
416414
simmer for 10 minutes
417415
"#
418416
.to_string(),
419-
1.0
417+
1.0,
420418
);
421419
let first_section = recipe
422420
.sections
@@ -481,7 +479,7 @@ Mix @flour{200%g} and @water{50%ml} together until smooth.
481479
Combine @cheese{100%g} and @spinach{50%g}, then season to taste.
482480
"#
483481
.to_string(),
484-
1.0
482+
1.0,
485483
);
486484

487485
let mut sections = recipe.sections.into_iter();

bindings/src/model.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use std::collections::HashMap;
22

33
use cooklang::model::Item as OriginalItem;
4-
use cooklang::quantity::{
5-
Quantity as OriginalQuantity, Value as OriginalValue
6-
};
4+
use cooklang::quantity::{Quantity as OriginalQuantity, Value as OriginalValue};
75
use cooklang::ScaledRecipe as OriginalRecipe;
86

97
#[derive(uniffi::Record, Debug)]

fuzz/fuzz_targets/fuzz_parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use libfuzzer_sys::fuzz_target;
44

5-
use cooklang::{CooklangParser, Extensions, Converter};
5+
use cooklang::{Converter, CooklangParser, Extensions};
66

77
fuzz_target!(|contents: &str| {
88
let parser = CooklangParser::new(Extensions::all(), Converter::default());

src/analysis/event_consumer.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,7 @@ impl<'i> RecipeCollector<'i, '_> {
364364
format!("Unknown config metadata key: {key_t}"),
365365
label!(key.span())
366366
)
367-
.hint(
368-
"Possible config keys are '[mode]' and '[duplicate]''",
369-
),
367+
.hint("Possible config keys are '[mode]' and '[duplicate]''"),
370368
);
371369
if self.old_style_metadata {
372370
self.content.metadata.map.insert(
@@ -1029,7 +1027,10 @@ impl<'i> RecipeCollector<'i, '_> {
10291027
}
10301028

10311029
fn value(&mut self, value: parser::QuantityValue, is_ingredient: bool) -> ScalableValue {
1032-
let parser::QuantityValue { value, scaling_lock } = value;
1030+
let parser::QuantityValue {
1031+
value,
1032+
scaling_lock,
1033+
} = value;
10331034
let has_scaling_lock = scaling_lock.is_some();
10341035
let is_text = value.is_text();
10351036

@@ -1496,13 +1497,17 @@ fn yaml_find_key_position(text: &str, key: &str) -> Option<usize> {
14961497
}
14971498

14981499
fn parse_reference(name: &str) -> Option<RecipeReference> {
1499-
if name.starts_with("./") || name.starts_with("../") || name.starts_with(".\\") || name.starts_with("..\\") {
1500+
if name.starts_with("./")
1501+
|| name.starts_with("../")
1502+
|| name.starts_with(".\\")
1503+
|| name.starts_with("..\\")
1504+
{
15001505
let path = name.replace('\\', "/");
15011506
let mut components: Vec<String> = path.split('/').map(String::from).skip(1).collect();
15021507
let file_stem = components.pop().unwrap();
15031508
Some(RecipeReference {
15041509
components,
1505-
name: file_stem.into()
1510+
name: file_stem,
15061511
})
15071512
} else {
15081513
None
@@ -1553,7 +1558,11 @@ mod tests {
15531558
assert_eq!(
15541559
parse_reference("./recipes/italian/pasta/spaghetti"),
15551560
Some(RecipeReference {
1556-
components: vec!["recipes".to_string(), "italian".to_string(), "pasta".to_string()],
1561+
components: vec![
1562+
"recipes".to_string(),
1563+
"italian".to_string(),
1564+
"pasta".to_string()
1565+
],
15571566
name: "spaghetti".into()
15581567
})
15591568
);

src/ingredient_list.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ impl IngredientList {
144144
}
145145

146146
/// Ingredient list of a recipe
147-
pub fn from_recipe(recipe: &ScaledRecipe, converter: &Converter, list_references: bool) -> Self {
147+
pub fn from_recipe(
148+
recipe: &ScaledRecipe,
149+
converter: &Converter,
150+
list_references: bool,
151+
) -> Self {
148152
let mut list = Self::new();
149153
list.add_recipe(recipe, converter, list_references);
150154
list
@@ -162,7 +166,12 @@ impl IngredientList {
162166
/// error.
163167
///
164168
/// Ingredients are listed based on their [`display_name`](crate::model::Ingredient::display_name).
165-
pub fn add_recipe(&mut self, recipe: &ScaledRecipe, converter: &Converter, list_references: bool) -> Vec<usize> {
169+
pub fn add_recipe(
170+
&mut self,
171+
recipe: &ScaledRecipe,
172+
converter: &Converter,
173+
list_references: bool,
174+
) -> Vec<usize> {
166175
let mut references = Vec::new();
167176

168177
for entry in recipe.group_ingredients(converter) {

src/parser/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub struct Quantity<'a> {
109109
#[derive(Debug, Clone, PartialEq, Serialize)]
110110
pub struct QuantityValue {
111111
pub value: Located<Value>,
112-
pub scaling_lock: Option<Span>
112+
pub scaling_lock: Option<Span>,
113113
}
114114

115115
impl QuantityValue {

src/parser/quantity.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ fn parse_regular_quantity<'i>(bp: &mut BlockParser<'_, 'i>) -> ParsedQuantity<'i
8787
}
8888

8989
fn parse_advanced_quantity<'i>(bp: &mut BlockParser<'_, 'i>) -> Option<ParsedQuantity<'i>> {
90-
if bp
91-
.tokens()
92-
.iter()
93-
.any(|t| matches!(t.kind, T![%]))
94-
{
90+
if bp.tokens().iter().any(|t| matches!(t.kind, T![%])) {
9591
return None;
9692
}
9793

@@ -138,7 +134,10 @@ fn parse_advanced_quantity<'i>(bp: &mut BlockParser<'_, 'i>) -> Option<ParsedQua
138134
Some(ParsedQuantity {
139135
quantity: Located::new(
140136
Quantity {
141-
value: QuantityValue {value, scaling_lock},
137+
value: QuantityValue {
138+
value,
139+
scaling_lock,
140+
},
142141
unit: Some(unit),
143142
},
144143
tokens_span(bp.tokens()),
@@ -152,7 +151,10 @@ fn value(bp: &mut BlockParser) -> QuantityValue {
152151
let value_tokens = bp.consume_while(|t| !matches!(t, T![%]));
153152
let value = parse_value(value_tokens, bp);
154153

155-
QuantityValue { value, scaling_lock }
154+
QuantityValue {
155+
value,
156+
scaling_lock,
157+
}
156158
}
157159

158160
fn scaling_lock(bp: &mut BlockParser) -> Option<Span> {
@@ -162,8 +164,8 @@ fn scaling_lock(bp: &mut BlockParser) -> Option<Span> {
162164
T![=] => {
163165
let tok = bp.bump_any();
164166
Some(tok.span)
165-
},
166-
_ => None
167+
}
168+
_ => None,
167169
}
168170
}
169171

@@ -329,7 +331,7 @@ fn float(tokens: &[Token], bp: &BlockParser) -> Result<f64, SourceDiag> {
329331
#[cfg(test)]
330332
mod tests {
331333
use super::*;
332-
use crate::{parser::TokenStream};
334+
use crate::parser::TokenStream;
333335
use test_case::test_case;
334336

335337
macro_rules! t {

src/scale.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ impl ScaleTarget {
2323
/// Creates a new [`ScaleTarget`].
2424
///
2525
/// - `factor` is the multiplier to scale the recipe by.
26-
/// Invalid parameters don't error here, but may do so in the
27-
/// scaling process.
26+
/// Invalid parameters don't error here, but may do so in the
27+
/// scaling process.
2828
fn new(factor: f64) -> Self {
2929
ScaleTarget { factor }
3030
}
@@ -150,8 +150,25 @@ impl ScalableRecipe {
150150
timers: timer_outcomes,
151151
};
152152

153+
// Update metadata with new servings
154+
let mut metadata = self.metadata;
155+
if let Servings(Some(servings)) = &self.data {
156+
if let Some(base_servings) = servings.first() {
157+
let new_servings = (*base_servings as f64 * factor).round() as u32;
158+
if metadata.get(crate::metadata::StdKey::Servings).is_some() {
159+
// Update existing servings value
160+
if let Some(servings_value) =
161+
metadata.get_mut(crate::metadata::StdKey::Servings)
162+
{
163+
*servings_value =
164+
serde_yaml::Value::Number(serde_yaml::Number::from(new_servings));
165+
}
166+
}
167+
}
168+
}
169+
153170
ScaledRecipe {
154-
metadata: self.metadata,
171+
metadata,
155172
sections: self.sections,
156173
ingredients,
157174
cookware,

tests/canonical.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl TestValue {
172172
Value::Number(num) => TestValue::Number(num.value()),
173173
Value::Range { .. } => panic!("unexpected range value"),
174174
Value::Text(value) => TestValue::Text(value),
175-
}
175+
},
176176
}
177177
}
178178
}

tests/canonical_cases/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! AUTO GENERATED WITH `gen_canonical_tests.py`
2-
use test_case::test_case;
32
use super::{runner, TestCase};
3+
use test_case::test_case;
44
#[test_case(r#"
55
result:
66
metadata: {}

0 commit comments

Comments
 (0)