Skip to content

Commit

Permalink
templater: extract fallible i64->isize conversion to helper function
Browse files Browse the repository at this point in the history
  • Loading branch information
yuja committed Feb 29, 2024
1 parent e8f01ce commit bba376a
Showing 1 changed file with 16 additions and 5 deletions.
21 changes: 16 additions & 5 deletions cli/src/template_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,8 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a>>() -> TemplateBuildMethodF
);
map.insert("substr", |language, build_ctx, self_property, function| {
let [start_idx, end_idx] = template_parser::expect_exact_arguments(function)?;
let start_idx_property = expect_integer_expression(language, build_ctx, start_idx)?;
let end_idx_property = expect_integer_expression(language, build_ctx, end_idx)?;
let start_idx_property = expect_isize_expression(language, build_ctx, start_idx)?;
let end_idx_property = expect_isize_expression(language, build_ctx, end_idx)?;
let out_property = TemplateFunction::new(
(self_property, start_idx_property, end_idx_property),
|(s, start_idx, end_idx)| Ok(string_substr(&s, start_idx, end_idx)),
Expand Down Expand Up @@ -595,13 +595,13 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a>>() -> TemplateBuildMethodF
map
}

fn string_substr(s: &str, start_idx: i64, end_idx: i64) -> String {
fn string_substr(s: &str, start_idx: isize, end_idx: isize) -> String {
// TODO: If we add .len() method, we'll expose bytes-based and char-based APIs.
// Having different index units would be confusing, so we might want to change
// .substr() to bytes-based and round up/down towards char or grapheme-cluster
// boundary.
let to_idx = |i: i64| -> usize {
let magnitude = usize::try_from(i.unsigned_abs()).unwrap_or(usize::MAX);
let to_idx = |i: isize| -> usize {
let magnitude = i.unsigned_abs();
if i < 0 {
s.chars().count().saturating_sub(magnitude)
} else {
Expand Down Expand Up @@ -1032,6 +1032,17 @@ pub fn expect_integer_expression<'a, L: TemplateLanguage<'a>>(
.ok_or_else(|| TemplateParseError::expected_type("Integer", node.span))
}

/// If the given expression `node` is of `Integer` type, converts it to `isize`.
pub fn expect_isize_expression<'a, L: TemplateLanguage<'a>>(
language: &L,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<L::Context, Output = isize> + 'a>> {
let i64_property = expect_integer_expression(language, build_ctx, node)?;
let isize_property = TemplateFunction::new(i64_property, |v| Ok(isize::try_from(v)?));
Ok(Box::new(isize_property))
}

/// If the given expression `node` is of `Integer` type, converts it to `usize`.
pub fn expect_usize_expression<'a, L: TemplateLanguage<'a>>(
language: &L,
Expand Down

0 comments on commit bba376a

Please sign in to comment.