Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support custom mime types #56

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open

Conversation

wash2
Copy link
Member

@wash2 wash2 commented Feb 27, 2024

This adds support for loading and storing data that is not text. I've renamed some of the existing methods, so it's a breaking change, but I guess I could avoid renaming the methods so that isn't an issue. and make the methods for loading and storing custom types something like store_custom or load_custom.

Copy link
Member

@kchibisov kchibisov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have CHANGELOG which is here, but no one cares about, even me.

src/worker.rs Outdated
Comment on lines 33 to 34
Store(Box<dyn AsMimeTypes + Send>, SelectionTarget),
/// Store Data with the given Mime Types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This broke formatting. Also, each doc comments ends with . in the end.

src/worker.rs Outdated
Comment on lines 68 to 70
if state.data_device_manager_state.is_some() =>
{
if let Err(err) = state.load_selection(target, &mime_types) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't follow the old code, because it doesn't check primary selection clipboard, which may be absent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean. I don't think the old code checked primary_selection_manager_state but I can add a check for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, the code I wrote is fool-proof and actually doesn't try to unwrap anything. I'm not even sure whether the first check is needed for data device, given that it's also checked, kind of.

Though, maybe won't hurt.

src/mime.rs Outdated
@@ -1,50 +1,88 @@
use std::borrow::Cow;
use thiserror::Error;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's used just for a single enum in the entire crate, no need to be fancy.

src/lib.rs Outdated
Comment on lines 107 to 110
fn store_inner<T: AsMimeTypes + Send + 'static>(&self, data: T, target: SelectionTarget) {
let request = worker::Command::Store(Box::new(data), target);
let _ = self.request_sender.send(request);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All private functions go bellow the public ones.

src/lib.rs Outdated
Comment on lines 59 to 70
if let Ok(reply) = self.request_receiver.recv() {
reply
match reply {
Ok((data, mime)) => T::try_from((data, mime))
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)),
Err(err) => Err(err),
}
} else {
// The clipboard thread is dead, however we shouldn't crash downstream, so
// propogating an error.
Err(std::io::Error::new(std::io::ErrorKind::Other, "clipboard is dead."))
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can probably rewrite this with match + .recv().map, it's just ugly the way it's right now.

src/mime.rs Outdated
Comment on lines 46 to 48
fn discriminant(&self) -> u8 {
unsafe { *(self as *const Self as *const u8) }
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tricks like that please. You can do it safely e.g by slapping into Text enum and doing discriminant there.

src/mime.rs Outdated
Comment on lines 71 to 76
allowed
.iter()
.find(|allowed| {
offered_mime_types.iter().any(|offered| offered.as_str() == allowed.as_ref())
})
.cloned()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks kind of less efficient, but I guess you don't have that many mime types, so it's kind of ok?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, I guess it is algorithmically inefficient, but I assumed neither list would be long enough in practice to cause issues.

src/mime.rs Outdated
/// Available mime types for this data
fn available(&self) -> Cow<'static, [MimeType]>;

/// Data as a specific mime_type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description reads really weird.

src/lib.rs Outdated
@@ -8,18 +8,22 @@ use std::ffi::c_void;
use std::io::Result;
use std::sync::mpsc::{self, Receiver};

use mime::{AllowedMimeTypes, AsMimeTypes, MimeType};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local crate exports go below the mod *; this place is reserved for the outsiders.

@wash2
Copy link
Member Author

wash2 commented Feb 28, 2024

We also have CHANGELOG which is here, but no one cares about, even me.

😅 I'll edit the CHANGELOG and address the other comments, thanks.

@wash2
Copy link
Member Author

wash2 commented Mar 1, 2024

Would there be any interest in using the mimes crate? I'm hoping to add support for multiple mime types to window_clipboard and I think it could also probably use the mime crate.

@wash2 wash2 marked this pull request as ready for review March 5, 2024 15:59
@wash2
Copy link
Member Author

wash2 commented Mar 5, 2024

Never mind about the mime crate, I think this is OK.

Cargo.toml Outdated Show resolved Hide resolved
src/dnd/mod.rs Outdated
pub fn end_dnd() {}


}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New line in the end of file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, this file will be part of a separate PR for DnD. So I'll remove it.

src/lib.rs Outdated
Comment on lines 15 to 16
use state::SelectionTarget;
use text::Text;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

below mod

src/lib.rs Outdated
Comment on lines 84 to 102
/// Load raw clipboard data.
///
/// Loads content from a primary clipboard on a last observed seat.
pub fn load_raw(
&self,
allowed: impl Into<Cow<'static, [MimeType]>>,
) -> Result<(Vec<u8>, MimeType)> {
self.load_inner(SelectionTarget::Clipboard, allowed)
}

/// Load raw primary clipboard data.
///
/// Loads content from a primary clipboard on a last observed seat.
pub fn load_primary_raw(
&self,
allowed: impl Into<Cow<'static, [MimeType]>>,
) -> Result<(Vec<u8>, MimeType)> {
self.load_inner(SelectionTarget::Primary, allowed)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use case for raw?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it useful to have an option without trait bounds on the return type, when passing around a boxed trait object clipboard. I still use the AllowedMimeTypes trait, but not in the return type trait for the clipboard because Boxing it in a return type doesn't seem to be object safe.

Copy link
Member Author

@wash2 wash2 Mar 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the trait were allowed to take an optional reference to self like below, the raw methods could be avoided, but the api would probably need to include an argument Option<&(impl AllowedMimeTypes + 'static)>. This way users could create their own type type implementing AllowedMimeTypes which just wraps the received raw data and the allowed mime types.

/// Describes the mime types which are accepted.
pub trait AllowedMimeTypes: TryFrom<(Vec<u8>, MimeType)> {
    /// List allowed mime types for the type to convert from a byte slice.
    ///
    /// Allowed mime types should be listed in order of decreasing preference,
    /// most preferred first.
    fn allowed(_self: Option<&self>) -> Cow<'static, [MimeType]>;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored the methods a bit so they are just allowing a specific mime type to be requested instead.

src/mime.rs Outdated
Comment on lines 78 to 83
fn discriminant(&self) -> usize {
match self {
MimeType::Text(t) => *t as usize,
MimeType::Other(_) => 3,
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is error prone and should be removed all together.

src/mime.rs Outdated
fn as_ref(&self) -> &str {
match self {
MimeType::Other(s) => s.as_ref(),
m => ALLOWED_TEXT_MIME_TYPES[m.discriminant()],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use MimeType::Text(text) and index with text right away.

src/mime.rs Outdated
}

fallback
pub fn find_allowed(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should likely be pub(crate) now.

@wash2 wash2 mentioned this pull request Mar 25, 2024
Draft
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants