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

image: Allow any kind of data that implements AsRef<[u8]> for the i… #1551

Merged
merged 2 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/pokedex/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl Pokemon {
{
let bytes = reqwest::get(&url).await?.bytes().await?;

Ok(image::Handle::from_memory(bytes.as_ref().to_vec()))
Ok(image::Handle::from_memory(bytes))
hecrj marked this conversation as resolved.
Show resolved Hide resolved
}

#[cfg(target_arch = "wasm32")]
Expand Down
58 changes: 49 additions & 9 deletions native/src/image.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Load and draw raster graphics.
use crate::{Hasher, Rectangle, Size};

use std::borrow::Cow;
use std::hash::{Hash, Hasher as _};
use std::path::PathBuf;
use std::sync::Arc;
Expand All @@ -10,7 +9,7 @@ use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct Handle {
id: u64,
data: Arc<Data>,
data: Data,
}

impl Handle {
Expand All @@ -29,12 +28,12 @@ impl Handle {
pub fn from_pixels(
width: u32,
height: u32,
pixels: impl Into<Cow<'static, [u8]>>,
pixels: impl AsRef<[u8]> + Clone + Send + Sync + 'static,
) -> Handle {
Self::from_data(Data::Rgba {
width,
height,
pixels: pixels.into(),
pixels: Bytes::new(pixels),
})
}

Expand All @@ -44,8 +43,10 @@ impl Handle {
///
/// This is useful if you already have your image loaded in-memory, maybe
/// because you downloaded or generated it procedurally.
pub fn from_memory(bytes: impl Into<Cow<'static, [u8]>>) -> Handle {
Self::from_data(Data::Bytes(bytes.into()))
pub fn from_memory(
bytes: impl AsRef<[u8]> + Clone + Send + Sync + 'static,
) -> Handle {
Self::from_data(Data::Bytes(Bytes::new(bytes)))
}

fn from_data(data: Data) -> Handle {
Expand All @@ -54,7 +55,7 @@ impl Handle {

Handle {
id: hasher.finish(),
data: Arc::new(data),
data,
}
}

Expand Down Expand Up @@ -84,14 +85,53 @@ impl Hash for Handle {
}
}

/// A wrapper around raw image data.
///
/// It behaves like a `&[u8]`.
#[derive(Clone)]
pub struct Bytes(Arc<dyn AsRef<[u8]> + Send + Sync + 'static>);

impl Bytes {
/// Creates new [`Bytes`] around `data`.
pub fn new(data: impl AsRef<[u8]> + Clone + Send + Sync + 'static) -> Self {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You don't really need the Clone here anymore as the Arc already gives you that :)
Do you want me to submit a PR for removing the trait bound or will you take care of the change?

Copy link
Member

Choose a reason for hiding this comment

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

Good catch. Just opened #1717.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

Self(Arc::new(data))
}
}

impl std::fmt::Debug for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.as_ref().as_ref().fmt(f)
}
}

impl std::hash::Hash for Bytes {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_ref().as_ref().hash(state);
}
}

impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref().as_ref()
}
}

impl std::ops::Deref for Bytes {
type Target = [u8];

fn deref(&self) -> &[u8] {
self.0.as_ref().as_ref()
}
}

/// The data of a raster image.
#[derive(Clone, Hash)]
pub enum Data {
/// File data
Path(PathBuf),

/// In-memory data
Bytes(Cow<'static, [u8]>),
Bytes(Bytes),

/// Decoded image pixels in RGBA format.
Rgba {
Expand All @@ -100,7 +140,7 @@ pub enum Data {
/// The height of the image.
height: u32,
/// The pixels.
pixels: Cow<'static, [u8]>,
pixels: Bytes,
},
}

Expand Down