WGID4LS4EISIOXB5Y5SOFGEF5PLBJSCPFCETH2CGRTFN3NC4WGJQC 6YZAVBWU6E5FYOI5JGEIPXGZLIKAW6LS2AOFIQWEE5DMOPPCD5PQC KLR5FRIBS6UOH3S3XAOE22TJACVSVOY7TOLW22DIWNGY27S6WZRAC WT3GA27PQ2AOAIGK65O3Q4DMX4AZDVNULBLRL6GF4QW6QCASUEAAC UB2ITZJSDADVINSQEZ3HA6PVGA7OA6JYFG5GMSO7Y7LOXJC4FI7AC YBJRDOTCX3ZRDB5EVXJBR55FX3CADCSIGMYWNYVC2PD5W3GXR3DQC 2VUX5BTDKHX3TJ677NW34H5WLSWH35C3PU46C7MXCN5O7PAZVXNQC A5YBC77VWH2LXCZJOPZORQJI5ZYABSCHJWVX5HVNWPM5RABXESLQC Z2CJPWZECB4PH6DI6Q2DEZIZJ3E2C3IXR3FGBXOLGAP6NVEX2ZDAC AMPZ2BXK4IGUZO3OPBRSJ6Z4GI5K4PRFMLUGTR6AP4FKKRWQG7LQC V55EAIWQXWER2HWKZHPJBV7DDJMSPSPWSO3FSSAYODJHVDBHUN6QC 6SW7UVSHRWJYE2PWVXULTUGEGD432T775EX6EKVEFRO3MDVVAG3AC B4RMW5AEGAJX5CFC4RFPI6Y3NBSDM7GZKNBPPTTICRZSDZSYNXHQC ZVI4AWERNOTDJ3765HJXRBZT57XPNKVONQ6TGOGNPOL2VN42KMJQC OQ6HSAWHIRTAIIWMDGCTIOK47JDY7QVVAHLRDA2R5TTJKNSBFCWQC NWJD6VM6POMYKQTTPP3X6LVCWU3FHLDRIHMCSC2PPUT7JWNY42LAC 4ELJZGRJNL6FXB33QTYDNPY57JA3WZPUXKLQRTGSLDM7W65PD3YQC HC7ROIBC66IBYFED4ZZM7RXGSNC2CCBWBI36RKM2G5FD5DKVEYMQC CALXOZXANFZ64NBZBTR2KYTZ6ZLLCJXNFAEALBB2EYAVDVJJ6X6AC L6KSEFQIWICZJ6HJUFKLZQDEH6X2QMFM4Z7ZZUGMLDMFF7EHRXWAC BFN2VHZS7VCBUHQ4S3CQ3LFQV2V4M6VANNAF32XMRFQVWRGYSZ6AC 3SYSJKYLVCXR54LRUPL6GOQISSJS6XWK4M6PRQRCKZN7F23NNVEAC 23SFYK4Q5NKBPJG53PQNPWQH6UOUU2YKJEL7RLXYBRLJOJYV7AWQC MYGIBRRHHXPKVRAMQQRJTZH74L2XOK3SF7J57JPCRKSVRLZ2D6NQC //! A drop-in replacement for [`iced::Task`] that allows for easy evaluation for//! testing.mod wrappers;pub use wrappers::*;#[cfg(not(test))]pub use iced::Task;#[cfg(test)]pub struct Task<T> {stream: Option<iced::futures::stream::BoxStream<'static, T>>,}#[cfg(test)]pub async fn await_next_result<T>(tasks: &mut Task<T>) -> Option<T> {let Task { stream } = tasks;if let Some(stream) = stream.as_mut() {if let Some(msg) = iced::futures::stream::StreamExt::next(stream).await{return Some(msg);}}None}#[cfg(test)]impl<T> Task<T> {pub fn none() -> Self {Self { stream: None }}pub fn done(value: T) -> Task<T>whereT: Send + 'static,{Self::future(iced::futures::future::ready(value))}pub fn perform<A>(future: impl Future<Output = A> + Send + 'static,f: impl FnOnce(A) -> T + Send + 'static,) -> SelfwhereT: Send + 'static,A: Send + 'static,{Self::future(iced::futures::FutureExt::map(future, f))}pub fn run<A>(stream: impl iced::futures::stream::Stream<Item = A> + Send + 'static,f: impl Fn(A) -> T + Send + 'static,) -> SelfwhereT: 'static,{Self::stream(iced::futures::stream::StreamExt::map(stream, f))}pub fn batch(tasks: impl IntoIterator<Item = Self>) -> SelfwhereT: 'static,{let mut select_all = iced::futures::stream::SelectAll::new();for task in tasks.into_iter() {if let Some(stream) = task.stream {select_all.push(stream);}}Self {stream: Some(iced::futures::stream::StreamExt::boxed(select_all)),}}pub fn map<O>(self, mut f: impl FnMut(T) -> O + Send + 'static) -> Task<O>whereT: Send + 'static,O: Send + 'static,{self.then(move |output| Task::done(f(output)))}pub fn then<O>(self,mut f: impl FnMut(T) -> Task<O> + Send + 'static,) -> Task<O>whereT: Send + 'static,O: Send + 'static,{Task {stream: match self.stream {None => None,Some(stream) => Some(iced::futures::stream::StreamExt::boxed(iced::futures::stream::StreamExt::flat_map(stream,move |output| {f(output).stream.unwrap_or_else(|| {iced::futures::stream::StreamExt::boxed(iced::futures::stream::empty(),)})},),)),},}}pub fn future(future: impl Future<Output = T> + Send + 'static) -> SelfwhereT: 'static,{Self::stream(iced::futures::stream::once(future))}pub fn stream(stream: impl iced::futures::stream::Stream<Item = T> + Send + 'static,) -> SelfwhereT: 'static,{Self {stream: Some(iced::futures::stream::StreamExt::boxed(stream)),}}}#[cfg(test)]mod test {use super::*;#[tokio::test]async fn test_run_task() {let mut task = Task::done(123_usize);let result = await_next_result(&mut task).await;assert_eq!(result, Some(123_usize))}}
//! Wrappers for iced tasks to allow testing.use std::path::PathBuf;use super::Task;use iced::window;/// Opens a new window with the given [`Settings`]; producing the [`Id`]/// of the new window on completion.pub fn open_window(settings: window::Settings,) -> (window::Id, Task<window::Id>) {#[cfg(not(test))]let (window_id, task) = window::open(settings);#[cfg(test)]let (window_id, task) = {let _ = settings;let id = window::Id::unique();(id, Task::done(id))};(window_id, task)}/// Changes the icon of the window using an icon from the content of an image/// file at the given path.pub fn window_set_icon<T>(window_id: window::Id, path: PathBuf) -> Task<T>whereT: Send + 'static,{#[cfg(not(test))]let set_icon_task = Task::perform(async move {use iced::advanced::graphics::image::image_rs::ImageFormat;let icon_bytes = tokio::fs::read(path).await.unwrap();window::icon::from_file_data(&icon_bytes, Some(ImageFormat::Png)).unwrap()},|msg| msg,).then(move |icon| window::set_icon(window_id, icon));#[cfg(test)]let set_icon_task = {let _ = (window_id, path);Task::none()};set_icon_task}/// Focuses the next focusable widget.pub fn widget_focus_next<T>() -> Task<T> {#[cfg(not(test))]let task = iced::widget::focus_next();#[cfg(test)]let task = Task::none();task}
window::open(window::Settings::default());let set_icon_task = Task::perform(async {use iced::advanced::graphics::image::image_rs::ImageFormat;let icon_bytes = fs::read("assets/icon.png").await.unwrap();window::icon::from_file_data(&icon_bytes, Some(ImageFormat::Png)).unwrap()},|msg| msg,).then(move |icon| window::set_icon(window_id, icon));
task::open_window(window::Settings::default());let set_icon_task =// TODO: `include_bytes!`?task::window_set_icon(window_id, PathBuf::from("assets/icon.png"));
[dev-dependencies][dev-dependencies.tokio]workspace = truefeatures = ["macros"]