1use std::io::Read;
17use std::io::Write;
18use std::fmt;
19use flate2::Compression;
20use flate2::write::DeflateEncoder;
21use flate2::read::DeflateDecoder;
22
23#[derive(Clone, Eq, PartialEq, Hash)]
27#[cfg_attr(feature = "with_serde", derive(serde_derive::Serialize, serde_derive::Deserialize))]
28pub struct ComprString {
29 gz: Box<[u8]>
30}
31
32impl ComprString {
33 pub fn new(s: &str) -> Self {
37 let mut e = DeflateEncoder::new(Vec::with_capacity(s.len()/2), Compression::best());
38 e.write_all(s.as_bytes()).unwrap();
39 ComprString{ gz: e.finish().unwrap().into_boxed_slice() }
40 }
41
42 pub fn to_string(&self) -> String {
46 let mut deflater = DeflateDecoder::new(&self.gz[..]);
47 let mut s = String::with_capacity(self.gz.len()*2);
48 deflater.read_to_string(&mut s).unwrap();
49 s
50 }
51
52 pub fn compressed_len(&self) -> usize {
57 self.gz.len()
58 }
59}
60
61impl fmt::Display for ComprString {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 f.write_str(&self.to_string())
64 }
65}
66
67impl fmt::Debug for ComprString {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 self.to_string().fmt(f)?;
70 write!(f, "@{}B", self.gz.len())
71 }
72}
73
74impl From<String> for ComprString {
75 fn from(o: String) -> Self {
76 Self::new(&o)
77 }
78}
79
80impl Into<String> for ComprString {
81 fn into(self) -> String {
82 self.to_string()
83 }
84}
85
86impl From<Box<str>> for ComprString {
87 fn from(o: Box<str>) -> Self {
88 Self::new(&o)
89 }
90}
91
92impl Into<Box<str>> for ComprString {
93 fn into(self) -> Box<str> {
94 self.to_string().into_boxed_str()
95 }
96}
97
98impl<'a> From<&'a str> for ComprString {
99 fn from(o: &'a str) -> Self {
100 Self::new(o)
101 }
102}
103
104#[test]
105fn test() {
106 let s = ComprString::new("hęllo world");
107 assert_eq!("hęllo world", &s.to_string());
108 assert_eq!("hęllo world", &format!("{}", s));
109 assert_eq!("\"hęllo world\"@17B", &format!("{:?}", s));
110
111 let s2 = ComprString::new("hęllo world");
112 assert_eq!(s, s2);
113
114 let s = ComprString::new("");
115 assert_eq!("", &s.to_string());
116 assert_eq!(2, s.compressed_len());
117
118 let l = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
119 let s = ComprString::new(l);
120 assert_eq!(l, &s.to_string());
121 assert!(s.compressed_len() < l.len());
122}