Repository: meilisearch/meilisearch
File: crates/milli/src/search/new/matches/mod.rs (Rust)

Code before:
                            words_positions = wp;
                            break;
                        }
                    }
                }
            }
        }

        self.matches = Some((tokens, matches));
        self
    }

    /// Returns boundaries of the words that match the query.
    pub fn matches(&mut self, array_indices: &[usize]) -> Vec<MatchBounds> {
        match &self.matches {
            None => self.compute_matches().matches(array_indices),
            Some((tokens, matches)) => matches
                .iter()
                .map(|m| MatchBounds {
                    start: tokens[m.get_first_token_pos()].byte_start,
                    length: (m.get_first_token_pos()..m.get_last_token_pos() + 1)
                        .map(|i| tokens[i].clone())
                        .flat_map(|token| token.char_map.clone().unwrap_or(vec![(1, 1); token.char_end - token.char_start] /* Some token doesn't have a char map, here we treat them as single byte chars. */))
                        .map(|(original, _)| original as usize)
                        .take(m.char_count)
                        .sum(),
                    indices: if array_indices.is_empty() {
                        None
                    } else {
                        Some(array_indices.to_owned())
                    },
                })
                .collect(),
        }
    }

    /// Returns the bounds in byte index of the crop window.
    fn crop_bounds(&self, tokens: &[Token<'_>], matches: &[Match], crop_size: usize) -> [usize; 2] {
        let (
            mut remaining_words,
            is_iterating_forward,
            before_tokens_starting_index,
            after_tokens_starting_index,
        ) = if !matches.is_empty() {
            let [matches_first, matches_last] =
                best_match_interval::find_best_match_interval(matches, crop_size);

            let matches_size =
                matches_last.get_last_word_pos() - matches_first.get_first_word_pos() + 1;

            let is_crop_size_gte_match_size = crop_size >= matches_size;

Review comment (suggestion):
We may avoid all these `clone()` and take the byte lengths of the characters when the char map is missing instead of counting 1 for each character.

```suggestion
                    length: (m.get_first_token_pos()..=m.get_last_token_pos())
                        .scan(m.char_count, |i, remaining_chars| {
                            let mut bytes = 0;
                            match &tokens[i].char_map {
                                Some(char_map) => {
                                  // iterate over the char map, retrieving the original bytes len
                                  for (original_bytes_in_char, _) in char_map {
                                    bytes += original_bytes_in_char;
                                    *remaining_chars -= 1;
                                  
                                    if remaining_chars == 0 {
                                      break;
                                    }
                                  }
                                }
                                None => {
                                  // iterate over the chars, retrieving the bytes len
                                  for c in tokens[i].lemma().chars() {
                                    bytes += c.len_utf8();
                                    *remaining_chars -= 1;
                                  
                                    if remaining_chars == 0 {
                                      break;
                                    }
                                  }
                                }
                              }
                            
                              bytes
                          })
                        .sum(),
```

But this should be put in a dedicated function to make the code cleaner.

Code after:
                        ) {
                            words_positions = wp;
                            break;
                        }
                    }
                }
            }
        }

        self.matches = Some((tokens, matches));
        self
    }

    /// Returns boundaries of the words that match the query.
    pub fn matches(&mut self, array_indices: &[usize]) -> Vec<MatchBounds> {
        match &self.matches {
            None => self.compute_matches().matches(array_indices),
            Some((tokens, matches)) => matches
                .iter()
                .map(|m| MatchBounds {
                    start: tokens[m.get_first_token_pos()].byte_start,
                    length: self.calc_byte_length(tokens, m),
                    indices: if array_indices.is_empty() {
                        None
                    } else {
                        Some(array_indices.to_owned())
                    },
                })
                .collect(),
        }
    }

    fn calc_byte_length(&self, tokens: &[Token<'t>], m: &Match) -> usize {
        (m.get_first_token_pos()..=m.get_last_token_pos())
            .flat_map(|i| match &tokens[i].char_map {
                Some(char_map) => {
                    char_map.iter().map(|(original, _)| *original as usize).collect_vec()
                }
                None => tokens[i].lemma().chars().map(|c| c.len_utf8()).collect_vec(),
            })
            .take(m.char_count)
            .sum()
    }

    /// Returns the bounds in byte index of the crop window.
    fn crop_bounds(&self, tokens: &[Token<'_>], matches: &[Match], crop_size: usize) -> [usize; 2] {
        let (
            mut remaining_words,
            is_iterating_forward,
            before_tokens_starting_index,
            after_tokens_starting_index,