mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-09 06:18:46 +08:00
Add PuCaCrypt
Fix CaseInsensitive cause BTreeMap not works correctly
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use serde::Deserialize;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -57,20 +58,97 @@ impl DerefMut for CaseInsensitiveString {
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for CaseInsensitiveString {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<String> for CaseInsensitiveString {
|
||||
fn borrow(&self) -> &String {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CaseInsensitiveString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for CaseInsensitiveString {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.to_ascii_lowercase().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<CaseInsensitiveStr> for CaseInsensitiveString {
|
||||
fn borrow(&self) -> &CaseInsensitiveStr {
|
||||
CaseInsensitiveStr::from_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct CaseInsensitiveStr(str);
|
||||
|
||||
impl CaseInsensitiveStr {
|
||||
pub fn from_str(s: &str) -> &Self {
|
||||
// SAFETY: CaseInsensitiveStr has the same memory layout as str, so this transmute is safe.
|
||||
unsafe { &*(s as *const str as *const Self) }
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CaseInsensitiveStr {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.eq_ignore_ascii_case(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for CaseInsensitiveStr {}
|
||||
|
||||
impl PartialOrd for CaseInsensitiveStr {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for CaseInsensitiveStr {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0
|
||||
.to_ascii_lowercase()
|
||||
.cmp(&other.0.to_ascii_lowercase())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CaseInsensitiveStr {
|
||||
type Target = str;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CaseInsensitiveStr {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for CaseInsensitiveStr {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.to_ascii_lowercase().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_btree_map() {
|
||||
let mut map = std::collections::BTreeMap::new();
|
||||
map.insert(CaseInsensitiveString("hella".to_string()), 0);
|
||||
map.insert(CaseInsensitiveString("Hello".to_string()), 1);
|
||||
map.insert(CaseInsensitiveString("world".to_string()), 2);
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("hello")), Some(&1));
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("WORLD")), Some(&2));
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("hella")), Some(&0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_map() {
|
||||
let mut map = std::collections::HashMap::new();
|
||||
map.insert(CaseInsensitiveString("hells".to_string()), 0);
|
||||
map.insert(CaseInsensitiveString("Hello".to_string()), 1);
|
||||
map.insert(CaseInsensitiveString("world".to_string()), 2);
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("hello")), Some(&1));
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("WORLD")), Some(&2));
|
||||
assert_eq!(map.get(CaseInsensitiveStr::from_str("hells")), Some(&0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user