1 /* 2 SPDX-License-Identifier: Apache-2.0 OR MIT 3 4 Copyright 2020 The arboard contributors 5 6 The project to which this file belongs is licensed under either of 7 the Apache 2.0 or the MIT license at the licensee's choice. The terms 8 and conditions of the chosen license apply to this file. 9 */ 10 11 use std::borrow::Cow; 12 use thiserror::Error; 13 14 /// An error that might happen during a clipboard operation. 15 /// 16 /// Note that both the `Display` and the `Debug` trait is implemented for this type in such a way 17 /// that they give a short human-readable description of the error; however the documentation 18 /// gives a more detailed explanation for each error kind. 19 #[derive(Error)] 20 pub enum Error { 21 /// The clipboard contents were not available in the requested format. 22 /// This could either be due to the clipboard being empty or the clipboard contents having 23 /// an incompatible format to the requested one (eg when calling `get_image` on text) 24 #[error("The clipboard contents were not available in the requested format or the clipboard is empty.")] 25 ContentNotAvailable, 26 27 /// The native clipboard is not accessible due to being held by an other party. 28 /// 29 /// This "other party" could be a different process or it could be within 30 /// the same program. So for example you may get this error when trying 31 /// to interact with the clipboard from multiple threads at once. 32 /// 33 /// Note that it's OK to have multiple `Clipboard` instances. The underlying 34 /// implementation will make sure that the native clipboard is only 35 /// opened for transferring data and then closed as soon as possible. 36 #[error("The native clipboard is not accessible due to being held by an other party.")] 37 ClipboardOccupied, 38 39 /// This can happen in either of the following cases. 40 /// 41 /// - When returned from `set_image`: the image going to the clipboard cannot be converted to the appropriate format. 42 /// - When returned from `get_image`: the image coming from the clipboard could not be converted into the `ImageData` struct. 43 /// - When returned from `get_text`: the text coming from the clipboard is not valid utf-8 or cannot be converted to utf-8. 44 #[error("The image or the text that was about the be transferred to/from the clipboard could not be converted to the appropriate format.")] 45 ConversionFailure, 46 47 /// Any error that doesn't fit the other error types. 48 /// 49 /// The `description` field is only meant to help the developer and should not be relied on as a 50 /// means to identify an error case during runtime. 51 #[error("Unknown error while interacting with the clipboard: {description}")] 52 Unknown { description: String }, 53 } 54 55 impl std::fmt::Debug for Error { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 57 use Error::*; 58 macro_rules! kind_to_str { 59 ($( $e: pat ),*) => { 60 match self { 61 $( 62 $e => stringify!($e), 63 )* 64 } 65 } 66 } 67 let name = 68 kind_to_str!(ContentNotAvailable, ClipboardOccupied, ConversionFailure, Unknown { .. }); 69 f.write_fmt(format_args!("{} - \"{}\"", name, self)) 70 } 71 } 72 73 /// Stores pixel data of an image. 74 /// 75 /// Each element in `bytes` stores the value of a channel of a single pixel. 76 /// This struct stores four channels (red, green, blue, alpha) so 77 /// a `3*3` image is going to be stored on `3*3*4 = 36` bytes of data. 78 /// 79 /// The pixels are in row-major order meaning that the second pixel 80 /// in `bytes` (starting at the fifth byte) corresponds to the pixel that's 81 /// sitting to the right side of the top-left pixel (x=1, y=0) 82 /// 83 /// Assigning a `2*1` image would for example look like this 84 /// ``` 85 /// use arboard::ImageData; 86 /// use std::borrow::Cow; 87 /// let bytes = [ 88 /// // A red pixel 89 /// 255, 0, 0, 255, 90 /// 91 /// // A green pixel 92 /// 0, 255, 0, 255, 93 /// ]; 94 /// let img = ImageData { 95 /// width: 2, 96 /// height: 1, 97 /// bytes: Cow::from(bytes.as_ref()) 98 /// }; 99 /// ``` 100 #[derive(Debug, Clone)] 101 pub struct ImageData<'a> { 102 pub width: usize, 103 pub height: usize, 104 pub bytes: Cow<'a, [u8]>, 105 } 106 107 impl<'a> ImageData<'a> { 108 /// Returns a the bytes field in a way that it's guaranteed to be owned. 109 /// It moves the bytes if they are already owned and clones them if they are borrowed. into_owned_bytes(self) -> std::borrow::Cow<'static, [u8]>110 pub fn into_owned_bytes(self) -> std::borrow::Cow<'static, [u8]> { 111 self.bytes.into_owned().into() 112 } 113 114 /// Returns an image data that is guaranteed to own its bytes. 115 /// It moves the bytes if they are already owned and clones them if they are borrowed. to_owned_img(&self) -> ImageData<'static>116 pub fn to_owned_img(&self) -> ImageData<'static> { 117 ImageData { 118 width: self.width, 119 height: self.height, 120 bytes: self.bytes.clone().into_owned().into(), 121 } 122 } 123 } 124