From f4e8f7c276f37ee68d89a9a3cb2f293f6563400c Mon Sep 17 00:00:00 2001 From: Breval Ferrari Date: Fri, 14 Mar 2025 22:53:16 -0400 Subject: [PATCH] relax trait requirements, rename failable methods with 'try' --- bingus/Cargo.toml | 1 + bingus/src/bin_/bytes.rs | 8 +++- bingus/src/img/image.rs | 95 +++++++++++++++++++++++++++++-------- bingus/src/lib.rs | 42 ++++++++++++---- bingus/src/snd.rs | 1 + bingus/src/snd/raw.rs | 4 +- bingus/src/snd/simphonia.rs | 42 ++++++++++++++++ bong/Cargo.toml | 3 +- 8 files changed, 163 insertions(+), 33 deletions(-) create mode 100644 bingus/src/snd/simphonia.rs diff --git a/bingus/Cargo.toml b/bingus/Cargo.toml index ce8eaa3..4dab652 100644 --- a/bingus/Cargo.toml +++ b/bingus/Cargo.toml @@ -19,3 +19,4 @@ derive-new = "0.7" strum = { version = "0.26", features = ["derive"] } dasp_sample = "0.11.0" derive_wrapper = "0.1" +symphonia = { version = "0.5.4", features = ["all"] } diff --git a/bingus/src/bin_/bytes.rs b/bingus/src/bin_/bytes.rs index c286c06..bdcc719 100644 --- a/bingus/src/bin_/bytes.rs +++ b/bingus/src/bin_/bytes.rs @@ -5,7 +5,7 @@ use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use crate::{Bendable, Bytes, IntoDataBytes, TryFromDataBytes}; impl IntoDataBytes for Bytes { - fn into_bytes(self) -> Bytes { + fn into_data_bytes(self) -> Bytes { self } } @@ -13,7 +13,11 @@ impl IntoDataBytes for Bytes { impl TryFromDataBytes for Bytes { type Error = Infallible; type Format = (); - fn try_from_bytes(bytes: Bytes, _: Self::Format, _: crate::Crop) -> Result + fn try_from_data_bytes( + bytes: Bytes, + _: Self::Format, + _: crate::Crop, + ) -> Result where Self: Sized, { diff --git a/bingus/src/img/image.rs b/bingus/src/img/image.rs index 2fb7f6d..8d647b2 100644 --- a/bingus/src/img/image.rs +++ b/bingus/src/img/image.rs @@ -1,4 +1,7 @@ -use std::ops::{Deref, DerefMut}; +use std::{ + convert::Infallible, + ops::{Deref, DerefMut}, +}; pub use image::*; use num::{ @@ -6,15 +9,16 @@ use num::{ Zero, }; use rayon::iter::ParallelIterator; +use thiserror::Error; -use crate::{Bendable, IntoDataBytes, TryFromDataBytes}; +use crate::{Bendable, Format, FromDataBytes, IntoDataBytes, TryFromDataBytes}; impl IntoDataBytes for ImageBuffer> where Vec: Deref, P::Subpixel: ToBytes, { - fn into_bytes(self) -> crate::Bytes { + fn into_data_bytes(self) -> crate::Bytes { self.iter() .flat_map(|subpixel| subpixel.to_ne_bytes().as_ref().to_vec()) .collect() @@ -32,9 +36,9 @@ where P::Subpixel: ToBytes + FromBytes, ::Bytes: for<'a> TryFrom<&'a [u8]>, { - type Error = (); + type Error = Infallible; type Format = Dimensions; - fn try_from_bytes( + fn try_from_data_bytes( bytes: crate::Bytes, format: Self::Format, crop: crate::Crop, @@ -70,7 +74,7 @@ where .collect::>(), }, ) - .ok_or(()) + .ok_or_else(|| unreachable!()) } } @@ -87,16 +91,67 @@ where self } fn format() -> crate::Format { - crate::Format::Image + Format::Image } } impl IntoDataBytes for DynamicImage { - fn into_bytes(self) -> crate::Bytes { + fn into_data_bytes(self) -> crate::Bytes { self.into_bytes() } } +#[derive(Debug, Error)] +#[error("this color type is not supported yet... sorry")] +pub struct UnsupportedColorType; + +impl TryFromDataBytes for DynamicImage { + type Format = (Dimensions, ColorType); + type Error = UnsupportedColorType; + fn try_from_data_bytes( + bytes: crate::Bytes, + format: Self::Format, + crop: crate::Crop, + ) -> Result + where + Self: Sized, + { + match format.1 { + ColorType::L8 => Ok(DynamicImage::ImageLuma8(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::La8 => Ok(DynamicImage::ImageLumaA8(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgb8 => Ok(DynamicImage::ImageRgb8(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgba8 => Ok(DynamicImage::ImageRgba8(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::L16 => Ok(DynamicImage::ImageLuma16(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::La16 => Ok(DynamicImage::ImageLumaA16(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgb16 => Ok(DynamicImage::ImageRgb16(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgba16 => Ok(DynamicImage::ImageRgba16(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgb32F => Ok(DynamicImage::ImageRgb32F(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + ColorType::Rgba32F => Ok(DynamicImage::ImageRgba32F(ImageBuffer::from_data_bytes( + bytes, format.0, crop, + ))), + _ => Err(UnsupportedColorType), + } + } +} + #[cfg(test)] mod tests { #[cfg(test)] @@ -111,8 +166,8 @@ mod tests { let image = RgbImage::new(0, 0); assert_eq!( Ok(image.clone()), - RgbImage::try_from_bytes( - image.into_bytes(), + RgbImage::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 0, height: 0 @@ -127,8 +182,8 @@ mod tests { let image = RgbImage::from_raw(3, 1, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).unwrap(); assert_eq!( Ok(image.clone()), - RgbImage::try_from_bytes( - image.into_bytes(), + RgbImage::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 3, height: 1 @@ -144,8 +199,8 @@ mod tests { RgbaImage::from_raw(3, 1, vec![1, 2, 3, 0, 4, 5, 6, 1, 7, 8, 9, 2]).unwrap(); assert_eq!( Ok(image.clone()), - RgbaImage::try_from_bytes( - image.into_bytes(), + RgbaImage::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 3, height: 1 @@ -165,8 +220,8 @@ mod tests { .unwrap(); assert_eq!( Ok(image.clone()), - ImageBuffer::, Vec>::try_from_bytes( - image.into_bytes(), + ImageBuffer::, Vec>::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 3, height: 1 @@ -186,8 +241,8 @@ mod tests { .unwrap(); assert_eq!( Ok(image.clone()), - ImageBuffer::, Vec>::try_from_bytes( - image.into_bytes(), + ImageBuffer::, Vec>::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 3, height: 1 @@ -207,8 +262,8 @@ mod tests { .unwrap(); assert_eq!( Ok(image.clone()), - Rgb32FImage::try_from_bytes( - image.into_bytes(), + Rgb32FImage::try_from_data_bytes( + image.into_data_bytes(), Dimensions { width: 3, height: 1 diff --git a/bingus/src/lib.rs b/bingus/src/lib.rs index d8d0a47..4ce202a 100644 --- a/bingus/src/lib.rs +++ b/bingus/src/lib.rs @@ -5,7 +5,7 @@ pub mod txt; pub(crate) type Bytes = Vec; -pub mod dynamic { +mod dynamic { use std::{ fs::File, io::{self, Read}, @@ -64,30 +64,32 @@ pub mod dynamic { } } -use dynamic::*; +use std::convert::Infallible; + +pub use dynamic::*; pub trait Bendable: TryFromDataBytes + IntoDataBytes { type Unit; - fn bend_into( + fn bend_into( self, format: ::Format, crop: Crop, ) -> Result::Error> { - T::bend_from(self, format, crop) + T::try_from_data_bytes(self.into_data_bytes(), format, crop) } - fn bend_from( + fn bend_from( b: T, format: ::Format, crop: Crop, ) -> Result::Error> { - Self::try_from_bytes(b.into_bytes(), format, crop) + Self::try_from_data_bytes(b.into_data_bytes(), format, crop) } fn map Self::Unit + Sync>(self, f: F) -> Self; fn format() -> Format; } pub trait IntoDataBytes: Sized { - fn into_bytes(self) -> Bytes; + fn into_data_bytes(self) -> Bytes; } #[derive(Default)] @@ -100,7 +102,31 @@ pub enum Crop { pub trait TryFromDataBytes { type Error; type Format; - fn try_from_bytes(bytes: Bytes, format: Self::Format, crop: Crop) -> Result + fn try_from_data_bytes( + bytes: Bytes, + format: Self::Format, + crop: Crop, + ) -> Result where Self: Sized; } + +pub trait FromDataBytes { + type Format; + fn from_data_bytes(bytes: Bytes, format: Self::Format, crop: Crop) -> Self + where + Self: Sized; +} + +impl FromDataBytes for T +where + T: TryFromDataBytes, +{ + type Format = ::Format; + fn from_data_bytes(bytes: Bytes, format: Self::Format, crop: Crop) -> Self + where + Self: Sized, + { + T::try_from_data_bytes(bytes, format, crop).unwrap_or_else(|_| unreachable!()) + } +} diff --git a/bingus/src/snd.rs b/bingus/src/snd.rs index 18a8a0f..57cd0d3 100644 --- a/bingus/src/snd.rs +++ b/bingus/src/snd.rs @@ -1,3 +1,4 @@ pub use dasp_sample::Sample; mod raw; pub use raw::RawSamples; +mod simphonia; diff --git a/bingus/src/snd/raw.rs b/bingus/src/snd/raw.rs index b4309d3..6b0bfb0 100644 --- a/bingus/src/snd/raw.rs +++ b/bingus/src/snd/raw.rs @@ -17,7 +17,7 @@ impl IntoDataBytes for RawSamples where T: Sample + ToBytes, { - fn into_bytes(self) -> crate::Bytes { + fn into_data_bytes(self) -> crate::Bytes { self.as_ref() .iter() .flat_map(|subpixel| subpixel.to_ne_bytes().as_ref().to_vec()) @@ -32,7 +32,7 @@ where { type Error = (); type Format = (); - fn try_from_bytes( + fn try_from_data_bytes( bytes: crate::Bytes, _format: Self::Format, crop: crate::Crop, diff --git a/bingus/src/snd/simphonia.rs b/bingus/src/snd/simphonia.rs new file mode 100644 index 0000000..a9d24af --- /dev/null +++ b/bingus/src/snd/simphonia.rs @@ -0,0 +1,42 @@ +use std::io; + +use symphonia::{ + core::{ + audio::{RawSample, RawSampleBuffer}, + io::MediaSourceStream, + probe::Hint, + sample::Sample, + }, + default, +}; + +use crate::TryFromDataBytes; + +pub struct Audio(RawSampleBuffer) +where + S: Sample + RawSample; + +impl TryFromDataBytes for Audio +where + S: Sample + RawSample, +{ + type Error = symphonia::core::errors::Error; + type Format = Hint; + fn try_from_data_bytes( + bytes: crate::Bytes, + format: Self::Format, + crop: crate::Crop, + ) -> Result + where + Self: Sized, + { + let registry = default::get_codecs(); + let probe = default::get_probe(); + let mediasource = io::Cursor::new(bytes); + let mss = MediaSourceStream::new(Box::new(mediasource), Default::default()); + let reader = probe + .format(&format, mss, &Default::default(), &Default::default())? + .format; + todo!() + } +} diff --git a/bong/Cargo.toml b/bong/Cargo.toml index c739bb9..59d66eb 100644 --- a/bong/Cargo.toml +++ b/bong/Cargo.toml @@ -7,8 +7,9 @@ description.workspace = true authors.workspace = true repository.workspace = true keywords.workspace = true -dependencies.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bingus = { path = "../bingus" } +clap = { version = "4.5.32", features = ["derive"] }