From 7097f211005047cc43fc8cfcf524df8398c21c85 Mon Sep 17 00:00:00 2001 From: wucke13 Date: Mon, 19 Sep 2022 20:20:55 +0200 Subject: [PATCH 1/4] update dependencies, fix warnings --- Cargo.toml | 5 +-- src/errors.rs | 20 +++++------ src/x11.rs | 94 +++++++++++++++++++++++---------------------------- 3 files changed, 55 insertions(+), 64 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ebb8b4f..39b71f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "clipboard2" version = "0.1.1" authors = ["Avi Weinstock ", "Felix Schütt "] +edition = "2021" description = "clipboard2 is an improved version of clipboard-rs with better error handling and MIME type handling on Windows" repository = "https://github.com/fschutt/clipboard2" license = "MIT" @@ -9,7 +10,7 @@ keywords = ["clipboard"] readme = "README.md" [target.'cfg(windows)'.dependencies] -clipboard-win = "2.0.0" +clipboard-win = "4.4" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" @@ -17,4 +18,4 @@ objc_id = "0.1" objc-foundation = "0.1" [target.'cfg(any(target_os = "linux", target_os = "openbsd"))'.dependencies] -x11-clipboard = "0.3.0-alpha.1" +x11-clipboard = "0.7" diff --git a/src/errors.rs b/src/errors.rs index bd00c49..e8dc628 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,18 +1,18 @@ use std::fmt::{self, Display, Formatter}; -#[cfg(any(target_os="linux", target_os="openbsd"))] +#[cfg(any(target_os = "linux", target_os = "openbsd"))] use x11_clipboard::error::Error as X11Error; -use std::string::FromUtf8Error; use std::error::Error; use std::io::Error as IoError; +use std::string::FromUtf8Error; #[derive(Debug)] pub enum ClipboardError { Unimplemented, IoError(IoError), EncodingError(FromUtf8Error), - #[cfg(any(target_os = "linux", target_os="openbsd"))] + #[cfg(any(target_os = "linux", target_os = "openbsd"))] X11ClipboardError(X11Error), #[cfg(target_os = "macos")] MacOsClipboardError(MacOsError), @@ -20,7 +20,7 @@ pub enum ClipboardError { WindowsClipboardError(WinError), } -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum WinError { EmptyClipboard, @@ -40,7 +40,7 @@ impl Error for WinError { use self::WinError::*; match *self { EmptyClipboard => "Empty clipboard or couldn't determine format of clipboard contents", - FormatNoSize => "Could not determine the length of the clipboard contents" + FormatNoSize => "Could not determine the length of the clipboard contents", } } @@ -55,21 +55,21 @@ impl From for ClipboardError { } } -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] impl From for ClipboardError { fn from(e: WinError) -> Self { ClipboardError::WindowsClipboardError(e) } } -#[cfg(any(target_os="linux", target_os="openbsd"))] +#[cfg(any(target_os = "linux", target_os = "openbsd"))] impl From for ClipboardError { fn from(e: X11Error) -> Self { ClipboardError::X11ClipboardError(e) } } -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] impl From for ClipboardError { fn from(e: MacOsError) -> Self { ClipboardError::MacOsClipboardError(e) @@ -106,8 +106,8 @@ impl Display for ClipboardError { use self::ClipboardError::*; match self { Unimplemented => write!(f, "Clipboard::Unimplemented: Attempted to get or set the clipboard, which hasn't been implemented yet."), - IoError(ref e) => write!(f, "Clipboard::IoError: {} cause: {:?}", e.description(), e.cause()), - EncodingError(ref e) => write!(f, "Clipboard::EncodingError: {} cause: {:?}", e.description(), e.cause()), + IoError(ref e) => write!(f, "Clipboard::IoError: {e} cause: {:?}", e.source()), + EncodingError(ref e) => write!(f, "Clipboard::EncodingError: {e} cause: {:?}", e.source()), #[cfg(any(target_os="linux", target_os="openbsd"))] X11ClipboardError(ref e) => write!(f, "X11ClipboardError: {}", e), #[cfg(target_os="macos")] diff --git a/src/x11.rs b/src/x11.rs index 3519e34..6eb071f 100644 --- a/src/x11.rs +++ b/src/x11.rs @@ -1,58 +1,48 @@ -use { - Clipboard, - errors::ClipboardError, - clipboard_metadata::ClipboardContentType, -}; -use x11_clipboard::Clipboard as SystemClipboard; +use crate::{clipboard_metadata::ClipboardContentType, errors::ClipboardError, Clipboard}; use std::time::Duration; +use x11_clipboard::Clipboard as SystemClipboard; pub struct X11Clipboard { - inner: SystemClipboard, + inner: SystemClipboard, } impl Clipboard for X11Clipboard { - - type Output = Self; - - fn new() - -> Result - { - Ok(X11Clipboard { - inner: SystemClipboard::new()? - }) - } - - /// # **WARNING**: Unimplemented, use `get_string_contents` - fn get_contents(&self) - -> Result<(Vec, ClipboardContentType), ClipboardError> - { - Err(ClipboardError::Unimplemented) - } - - fn get_string_contents(&self) -> Result - { - Ok(String::from_utf8(self.inner.load( - self.inner.getter.atoms.primary, - self.inner.getter.atoms.utf8_string, - self.inner.getter.atoms.property, - Duration::from_secs(3), - )?)?) - } - - /// # **WARNING**: Unimplemented, use `set_string_contents` - fn set_contents(&self, _contents: Vec, _: ClipboardContentType) - -> Result<(), ClipboardError> - { - Err(ClipboardError::Unimplemented) - } - - fn set_string_contents(&self, contents: String) - -> Result<(), ClipboardError> - { - Ok(self.inner.store( - self.inner.getter.atoms.primary, - self.inner.setter.atoms.utf8_string, - &*contents, - )?) - } -} \ No newline at end of file + type Output = Self; + + fn new() -> Result { + Ok(X11Clipboard { + inner: SystemClipboard::new()?, + }) + } + + /// # **WARNING**: Unimplemented, use `get_string_contents` + fn get_contents(&self) -> Result<(Vec, ClipboardContentType), ClipboardError> { + Err(ClipboardError::Unimplemented) + } + + fn get_string_contents(&self) -> Result { + Ok(String::from_utf8(self.inner.load( + self.inner.getter.atoms.primary, + self.inner.getter.atoms.utf8_string, + self.inner.getter.atoms.property, + Duration::from_secs(3), + )?)?) + } + + /// # **WARNING**: Unimplemented, use `set_string_contents` + fn set_contents( + &self, + _contents: Vec, + _: ClipboardContentType, + ) -> Result<(), ClipboardError> { + Err(ClipboardError::Unimplemented) + } + + fn set_string_contents(&self, contents: String) -> Result<(), ClipboardError> { + Ok(self.inner.store( + self.inner.getter.atoms.primary, + self.inner.setter.atoms.utf8_string, + &*contents, + )?) + } +} From b9c8b2d015df1db665f8969b0d3dfc77b60c6270 Mon Sep 17 00:00:00 2001 From: wucke13 Date: Mon, 19 Sep 2022 20:21:18 +0200 Subject: [PATCH 2/4] add CI --- .github/workflows/audit.yml | 20 ++++++++++++ .github/workflows/rust.yml | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 .github/workflows/audit.yml create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..cf6304c --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,20 @@ +name: Security audit + +on: + schedule: + - cron: '0 0 * * *' + push: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + pull_request: + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..bf33a7b --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,65 @@ +on: [push, pull_request] + +name: Rust + +jobs: + check: + name: Check + strategy: + matrix: + os: [ macos-latest, ubuntu-latest, windows-latest ] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: Run cargo check + uses: actions-rs/cargo@v1 + with: + command: check + + test: + name: Test Suite + strategy: + matrix: + os: [ macos-latest, ubuntu-latest, windows-latest ] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: Run cargo test + uses: actions-rs/cargo@v1 + with: + command: test + + clippy_check: + name: Clippy + strategy: + matrix: + os: [ macos-latest, ubuntu-latest, windows-latest ] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: clippy + override: true + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From de9f9e925ca7c70590140492cfe56c93476b799d Mon Sep 17 00:00:00 2001 From: wucke13 Date: Mon, 19 Sep 2022 20:38:01 +0200 Subject: [PATCH 3/4] fix build --- src/clipboard_metadata.rs | 408 +++++++++++++++++++------------------- src/errors.rs | 17 +- src/lib.rs | 42 ++-- src/macos.rs | 135 ++++++------- src/win.rs | 115 ++++++----- 5 files changed, 353 insertions(+), 364 deletions(-) diff --git a/src/clipboard_metadata.rs b/src/clipboard_metadata.rs index 1569d3b..0bf6c33 100644 --- a/src/clipboard_metadata.rs +++ b/src/clipboard_metadata.rs @@ -1,223 +1,223 @@ #![allow(dead_code)] pub enum ClipboardContentType { - #[cfg(any(target_os="linux", target_os="openbsd"))] - X11ContentType(X11ContentType), - #[cfg(target_os="windows")] - WinContentType(WinContentType), - #[cfg(target_os="macos")] - MacContent, + #[cfg(any(target_os = "linux", target_os = "openbsd"))] + X11ContentType(X11ContentType), + #[cfg(target_os = "windows")] + WinContentType(WinContentType), + #[cfg(target_os = "macos")] + MacContent, } /// See: https://tronche.com/gui/x/icccm/sec-2.html#s-2 -#[cfg(any(target_os="linux", target_os="openbsd"))] +#[cfg(any(target_os = "linux", target_os = "openbsd"))] pub enum X11ContentType { - AdobePortableDocumentFormat, - ApplePict, - /// A list of pixel values - Background, - /// A list of bitmap IDs - Bitmap, - /// The start and end of the selection in bytes - CharacterPosition, - Class, - /// Any top-level window owned by the selection owner - ClientWindow, - /// A list of colormap IDs - Colormap, - /// The start and end column numbers - ColumnNumber, - /// Compound Text - CompoundText, - Delete, - /// A list of drawable IDs - Drawable, - Eps, - EpsInterchange, - /// The full path name of a file - FileName, - /// A list of pixel values - Foreground, - HostName, - InsertProperty, - InsertSelection, - /// The number of bytes in the selection - Length, - /// The start and end line numbers - LineNumber, - /// The number of disjoint parts of the selection - ListLength, - /// The name of the selected procedure - Module, - Multiple, - Name, - /// ISO Office Document Interchange Format - Odif, - /// The operating system of the owner client - OwnerOs, - /// A list of pixmap IDs - Pixmap, - Postscript, - /// The name of the selected procedure - Procedure, - /// The process ID of the owner - Process, - /// ISO Latin-1 (+TAB+NEWLINE) text - String, - /// A list of valid target atoms - Targets, - /// The task ID of the owner - Task, - /// The text in the owner's choice of encoding - Text, - /// The timestamp used to acquire the selection - Timestamp, - /// The name of the user running the owner - User, + AdobePortableDocumentFormat, + ApplePict, + /// A list of pixel values + Background, + /// A list of bitmap IDs + Bitmap, + /// The start and end of the selection in bytes + CharacterPosition, + Class, + /// Any top-level window owned by the selection owner + ClientWindow, + /// A list of colormap IDs + Colormap, + /// The start and end column numbers + ColumnNumber, + /// Compound Text + CompoundText, + Delete, + /// A list of drawable IDs + Drawable, + Eps, + EpsInterchange, + /// The full path name of a file + FileName, + /// A list of pixel values + Foreground, + HostName, + InsertProperty, + InsertSelection, + /// The number of bytes in the selection + Length, + /// The start and end line numbers + LineNumber, + /// The number of disjoint parts of the selection + ListLength, + /// The name of the selected procedure + Module, + Multiple, + Name, + /// ISO Office Document Interchange Format + Odif, + /// The operating system of the owner client + OwnerOs, + /// A list of pixmap IDs + Pixmap, + Postscript, + /// The name of the selected procedure + Procedure, + /// The process ID of the owner + Process, + /// ISO Latin-1 (+TAB+NEWLINE) text + String, + /// A list of valid target atoms + Targets, + /// The task ID of the owner + Task, + /// The text in the owner's choice of encoding + Text, + /// The timestamp used to acquire the selection + Timestamp, + /// The name of the user running the owner + User, } /// See https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168%28v=vs.85%29.aspx -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum WinContentType { - /// A handle to a bitmap (HBITMAP) - Bitmap, - /// A memory object containing a BITMAPINFO structure followed by the bitmap bits. - Dib, - /// A memory object containing a BITMAPV5HEADER structure followed by - /// the bitmap color space information and the bitmap bits. - Dib5, - /// Software Arts' Data Interchange Format. - Dif, - /// Bitmap display format associated with a private format. The hMem parameter must be a - /// handle to data that can be displayed in bitmap format in lieu of the privately - /// formatted data. - DspBitmap, - /// CF_DSPENHMETAFILE: Enhanced metafile display format associated with a private - /// format. The hMem parameter must be a handle to data that can be displayed in - /// enhanced metafile format in lieu of the privately formatted data. - DspEnhancedMetaFile, - /// CF_DSPMETAFILEPICT: Metafile-picture display format associated with a private - /// format. The hMem parameter must be a handle to data that can be displayed in - /// metafile-picture format in lieu of the privately formatted data. - DspMetaFilePict, - /// Text display format associated with a private format. The hMem parameter must - /// be a handle to data that can be displayed in text format in lieu of the - /// privately formatted data. - DspText, - /// A handle to an enhanced metafile (HENHMETAFILE). - EnhancedMetaFile, - /// Start of a range of integer values for application-defined - /// GDI object clipboard formats. - GdiObjectFirst, - /// End of a range of integer values for application-defined GDI - /// object clipboard formats. - GdiObjectLast, - /// A handle to type HDROP that identifies a list of files. - HDrop, - /// The data is a handle to the locale identifier associated - /// with text in the clipboard. - Locale, - /// Handle to a metafile picture format as defined by the METAFILEPICT structure. - MetaFilePict, - /// Text format containing characters in the OEM character set. - OemText, - /// Owner-display format - OwnerDisplay, - /// Handle to a color palette - Palette, - /// Data for the pen extensions to the Microsoft Windows for Pen Computing - PenData, - /// Start of a range of integer values for private clipboard formats - PrivateFirst, - /// End of a range of integer values for private clipboard formats - PrivateLast, - /// Represents audio data more complex than can be represented in a CF_WAVE standard wave format - Riff, - /// Microsoft Symbolic Link (SYLK) format - Sylk, - /// ANSI text format - Text, - /// Tagged-image file format - Tiff, - /// UTF16 text format - UnicodeText, - /// Represents audio data in one of the standard wave formats - Wave, - /// Custom content type, used as backup if none of the formats are known - Custom(u32), + /// A handle to a bitmap (HBITMAP) + Bitmap, + /// A memory object containing a BITMAPINFO structure followed by the bitmap bits. + Dib, + /// A memory object containing a BITMAPV5HEADER structure followed by + /// the bitmap color space information and the bitmap bits. + Dib5, + /// Software Arts' Data Interchange Format. + Dif, + /// Bitmap display format associated with a private format. The hMem parameter must be a + /// handle to data that can be displayed in bitmap format in lieu of the privately + /// formatted data. + DspBitmap, + /// CF_DSPENHMETAFILE: Enhanced metafile display format associated with a private + /// format. The hMem parameter must be a handle to data that can be displayed in + /// enhanced metafile format in lieu of the privately formatted data. + DspEnhancedMetaFile, + /// CF_DSPMETAFILEPICT: Metafile-picture display format associated with a private + /// format. The hMem parameter must be a handle to data that can be displayed in + /// metafile-picture format in lieu of the privately formatted data. + DspMetaFilePict, + /// Text display format associated with a private format. The hMem parameter must + /// be a handle to data that can be displayed in text format in lieu of the + /// privately formatted data. + DspText, + /// A handle to an enhanced metafile (HENHMETAFILE). + EnhancedMetaFile, + /// Start of a range of integer values for application-defined + /// GDI object clipboard formats. + GdiObjectFirst, + /// End of a range of integer values for application-defined GDI + /// object clipboard formats. + GdiObjectLast, + /// A handle to type HDROP that identifies a list of files. + HDrop, + /// The data is a handle to the locale identifier associated + /// with text in the clipboard. + Locale, + /// Handle to a metafile picture format as defined by the METAFILEPICT structure. + MetaFilePict, + /// Text format containing characters in the OEM character set. + OemText, + /// Owner-display format + OwnerDisplay, + /// Handle to a color palette + Palette, + /// Data for the pen extensions to the Microsoft Windows for Pen Computing + PenData, + /// Start of a range of integer values for private clipboard formats + PrivateFirst, + /// End of a range of integer values for private clipboard formats + PrivateLast, + /// Represents audio data more complex than can be represented in a CF_WAVE standard wave format + Riff, + /// Microsoft Symbolic Link (SYLK) format + Sylk, + /// ANSI text format + Text, + /// Tagged-image file format + Tiff, + /// UTF16 text format + UnicodeText, + /// Represents audio data in one of the standard wave formats + Wave, + /// Custom content type, used as backup if none of the formats are known + Custom(u32), } -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] impl WinContentType { - /// Toggles through the clipboard types - pub(crate) fn next(&self) -> Option { - use self::WinContentType::*; - match self { - Bitmap => Some(Dib), - Dib => Some(Dib5), - Dib5 => Some(Dif), - Dif => Some(DspBitmap), - DspBitmap => Some(DspEnhancedMetaFile), - DspEnhancedMetaFile => Some(DspMetaFilePict), - DspMetaFilePict => Some(DspText), - DspText => Some(EnhancedMetaFile), - EnhancedMetaFile => Some(GdiObjectFirst), - GdiObjectFirst => Some(GdiObjectLast), - GdiObjectLast => Some(HDrop), - HDrop => Some(Locale), - Locale => Some(MetaFilePict), - MetaFilePict => Some(OemText), - OemText => Some(OwnerDisplay), - OwnerDisplay => Some(Palette), - Palette => Some(PenData), - PenData => Some(PrivateFirst), - PrivateFirst => Some(PrivateLast), - PrivateLast => Some(Riff), - Riff => Some(Sylk), - Sylk => Some(Text), - Text => Some(Tiff), - Tiff => Some(UnicodeText), - UnicodeText => Some(Wave), - Wave => Some(Custom((*self).into())), - Custom(_) => None, - } - } + /// Toggles through the clipboard types + pub(crate) fn next(&self) -> Option { + use self::WinContentType::*; + match self { + Self::Bitmap => Some(Dib), + Dib => Some(Dib5), + Dib5 => Some(Dif), + Dif => Some(DspBitmap), + DspBitmap => Some(DspEnhancedMetaFile), + DspEnhancedMetaFile => Some(DspMetaFilePict), + DspMetaFilePict => Some(DspText), + DspText => Some(EnhancedMetaFile), + EnhancedMetaFile => Some(GdiObjectFirst), + GdiObjectFirst => Some(GdiObjectLast), + GdiObjectLast => Some(HDrop), + HDrop => Some(Locale), + Locale => Some(MetaFilePict), + MetaFilePict => Some(OemText), + OemText => Some(OwnerDisplay), + OwnerDisplay => Some(Palette), + Palette => Some(PenData), + PenData => Some(PrivateFirst), + PrivateFirst => Some(PrivateLast), + PrivateLast => Some(Riff), + Riff => Some(Sylk), + Sylk => Some(Text), + Text => Some(Tiff), + Tiff => Some(UnicodeText), + UnicodeText => Some(Wave), + Wave => Some(Custom((*self).into())), + Custom(_) => None, + } + } } -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] impl Into for WinContentType { - fn into(self) -> u32 { - use self::WinContentType::*; - use clipboard_win::formats::*; - match self { - Bitmap => CF_BITMAP, - Custom(a) => a, - Dib => CF_DIB, - Dib5 => CF_DIBV5, - Dif => CF_DIF, - DspBitmap => CF_DSPBITMAP, - DspEnhancedMetaFile => CF_DSPENHMETAFILE, - DspMetaFilePict => CF_DSPMETAFILEPICT, - DspText => CF_DSPTEXT, - EnhancedMetaFile => CF_ENHMETAFILE, - GdiObjectFirst => CF_GDIOBJFIRST, - GdiObjectLast =>CF_GDIOBJLAST, - HDrop => CF_HDROP, - Locale => CF_LOCALE, - MetaFilePict => CF_METAFILEPICT, - OemText => CF_OEMTEXT, - OwnerDisplay => CF_OWNERDISPLAY, - Palette => CF_PALETTE, - PenData => CF_PENDATA, - PrivateFirst => CF_PRIVATEFIRST, - PrivateLast => CF_PRIVATELAST, - Riff => CF_RIFF, - Sylk => CF_SYLK, - Text => CF_TEXT, - Tiff => CF_TIFF, - UnicodeText => CF_UNICODETEXT, - Wave => CF_WAVE, - } - } + fn into(self) -> u32 { + use self::WinContentType::*; + use clipboard_win::formats::*; + match self { + Self::Bitmap => CF_BITMAP, + Custom(a) => a, + Dib => CF_DIB, + Dib5 => CF_DIBV5, + Dif => CF_DIF, + DspBitmap => CF_DSPBITMAP, + DspEnhancedMetaFile => CF_DSPENHMETAFILE, + DspMetaFilePict => CF_DSPMETAFILEPICT, + DspText => CF_DSPTEXT, + EnhancedMetaFile => CF_ENHMETAFILE, + GdiObjectFirst => CF_GDIOBJFIRST, + GdiObjectLast => CF_GDIOBJLAST, + HDrop => CF_HDROP, + Locale => CF_LOCALE, + MetaFilePict => CF_METAFILEPICT, + OemText => CF_OEMTEXT, + OwnerDisplay => CF_OWNERDISPLAY, + Palette => CF_PALETTE, + PenData => CF_PENDATA, + PrivateFirst => CF_PRIVATEFIRST, + PrivateLast => CF_PRIVATELAST, + Riff => CF_RIFF, + Sylk => CF_SYLK, + Text => CF_TEXT, + Tiff => CF_TIFF, + UnicodeText => CF_UNICODETEXT, + Wave => CF_WAVE, + } + } } diff --git a/src/errors.rs b/src/errors.rs index e8dc628..3a91784 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -30,7 +30,7 @@ pub enum WinError { #[cfg(target_os = "windows")] impl Display for WinError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.description()) + write!(f, "{self}") } } @@ -44,7 +44,7 @@ impl Error for WinError { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { None } } @@ -55,6 +55,13 @@ impl From for ClipboardError { } } +#[cfg(target_os = "windows")] +impl From for ClipboardError { + fn from(e: clipboard_win::SystemError) -> Self { + ClipboardError::IoError(e) + } +} + #[cfg(target_os = "windows")] impl From for ClipboardError { fn from(e: WinError) -> Self { @@ -109,11 +116,11 @@ impl Display for ClipboardError { IoError(ref e) => write!(f, "Clipboard::IoError: {e} cause: {:?}", e.source()), EncodingError(ref e) => write!(f, "Clipboard::EncodingError: {e} cause: {:?}", e.source()), #[cfg(any(target_os="linux", target_os="openbsd"))] - X11ClipboardError(ref e) => write!(f, "X11ClipboardError: {}", e), + X11ClipboardError(ref e) => write!(f, "X11ClipboardError: {e}"), #[cfg(target_os="macos")] - MacOsClipboardError(ref e) => write!(f, "MacOsClipboardError: {}", e), + MacOsClipboardError(ref e) => write!(f, "MacOsClipboardError: {e}"), #[cfg(target_os="windows")] - WindowsClipboardError(ref e) => write!(f, "WindowsClipboardError: {} cause: {:?}", e.description(), e.cause()), + WindowsClipboardError(ref e) => write!(f, "WindowsClipboardError: {e} cause: {:?}", e.source()), } } } diff --git a/src/lib.rs b/src/lib.rs index 49f6bdb..37c3b15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,44 +2,40 @@ //! //! Fork of https://github.com/aweinstock314/rust-clipboard with better error handling -#[cfg(target_os="windows")] -extern crate clipboard_win; -#[cfg(any(target_os="linux", target_os="openbsd"))] -extern crate x11_clipboard; -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] #[macro_use] extern crate objc; -#[cfg(target_os="macos")] -extern crate objc_id; -#[cfg(target_os="macos")] -extern crate objc_foundation; -mod errors; pub mod clipboard_metadata; +mod errors; -pub use errors::ClipboardError; pub use clipboard_metadata::ClipboardContentType; +pub use errors::ClipboardError; pub trait Clipboard { - type Output; - fn new() -> Result; - fn get_contents(&self) -> Result<(Vec, ClipboardContentType), ClipboardError>; - fn get_string_contents(&self) -> Result; - fn set_contents(&self, contents: Vec, format: ClipboardContentType) -> Result<(), ClipboardError>; - fn set_string_contents(&self, contents: String) -> Result<(), ClipboardError>; + type Output; + fn new() -> Result; + fn get_contents(&self) -> Result<(Vec, ClipboardContentType), ClipboardError>; + fn get_string_contents(&self) -> Result; + fn set_contents( + &self, + contents: Vec, + format: ClipboardContentType, + ) -> Result<(), ClipboardError>; + fn set_string_contents(&self, contents: String) -> Result<(), ClipboardError>; } -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] pub mod win; -#[cfg(target_os="windows")] +#[cfg(target_os = "windows")] pub use win::WindowsClipboard as SystemClipboard; -#[cfg(any(target_os="linux", target_os="openbsd"))] +#[cfg(any(target_os = "linux", target_os = "openbsd"))] pub mod x11; -#[cfg(any(target_os="linux", target_os="openbsd"))] +#[cfg(any(target_os = "linux", target_os = "openbsd"))] pub use x11::X11Clipboard as SystemClipboard; -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] pub mod macos; -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] pub use macos::MacOsClipboard as SystemClipboard; diff --git a/src/macos.rs b/src/macos.rs index 1343380..b945583 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,94 +1,83 @@ -use { - Clipboard, - errors::{ClipboardError, MacOsError}, - clipboard_metadata::ClipboardContentType, -}; -use objc::runtime::{Object, Class}; -use objc_foundation::{ - INSArray, INSString, INSObject, - NSArray, NSDictionary, NSString, NSObject +use crate::{ + clipboard_metadata::ClipboardContentType, + errors::{ClipboardError, MacOsError}, + Clipboard, }; +use objc::runtime::{Class, Object}; +use objc_foundation::{INSArray, INSObject, INSString, NSArray, NSDictionary, NSObject, NSString}; use objc_id::{Id, Owned}; use std::mem::transmute; // required to bring NSPasteboard into the path of the class-resolver #[link(name = "AppKit", kind = "framework")] -extern "C" { } +extern "C" {} pub struct MacOsClipboard { - pasteboard: Id, + pasteboard: Id, } impl Clipboard for MacOsClipboard { + type Output = Self; - type Output = Self; - - fn new() - -> Result - { - let cls = Class::get("NSPasteboard").ok_or(MacOsError::PasteboardNotFound)?; - let pasteboard: *mut Object = unsafe { msg_send![cls, generalPasteboard] }; - if pasteboard.is_null() { - return Err(MacOsError::NullPasteboard.into()); - } - let pasteboard: Id = unsafe { Id::from_ptr(pasteboard) }; - Ok(MacOsClipboard { pasteboard: pasteboard }) - } + fn new() -> Result { + let cls = Class::get("NSPasteboard").ok_or(MacOsError::PasteboardNotFound)?; + let pasteboard: *mut Object = unsafe { msg_send![cls, generalPasteboard] }; + if pasteboard.is_null() { + return Err(MacOsError::NullPasteboard.into()); + } + let pasteboard: Id = unsafe { Id::from_ptr(pasteboard) }; + Ok(MacOsClipboard { pasteboard }) + } - /// # **WARNING**: Unimplemented, use `get_string_contents` - fn get_contents(&self) - -> Result<(Vec, ClipboardContentType), ClipboardError> - { - Err(ClipboardError::Unimplemented) - } + /// # **WARNING**: Unimplemented, use `get_string_contents` + fn get_contents(&self) -> Result<(Vec, ClipboardContentType), ClipboardError> { + Err(ClipboardError::Unimplemented) + } - fn get_string_contents(&self) - -> Result - { - let string_class: Id = { - let cls: Id = unsafe { Id::from_ptr(class("NSString")) }; - unsafe { transmute(cls) } - }; + fn get_string_contents(&self) -> Result { + let string_class: Id = { + let cls: Id = unsafe { Id::from_ptr(class("NSString")) }; + unsafe { transmute(cls) } + }; - let classes: Id> = NSArray::from_vec(vec![string_class]); - let options: Id> = NSDictionary::new(); + let classes: Id> = NSArray::from_vec(vec![string_class]); + let options: Id> = NSDictionary::new(); - let string_array: Id> = unsafe { - let obj: *mut NSArray = - msg_send![self.pasteboard, readObjectsForClasses:&*classes options:&*options]; - if obj.is_null() { - return Err(MacOsError::ReadObjectsForClassesNull.into()); - } - Id::from_ptr(obj) - }; + let string_array: Id> = unsafe { + let obj: *mut NSArray = + msg_send![self.pasteboard, readObjectsForClasses:&*classes options:&*options]; + if obj.is_null() { + return Err(MacOsError::ReadObjectsForClassesNull.into()); + } + Id::from_ptr(obj) + }; - if string_array.count() == 0 { - Err(MacOsError::ReadObjectsForClassesEmpty.into()) - } else { - Ok(string_array[0].as_str().to_owned()) - } - } + if string_array.count() == 0 { + Err(MacOsError::ReadObjectsForClassesEmpty.into()) + } else { + Ok(string_array[0].as_str().to_owned()) + } + } - /// # **WARNING**: Unimplemented, use `get_string_contents` - fn set_contents(&self, contents: Vec, _: ClipboardContentType) - -> Result<(), ClipboardError> - { - Err(ClipboardError::Unimplemented) - } - - fn set_string_contents(&self, contents: String) - -> Result<(), ClipboardError> - { - let string_array = NSArray::from_vec(vec![NSString::from_str(&contents)]); - let _: usize = unsafe { msg_send![self.pasteboard, clearContents] }; - let success: bool = unsafe { msg_send![self.pasteboard, writeObjects:string_array] }; - return if success { - Ok(()) - } else { - Err(MacOsError::PasteWriteObjectsError.into()) - }; - } + /// # **WARNING**: Unimplemented, use `get_string_contents` + fn set_contents( + &self, + _contents: Vec, + _: ClipboardContentType, + ) -> Result<(), ClipboardError> { + Err(ClipboardError::Unimplemented) + } + fn set_string_contents(&self, contents: String) -> Result<(), ClipboardError> { + let string_array = NSArray::from_vec(vec![NSString::from_str(&contents)]); + let _: usize = unsafe { msg_send![self.pasteboard, clearContents] }; + let success: bool = unsafe { msg_send![self.pasteboard, writeObjects: string_array] }; + if success { + Ok(()) + } else { + Err(MacOsError::PasteWriteObjectsError.into()) + } + } } // This is a convenience function that both cocoa-rs and @@ -97,4 +86,4 @@ impl Clipboard for MacOsClipboard { #[inline] pub fn class(name: &str) -> *mut Class { unsafe { transmute(Class::get(name)) } -} \ No newline at end of file +} diff --git a/src/win.rs b/src/win.rs index 059f2f9..506c0a2 100644 --- a/src/win.rs +++ b/src/win.rs @@ -1,64 +1,61 @@ -use { - Clipboard, - errors::{ClipboardError, WinError}, - clipboard_metadata::{WinContentType, ClipboardContentType} +use crate::{ + clipboard_metadata::{ClipboardContentType, WinContentType}, + errors::{ClipboardError, WinError}, + Clipboard, }; -use clipboard_win::{ - Clipboard as SystemClipboard, - raw::is_format_avail, -}; +use clipboard_win::{raw::is_format_avail, Clipboard as SystemClipboard}; -pub struct WindowsClipboard { } +pub struct WindowsClipboard {} impl Clipboard for WindowsClipboard { - type Output = Self; - - fn new() -> Result { - Ok(WindowsClipboard { }) - } - - fn get_contents(&self) - -> Result<(Vec, ClipboardContentType), ClipboardError> - { - let clipboard = SystemClipboard::new()?; - let mut format = WinContentType::Bitmap; - loop { - if is_format_avail(format.into()) { - let format_size = match clipboard.size(format.into()) { - Some(s) => s, - None => return Err(WinError::FormatNoSize.into()), - }; - let mut vec = vec![0; format_size]; - clipboard.get(format.into(), &mut vec)?; - return Ok((vec, ClipboardContentType::WinContentType(format))); - } else { - match format.next() { - Some(f) => format = f, - None => return Err(WinError::EmptyClipboard.into()), - } - } - } - } - - fn get_string_contents(&self) - -> Result - { - SystemClipboard::new()?.get_string().map_err(|e| e.into()) - } - - fn set_contents(&self, contents: Vec, format: ClipboardContentType) - -> Result<(), ClipboardError> - { - let win_content_type = match format { - ClipboardContentType::WinContentType(w) => w, - }; - SystemClipboard::new()?.set(win_content_type.into(), &contents).map_err(|e| e.into()) - } - - fn set_string_contents(&self, contents: String) - -> Result<(), ClipboardError> - { - SystemClipboard::new()?.set_string(&contents).map_err(|e| e.into()) - } -} \ No newline at end of file + type Output = Self; + + fn new() -> Result { + Ok(WindowsClipboard {}) + } + + fn get_contents(&self) -> Result<(Vec, ClipboardContentType), ClipboardError> { + let clipboard = SystemClipboard::new()?; + let mut format = WinContentType::Bitmap; + loop { + if is_format_avail(format.into()) { + let format_size = match clipboard.size(format.into()) { + Some(s) => s, + None => return Err(WinError::FormatNoSize.into()), + }; + let mut vec = vec![0; format_size]; + clipboard.get(format.into(), &mut vec)?; + return Ok((vec, ClipboardContentType::WinContentType(format))); + } else { + match format.next() { + Some(f) => format = f, + None => return Err(WinError::EmptyClipboard.into()), + } + } + } + } + + fn get_string_contents(&self) -> Result { + SystemClipboard::new()?.get_string().map_err(|e| e.into()) + } + + fn set_contents( + &self, + contents: Vec, + format: ClipboardContentType, + ) -> Result<(), ClipboardError> { + let win_content_type = match format { + ClipboardContentType::WinContentType(w) => w, + }; + SystemClipboard::new()? + .set(win_content_type.into(), &contents) + .map_err(|e| e.into()) + } + + fn set_string_contents(&self, contents: String) -> Result<(), ClipboardError> { + SystemClipboard::new()? + .set_string(&contents) + .map_err(|e| e.into()) + } +} From 9350a650e9e27b5bd2547905701b3df18b5c4d10 Mon Sep 17 00:00:00 2001 From: wucke13 Date: Mon, 19 Sep 2022 22:19:49 +0200 Subject: [PATCH 4/4] run cargo fmt --- examples/simple.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/simple.rs b/examples/simple.rs index e7092f6..6320d02 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -3,7 +3,9 @@ extern crate clipboard2; use clipboard2::{Clipboard, SystemClipboard}; fn main() { - let clipboard = SystemClipboard::new().unwrap(); - clipboard.set_string_contents(String::from("Hello")).unwrap(); - println!("{}", clipboard.get_string_contents().unwrap()); -} \ No newline at end of file + let clipboard = SystemClipboard::new().unwrap(); + clipboard + .set_string_contents(String::from("Hello")) + .unwrap(); + println!("{}", clipboard.get_string_contents().unwrap()); +}