tvscreener/tui/
clipboard.rs1use std::io::{self, Write};
7
8pub fn copy_via_osc52(text: &str) -> io::Result<()> {
17 let encoded = encode_base64(text.as_bytes());
18 let mut out = io::stdout();
19 write!(out, "\x1b]52;c;{encoded}\x07")?;
21 out.flush()
22}
23
24fn encode_base64(data: &[u8]) -> String {
25 const TABLE: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
26 let mut out = String::with_capacity(data.len().div_ceil(3) * 4);
27 let mut i = 0;
28 while i + 3 <= data.len() {
29 let n = (u32::from(data[i]) << 16) | (u32::from(data[i + 1]) << 8) | u32::from(data[i + 2]);
30 out.push(TABLE[((n >> 18) & 0x3f) as usize] as char);
31 out.push(TABLE[((n >> 12) & 0x3f) as usize] as char);
32 out.push(TABLE[((n >> 6) & 0x3f) as usize] as char);
33 out.push(TABLE[(n & 0x3f) as usize] as char);
34 i += 3;
35 }
36 match data.len() - i {
37 1 => {
38 let n = u32::from(data[i]) << 16;
39 out.push(TABLE[((n >> 18) & 0x3f) as usize] as char);
40 out.push(TABLE[((n >> 12) & 0x3f) as usize] as char);
41 out.push('=');
42 out.push('=');
43 }
44 2 => {
45 let n = (u32::from(data[i]) << 16) | (u32::from(data[i + 1]) << 8);
46 out.push(TABLE[((n >> 18) & 0x3f) as usize] as char);
47 out.push(TABLE[((n >> 12) & 0x3f) as usize] as char);
48 out.push(TABLE[((n >> 6) & 0x3f) as usize] as char);
49 out.push('=');
50 }
51 _ => {}
52 }
53 out
54}
55
56#[cfg(test)]
57mod tests {
58 use super::encode_base64;
59
60 #[test]
61 fn base64_known_vectors() {
62 assert_eq!(encode_base64(b""), "");
63 assert_eq!(encode_base64(b"f"), "Zg==");
64 assert_eq!(encode_base64(b"fo"), "Zm8=");
65 assert_eq!(encode_base64(b"foo"), "Zm9v");
66 assert_eq!(encode_base64(br#"{"rows":[]}"#), "eyJyb3dzIjpbXX0=");
67 }
68}