refactor: use Cow<str> for errors

since some errors are just string literals;
this lets us avoid allocating a new string
This commit is contained in:
electria 2026-08-25 09:37:00 -07:00
commit 95a24fa987
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs
2 changed files with 21 additions and 18 deletions

View file

@ -33,9 +33,9 @@ enum Message {
FocusNext, FocusNext,
FocusPrevious, FocusPrevious,
ImagePicked(Result<PathBuf, String>), ImagePicked(Result<PathBuf, Cow<'static, str>>),
ImageDisplayReady(Result<widget::image::Allocation, widget::image::Error>), ImageDisplayReady(Result<widget::image::Allocation, widget::image::Error>),
SavePathPicked(Result<PathBuf, String>), SavePathPicked(Result<PathBuf, Cow<'static, str>>),
FileDropped(PathBuf), FileDropped(PathBuf),
} }
@ -46,7 +46,7 @@ struct State {
image_display: Option<widget::image::Allocation>, image_display: Option<widget::image::Allocation>,
image_filter: widget::image::FilterMethod, image_filter: widget::image::FilterMethod,
error: Option<String>, error: Option<Cow<'static, str>>,
info: Option<String>, info: Option<String>,
infobar_shown: bool, infobar_shown: bool,
@ -58,7 +58,7 @@ impl State {
if let Some(path) = env::args().nth(1) { if let Some(path) = env::args().nth(1) {
match state.load_image(path) { match state.load_image(path) {
Err(e) => state.error = Some(e), Err(e) => state.error = Some(e.into()),
Ok(task) => return (state, task), Ok(task) => return (state, task),
} }
} }
@ -108,22 +108,25 @@ impl State {
} }
fn update(&mut self, message: Message) -> Task<Message> { fn update(&mut self, message: Message) -> Task<Message> {
match message { match message {
Message::ImagePicked(result) => match result.and_then(|path| self.load_image(path)) { Message::ImagePicked(result) => {
Err(e) => self.error = Some(e), match result.and_then(|path| self.load_image(path).map_err(Cow::from)) {
Ok(task) => { Err(e) => self.error = Some(e.into()),
self.error = None; Ok(task) => {
return task; self.error = None;
return task;
}
} }
}, }
Message::ImageDisplayReady(result) => { Message::ImageDisplayReady(result) => {
self.image_display = Some(result.unwrap()); self.image_display = Some(result.unwrap());
} }
Message::SavePathPicked(result) => { Message::SavePathPicked(result) => {
self.error = result self.error = result
.map_err(Cow::from)
.and_then(|path| { .and_then(|path| {
self.image.as_ref().map_or_else( self.image.as_ref().map_or_else(
|| Err("no image to save".into()), || Err("no image to save".into()),
|image| image.save(path).map_err(|e| e.to_string()), |image| image.save(path).map_err(|e| e.to_string().into()),
) )
}) })
.err(); .err();
@ -181,11 +184,11 @@ impl State {
Ok(mut clipboard) => { Ok(mut clipboard) => {
self.error = clipboard self.error = clipboard
.set_image(utils::arboard_from_rgbaimage(image)) .set_image(utils::arboard_from_rgbaimage(image))
.map_err(|e| e.to_string()) .map_err(|e| e.to_string().into())
.err(); .err();
self.clipboard = Some(clipboard); self.clipboard = Some(clipboard);
} }
Err(e) => self.error = Some(e.to_string()), Err(e) => self.error = Some(e.to_string().into()),
} }
} else { } else {
self.error = Some("no image to yank".into()); self.error = Some("no image to yank".into());
@ -199,7 +202,7 @@ impl State {
Ok(mut clipboard) => { Ok(mut clipboard) => {
let result = clipboard.get_image().map(utils::rgbaimage_from_arboard); let result = clipboard.get_image().map(utils::rgbaimage_from_arboard);
self.error = result.as_ref().map_err(|e| e.to_string()).err(); self.error = result.as_ref().map_err(|e| e.to_string().into()).err();
self.clipboard = Some(clipboard); self.clipboard = Some(clipboard);
if let Ok(image) = result { if let Ok(image) = result {
@ -211,7 +214,7 @@ impl State {
return self.allocate_image(); return self.allocate_image();
} }
} }
Err(e) => self.error = Some(e.to_string()), Err(e) => self.error = Some(e.to_string().into()),
} }
} }
@ -220,7 +223,7 @@ impl State {
self.error = None; self.error = None;
return task; return task;
} }
Err(e) => self.error = Some(e), Err(e) => self.error = Some(e.into()),
}, },
} }

View file

@ -34,7 +34,7 @@ fn load_image_impl(path: impl AsRef<Path>) -> ImageResult<RgbaImage> {
Ok(decoded_image.into_rgba8()) Ok(decoded_image.into_rgba8())
} }
pub async fn pick_image() -> Result<PathBuf, String> { pub async fn pick_image() -> Result<PathBuf, Cow<'static, str>> {
let Some(filehandle) = AsyncFileDialog::new() let Some(filehandle) = AsyncFileDialog::new()
.add_filter( .add_filter(
"image", "image",
@ -52,7 +52,7 @@ pub async fn pick_image() -> Result<PathBuf, String> {
Ok(filehandle.path().to_owned()) Ok(filehandle.path().to_owned())
} }
pub async fn pick_save_path() -> Result<PathBuf, String> { pub async fn pick_save_path() -> Result<PathBuf, Cow<'static, str>> {
let Some(filehandle) = AsyncFileDialog::new().save_file().await else { let Some(filehandle) = AsyncFileDialog::new().save_file().await else {
return Err("no path to save provided".into()); return Err("no path to save provided".into());
}; };