MCPcopy Create free account
hub / github.com/apache/datafusion / get_true_start_end

Function get_true_start_end

datafusion/functions/src/unicode/substr.rs:170–222  ·  view source on GitHub ↗

Convert the given `start` and `count` to valid byte indices within `input` string. Input `start` and `count` are equivalent to PostgreSQL's `substr(s, start, count)`. `start` is 1-based; if `count` is not provided, returns indices to the end of the string. Input indices are character-based, and return values are byte indices. The input bounds can be outside string bounds; this function will retur

(
    input: &str,
    start: i64,
    count: Option<i64>,
    is_input_ascii_only: bool,
)

Source from the content-addressed store, hash-verified

168/// get_true_start_end('Hi🌏', -10, Some(2)) -> Ok((0, 0))
169/// ```
170pub fn get_true_start_end(
171 input: &str,
172 start: i64,
173 count: Option<i64>,
174 is_input_ascii_only: bool,
175) -> Result<(usize, usize)> {
176 if let Some(count) = count
177 && count < 0
178 {
179 return exec_err!("negative count not allowed: {count}");
180 }
181
182 // The caller-provided `start` is 1-indexed.
183 let Some(start) = start.checked_sub(1) else {
184 return exec_err!("start position overflow: {start}");
185 };
186
187 let end = match count {
188 Some(count) => start.saturating_add(count),
189 None => input.len() as i64,
190 };
191
192 let start = start.clamp(0, input.len() as i64) as usize;
193 let end = end.clamp(0, input.len() as i64) as usize;
194
195 // If input is ASCII-only, byte-based indices equal char-based indices
196 if is_input_ascii_only {
197 return Ok((start, end));
198 }
199
200 // Otherwise, calculate byte indices from char indices. We initialize both
201 // `byte_start` and `byte_end` to the string length to handle cases where
202 // the requested 'start' or 'end' positions are at or beyond the end of the
203 // string (resulting in an empty substring).
204 let mut byte_start = input.len();
205 let mut byte_end = input.len();
206
207 for (char_idx, (byte_idx, _)) in input.char_indices().enumerate() {
208 if char_idx == start {
209 byte_start = byte_idx;
210 // If no length is specified, we only need the start offset.
211 if count.is_none() {
212 break;
213 }
214 }
215 if char_idx == end {
216 byte_end = byte_idx;
217 break;
218 }
219 }
220
221 Ok((byte_start, byte_end))
222}
223
224// String characters are variable length encoded in UTF-8, `substr()` function's
225// arguments are character-based, converting them into byte-based indices

Callers 4

byte_rangeMethod · 0.85
string_view_substrFunction · 0.85
generic_string_substrFunction · 0.85

Calls 3

clampMethod · 0.80
is_noneMethod · 0.80
lenMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…