1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use std::char::from_u32_unchecked; unsafe fn adjust(x: u32) -> char { from_u32_unchecked(if x >= 0xd800 { x + 0xd2800 } else { x }) } pub fn encode(x: &[u8]) -> String { let mut ret = String::new(); for x in x.chunks(5) { let ch1 = match x.len() { 1 => x[0] as u32, 2 => x[0] as u32|(x[1] as u32)<<7, _ => x[0] as u32|(x[1] as u32)<<7|(x[2] as u32&15)<<14, }; ret.push(unsafe { adjust(ch1) }); if let Some(ch2) = match x.len() { 4 => Some(((x[2] as u32)>>4)|(x[3] as u32)<<4), 5 => Some(((x[2] as u32)>>4)|(x[3] as u32|(x[4] as u32)<<7)<<4), _ => None, } { ret.push(unsafe { adjust(ch2) }); } } ret } fn unadjust(x: char) -> u32 { let x = x as u32; if x >= 0xd800 { x - 0xd2800 } else { x } } pub fn decode(x: &str) -> Vec<u8> { let mut ret = Vec::new(); let mut chs = x.chars(); while let Some(ch1) = chs.next() { let u1 = unadjust(ch1); ret.push((u1&127) as u8); ret.push((u1>>7&127) as u8); if let Some(ch2) = chs.next() { let u2 = unadjust(ch2); ret.push((u1>>14&127|(u2&15)<<4) as u8); ret.push(((u2>>4)&127) as u8); ret.push(((u2>>11)&127) as u8); } } while let Some(&0) = ret.last() { ret.pop(); } ret } pub fn encode_str(x: &str) -> String { encode(x.as_bytes()) } pub fn decode_str(x: &str) -> String { unsafe { String::from_utf8_unchecked(decode(x)) } } #[cfg(test)] mod tests { use super::*; const TESTR: &'static str = "asdf hello"; #[test] fn test() { println!("{:?}", TESTR.as_bytes()); let enc = encode(TESTR.as_bytes()); assert!(enc.chars().count() < TESTR.chars().count()); let dec = decode(&enc); println!("{:?}", dec); assert!(dec == TESTR.as_bytes()); } #[test] fn test_str() { println!("{}", TESTR); let enc = encode_str(TESTR); assert!(enc.chars().count() < TESTR.chars().count()); let dec = decode_str(&enc); println!("{}", dec); assert!(dec == TESTR); } }