Increment a UTF8 string by one, returning `None` if it can't be incremented. This makes it so that the returned string will always compare greater than the input string or any other string with the same prefix. This is necessary since the statistics may have been truncated: if we have a min statistic of "fo" that may have originally been "foz" or anything else with the prefix "fo". E.g. `increment
(data: &str)
| 1961 | /// E.g. `increment_utf8("foo") >= "foo"` and `increment_utf8("foo") >= "fooz"` |
| 1962 | /// In this example `increment_utf8("foo") == "fop" |
| 1963 | fn increment_utf8(data: &str) -> Option<String> { |
| 1964 | // Helper function to check if a character is valid to use |
| 1965 | fn is_valid_unicode(c: char) -> bool { |
| 1966 | let cp = c as u32; |
| 1967 | |
| 1968 | // Filter out non-characters (https://www.unicode.org/versions/corrigendum9.html) |
| 1969 | if [0xFFFE, 0xFFFF].contains(&cp) || (0xFDD0..=0xFDEF).contains(&cp) { |
| 1970 | return false; |
| 1971 | } |
| 1972 | |
| 1973 | // Filter out private use area |
| 1974 | if cp >= 0x110000 { |
| 1975 | return false; |
| 1976 | } |
| 1977 | |
| 1978 | true |
| 1979 | } |
| 1980 | |
| 1981 | // Convert string to vector of code points |
| 1982 | let mut code_points: Vec<char> = data.chars().collect(); |
| 1983 | |
| 1984 | // Work backwards through code points |
| 1985 | for idx in (0..code_points.len()).rev() { |
| 1986 | let original = code_points[idx] as u32; |
| 1987 | |
| 1988 | // Try incrementing the code point |
| 1989 | if let Some(next_char) = char::from_u32(original + 1) |
| 1990 | && is_valid_unicode(next_char) |
| 1991 | { |
| 1992 | code_points[idx] = next_char; |
| 1993 | // truncate the string to the current index |
| 1994 | code_points.truncate(idx + 1); |
| 1995 | return Some(code_points.into_iter().collect()); |
| 1996 | } |
| 1997 | } |
| 1998 | |
| 1999 | None |
| 2000 | } |
| 2001 | |
| 2002 | /// Wrap the statistics expression in a check that skips the expression if the column is all nulls. |
| 2003 | /// |
no test coverage detected
searching dependent graphs…