fix string order

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2024-02-15 16:36:52 +01:00
parent 0b8dce9266
commit 3a7208f1b5
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 227 additions and 56 deletions

View file

@ -36,8 +36,9 @@ const VALUE_TRAYLING_BYTE_PREFIX: u8 = 0b1000_0000;
impl Ord for StringDataItem {
fn cmp(&self, other: &Self) -> Ordering {
self.data
.cmp(&other.data)
self.get_aosp_utf16()
.unwrap()
.cmp(&other.get_aosp_utf16().unwrap())
.then(self.utf16_size.cmp(&other.utf16_size))
}
}
@ -122,6 +123,57 @@ impl From<&str> for StringDataItem {
}
impl StringDataItem {
/// Return the utf-16 string used by google in the aosp for comparaison & other.
fn get_aosp_utf16(&self) -> Result<Vec<u32>> {
let mut utf16_string = vec![];
let mut i = 0;
while i < self.data.len() {
let one = self.data[i] as u32;
i += 1;
if one & 0x80 == 0 {
utf16_string.push(one);
continue;
}
if i >= self.data.len() {
return Err(Error::InvalidStringEncoding(
"String contains invalid caracters".into(),
));
}
let two = self.data[i] as u32;
i += 1;
if one & 0x20 == 0 {
utf16_string.push((one & 0x1f) << 6 | (two & 0x3f));
continue;
}
if i >= self.data.len() {
return Err(Error::InvalidStringEncoding(
"String contains invalid caracters".into(),
));
}
let three = self.data[i] as u32;
i += 1;
if one & 0x10 == 0 {
utf16_string.push((one & 0x0f) << 12 | (two & 0x3f) << 6 | (three & 0x3f));
continue;
}
if i >= self.data.len() {
return Err(Error::InvalidStringEncoding(
"String contains invalid caracters".into(),
));
}
let four = self.data[i] as u32;
i += 1;
let code_point =
(one & 0x0f) << 18 | (two & 0x3f) << 12 | (three & 0x3f) << 6 | (four & 0x3f);
let mut pair = ((code_point >> 10) + 0xd7c0) & 0xffff;
pair |= ((code_point & 0x03ff) + 0xdc00) << 16;
utf16_string.push(pair);
}
Ok(utf16_string)
}
fn get_string(&self) -> Result<String> {
let mut string = String::new();
let mut i = 0;
@ -481,4 +533,25 @@ mod test {
assert_eq!(encoded, expected.as_str().into());
}
}
/// Apparently I don't know how to code an order relation so here it is...
#[test]
fn test_ord_relation() {
let s1: StringDataItem = "Landroidx/lifecycle/WithLifecycleStateKt$suspendWithStateAtLeastUnchecked$2$observer$1;".into();
let s2: StringDataItem = "Lcom/google/android/material/search/SearchBarAnimationHelper$$ExternalSyntheticLambda4;".into();
let s1_utf16 = s1.get_aosp_utf16().unwrap();
let s2_utf16 = s2.get_aosp_utf16().unwrap();
assert_eq!(s1_utf16 < s2_utf16, true);
assert_eq!(s1_utf16 == s2_utf16, false);
assert_eq!(s1_utf16 > s2_utf16, false);
assert_eq!(s2_utf16 < s1_utf16, false);
assert_eq!(s2_utf16 == s1_utf16, false);
assert_eq!(s2_utf16 > s1_utf16, true);
assert_eq!(s1 < s2, true);
assert_eq!(s1 == s2, false);
assert_eq!(s1 > s2, false);
assert_eq!(s2 < s1, false);
assert_eq!(s2 == s1, false);
assert_eq!(s2 > s1, true);
}
}