uncurses/ansi/
clipboard.rs1use std::io::{self, Write};
28
29pub const SYSTEM_CLIPBOARD: u8 = b'c';
31
32pub const PRIMARY_CLIPBOARD: u8 = b'p';
34
35pub fn write_set_clipboard<W: Write>(w: &mut W, pc: u8, data: &[u8]) -> io::Result<()> {
39 let encoded = base64_encode(data);
40 write!(w, "\x1b]52;{};{}\x07", pc as char, encoded)
41}
42
43pub fn write_request_clipboard<W: Write>(w: &mut W, pc: u8) -> io::Result<()> {
47 write!(w, "\x1b]52;{};?\x07", pc as char)
48}
49
50pub fn write_clear_clipboard<W: Write>(w: &mut W, pc: u8) -> io::Result<()> {
54 write!(w, "\x1b]52;{};\x07", pc as char)
55}
56
57fn base64_encode(input: &[u8]) -> String {
58 const ALPHABET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
59 let mut out = String::with_capacity(input.len().div_ceil(3) * 4);
60 let mut i = 0;
61 while i + 3 <= input.len() {
62 let n = ((input[i] as u32) << 16) | ((input[i + 1] as u32) << 8) | input[i + 2] as u32;
63 out.push(ALPHABET[((n >> 18) & 0x3f) as usize] as char);
64 out.push(ALPHABET[((n >> 12) & 0x3f) as usize] as char);
65 out.push(ALPHABET[((n >> 6) & 0x3f) as usize] as char);
66 out.push(ALPHABET[(n & 0x3f) as usize] as char);
67 i += 3;
68 }
69 let rem = input.len() - i;
70 if rem == 1 {
71 let n = (input[i] as u32) << 16;
72 out.push(ALPHABET[((n >> 18) & 0x3f) as usize] as char);
73 out.push(ALPHABET[((n >> 12) & 0x3f) as usize] as char);
74 out.push('=');
75 out.push('=');
76 } else if rem == 2 {
77 let n = ((input[i] as u32) << 16) | ((input[i + 1] as u32) << 8);
78 out.push(ALPHABET[((n >> 18) & 0x3f) as usize] as char);
79 out.push(ALPHABET[((n >> 12) & 0x3f) as usize] as char);
80 out.push(ALPHABET[((n >> 6) & 0x3f) as usize] as char);
81 out.push('=');
82 }
83 out
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_base64() {
92 assert_eq!(base64_encode(b"hi"), "aGk=");
93 assert_eq!(base64_encode(b"hello"), "aGVsbG8=");
94 assert_eq!(base64_encode(b"foobar"), "Zm9vYmFy");
95 }
96
97 #[test]
98 fn test_set_clipboard() {
99 let mut buf = Vec::new();
100 write_set_clipboard(&mut buf, SYSTEM_CLIPBOARD, b"hi").unwrap();
101 assert_eq!(buf, b"\x1b]52;c;aGk=\x07");
102 }
103
104 #[test]
105 fn test_request_clipboard() {
106 let mut buf = Vec::new();
107 write_request_clipboard(&mut buf, PRIMARY_CLIPBOARD).unwrap();
108 assert_eq!(buf, b"\x1b]52;p;?\x07");
109 }
110}