1#[cfg(feature = "serde")]
2use crate::as_valuable::AsValuable;
3#[cfg(feature = "fmt")]
4use crate::fmt::{Debugged, OptionalDisplay};
5#[cfg(feature = "tui")]
6use crate::geometry::Orientation;
7#[cfg(feature = "ropey")]
8use crate::geometry::PointUsize;
9use crate::is::Is;
10#[cfg(feature = "output")]
11use crate::output::Output;
12#[cfg(feature = "process")]
13use crate::process::ProcessBuilder;
14#[cfg(feature = "ropey")]
15use crate::rope_builder::RopeBuilder;
16#[cfg(feature = "tui")]
17use crate::scrollable::{ScrollCount, ScrollWhen, Scrollable};
18#[cfg(any(feature = "serde", feature = "tui"))]
19use crate::seq_visitor::SeqVisitor;
20#[cfg(feature = "socket")]
21use crate::socket::{Request, Socket};
22#[cfg(feature = "tracing")]
23use crate::status::Status;
24#[cfg(any(feature = "ropey", feature = "tui"))]
25use crate::transpose::Transpose;
26#[cfg(feature = "async")]
27use crate::{into_stream::IntoStream, read_value::ReadValue, run_for::RunForError};
28#[cfg(any(
29 feature = "async",
30 feature = "fs",
31 feature = "process",
32 feature = "reqwest",
33 feature = "socket",
34 feature = "tui",
35))]
36use anyhow::{Context, Error as AnyhowError};
37#[cfg(feature = "async")]
38use bytes::Buf;
39#[cfg(feature = "poem")]
40use bytes::Bytes;
41#[cfg(feature = "fs")]
42use camino::{Utf8Path, Utf8PathBuf};
43#[cfg(any(feature = "async", feature = "poem"))]
44use futures::Stream;
45#[cfg(feature = "async")]
46use futures::{Sink, SinkExt, StreamExt, TryFuture, future::Either, stream::Filter, stream::FuturesUnordered};
47#[cfg(feature = "tui")]
48use num::traits::{SaturatingAdd, SaturatingSub};
49#[cfg(any(feature = "ropey", feature = "misc", feature = "tui"))]
50use num::{Bounded, NumCast, ToPrimitive, Zero};
51#[cfg(feature = "poem")]
52use poem::{Body as PoemBody, Endpoint, IntoResponse, web::websocket::Message as PoemMessage};
53#[cfg(feature = "poem")]
54use poem_openapi::{error::ParseRequestPayloadError, payload::Binary as PoemBinary, payload::Json as PoemJson};
55#[cfg(feature = "tui")]
56use ratatui::{
57 Frame,
58 layout::Rect,
59 text::{Line, Span},
60 widgets::{Block, Widget},
61};
62#[cfg(feature = "reqwest")]
63use reqwest::{RequestBuilder, Response};
64#[cfg(feature = "rmp")]
65use rmp_serde::{decode::Error as RmpDecodeError, encode::Error as RmpEncodeError};
66#[cfg(feature = "ropey")]
67use ropey::{Rope, RopeSlice, iter::Chunks, iter::Lines};
68#[cfg(any(feature = "rmp", feature = "serde", feature = "tui"))]
69use serde::Deserialize;
70#[cfg(any(feature = "serde", feature = "tui"))]
71use serde::Deserializer;
72#[cfg(any(feature = "reqwest", feature = "rmp", feature = "serde"))]
73use serde::Serialize;
74#[cfg(feature = "serde")]
75use serde::de::DeserializeOwned;
76#[cfg(any(feature = "poem", feature = "serde"))]
77use serde_json::Error as SerdeJsonError;
78#[cfg(feature = "serde")]
79use serde_json::{Value as Json, value::Index};
80#[cfg(feature = "serde")]
81use serde_yaml_ng::Error as SerdeYamlError;
82#[cfg(any(
83 feature = "async",
84 feature = "fs",
85 feature = "process",
86 feature = "reqwest",
87 feature = "socket",
88 feature = "tui",
89))]
90use std::fmt::Debug;
91#[cfg(feature = "fs")]
92use std::path::PathBuf;
93#[cfg(feature = "process")]
94use std::process::ExitStatus;
95use std::{
96 borrow::{Borrow, BorrowMut, Cow},
97 collections::HashMap,
98 error::Error as StdError,
99 fmt::Display,
100 fs::File,
101 future::Ready,
102 hash::Hash,
103 io::{BufReader, BufWriter, Error as IoError, Read, Write},
104 iter::{Once, Repeat},
105 mem::ManuallyDrop,
106 ops::{Add, ControlFlow, Range},
107 path::Path,
108 pin::Pin,
109 str::Utf8Error,
110 sync::{
111 Arc,
112 atomic::{AtomicUsize, Ordering},
113 },
114 task::Poll,
115 time::Instant,
116};
117#[cfg(feature = "async")]
118use std::{fs::Metadata, time::Duration};
119#[cfg(any(feature = "async", feature = "process"))]
120use tokio::io::{AsyncReadExt, AsyncWriteExt};
121#[cfg(any(feature = "async", feature = "ropey"))]
122use tokio::{
123 fs::File as TokioFile,
124 io::{AsyncRead, BufReader as TokioBufReader},
125};
126#[cfg(feature = "async")]
127use tokio::{
128 io::{AsyncWrite, BufWriter as TokioBufWriter},
129 sync::oneshot::Sender as OneshotSender,
130 task::JoinHandle,
131 task::{JoinSet, LocalSet},
132 time::{Interval, Sleep, Timeout},
133};
134#[cfg(feature = "async")]
135use tokio_util::{
136 codec::{Framed, LengthDelimitedCodec, LinesCodec},
137 io::StreamReader,
138};
139#[cfg(feature = "tracing")]
140use tracing::Level;
141#[cfg(any(feature = "ropey", feature = "tui"))]
142use unicode_segmentation::{GraphemeIndices, Graphemes, UnicodeSegmentation};
143#[cfg(feature = "serde")]
144use valuable::Value;
145
146#[allow(async_fn_in_trait)]
147pub trait Utils {
148 const DEFAULT_ROPE_BUILDER_BUFFER_SIZE: usize = 8192;
149 const IS_EXTENDED: bool = true;
150 const NEWLINE: &str = "\n";
151 const READ_FROM_CLIPBOARD_COMMAND: &str = "pbpaste";
152 const WRITE_TO_CLIPBOARD_COMMAND: &str = "pbcopy";
153
154 #[cfg(feature = "async")]
155 async fn abort_all_and_wait<T: 'static>(&mut self)
156 where
157 Self: BorrowMut<JoinSet<T>>,
158 {
159 let join_set = self.borrow_mut();
160
161 join_set.abort_all();
162
163 while join_set.join_next().await.is_some() {}
164 }
165
166 #[cfg(feature = "fs")]
167 fn absolute_utf8(&self) -> Result<Cow<'_, Utf8Path>, IoError>
168 where
169 Self: AsRef<Utf8Path>,
170 {
171 let path = self.as_ref();
172
173 if path.is_absolute() {
174 path.borrowed().ok()
175 } else {
176 camino::absolute_utf8(path)?.owned::<Utf8Path>().ok()
177 }
178 }
179
180 async fn achain<T: Future>(self, rhs: T) -> T::Output
181 where
182 Self: Future + Sized,
183 {
184 self.await;
185
186 rhs.await
187 }
188
189 #[cfg(feature = "tui")]
190 fn add_span<'a, T: Into<Span<'a>>>(self, span: T) -> Line<'a>
191 where
192 Self: Into<Line<'a>>,
193 {
194 let mut line = self.into();
195
196 line.spans.push(span.into());
197
198 line
199 }
200
201 #[cfg(any(
202 feature = "async",
203 feature = "fs",
204 feature = "process",
205 feature = "reqwest",
206 feature = "socket",
207 feature = "tui",
208 ))]
209 fn anyhow_msg_error(self) -> AnyhowError
210 where
211 Self: 'static + Debug + Display + Send + Sized + Sync,
212 {
213 AnyhowError::msg(self)
214 }
215
216 #[cfg(any(
217 feature = "async",
218 feature = "fs",
219 feature = "process",
220 feature = "reqwest",
221 feature = "socket",
222 feature = "tui",
223 ))]
224 fn anyhow_error(self) -> AnyhowError
225 where
226 Self: Into<AnyhowError>,
227 {
228 self.into()
229 }
230
231 #[cfg(any(
232 feature = "async",
233 feature = "fs",
234 feature = "process",
235 feature = "reqwest",
236 feature = "socket",
237 feature = "tui",
238 ))]
239 fn anyhow_result<T, E: Into<AnyhowError>>(self) -> Result<T, AnyhowError>
240 where
241 Self: Is<Result<T, E>>,
242 {
243 self.into_self().map_err(E::into)
244 }
245
246 fn arc(self) -> Arc<Self>
247 where
248 Self: Sized,
249 {
250 Arc::new(self)
251 }
252
253 async fn async_with<T>(self, next: impl Future<Output = T>) -> T
254 where
255 Self: Future + Sized,
256 {
257 self.await;
258
259 next.await
260 }
261
262 fn as_borrowed<'a, B: ?Sized + ToOwned>(&'a self) -> &'a B
263 where
264 Self: Borrow<Cow<'a, B>>,
265 {
266 self.borrow().borrow()
267 }
268
269 fn as_immut(&mut self) -> &Self {
270 &*self
271 }
272
273 fn as_ptr(&self) -> *const Self {
274 std::ptr::from_ref(self)
275 }
276
277 fn as_ptr_mut(&mut self) -> *mut Self {
278 std::ptr::from_mut(self)
279 }
280
281 fn as_utf8(&self) -> Result<&str, Utf8Error>
282 where
283 Self: AsRef<[u8]>,
284 {
285 std::str::from_utf8(self.as_ref())
286 }
287
288 #[cfg(feature = "fs")]
289 fn as_utf8_path(&self) -> &Utf8Path
290 where
291 Self: AsRef<Utf8Path>,
292 {
293 self.as_ref()
294 }
295
296 #[cfg(feature = "ropey")]
297 fn as_slice(&self) -> RopeSlice<'_>
298 where
299 Self: Borrow<Rope>,
300 {
301 self.borrow().slice(..)
302 }
303
304 #[cfg(feature = "serde")]
305 fn as_valuable(&self) -> Value<'_>
306 where
307 Self: AsValuable,
308 {
309 AsValuable::as_valuable(self)
310 }
311
312 #[cfg(feature = "tui")]
313 fn bordered_block<'a>(self) -> Block<'a>
314 where
315 Self: Into<Line<'a>> + Sized,
316 {
317 Block::bordered().title(self)
318 }
319
320 fn borrowed(&self) -> Cow<'_, Self>
321 where
322 Self: ToOwned,
323 {
324 Cow::Borrowed(self)
325 }
326
327 fn buf_reader(self) -> BufReader<Self>
328 where
329 Self: Read + Sized,
330 {
331 BufReader::new(self)
332 }
333
334 #[cfg(any(feature = "async", feature = "ropey"))]
335 fn buf_reader_async(self) -> TokioBufReader<Self>
336 where
337 Self: AsyncRead + Sized,
338 {
339 TokioBufReader::new(self)
340 }
341
342 fn buf_writer(self) -> BufWriter<Self>
343 where
344 Self: Write + Sized,
345 {
346 BufWriter::new(self)
347 }
348
349 #[cfg(feature = "async")]
350 fn buf_writer_async(self) -> TokioBufWriter<Self>
351 where
352 Self: AsyncWrite + Sized,
353 {
354 TokioBufWriter::new(self)
355 }
356
357 #[cfg(any(feature = "ropey", feature = "misc", feature = "tui"))]
358 fn cast_or_max<T: Bounded + NumCast>(self) -> T
359 where
360 Self: Sized + ToPrimitive,
361 {
362 match T::from(self) {
363 Some(value) => value,
364 None => T::max_value(),
365 }
366 }
367
368 fn cast_ref<T>(&self) -> &T {
371 let ptr = std::ptr::from_ref(self).cast::<T>();
372 let value = unsafe { ptr.as_ref() };
373
374 value.unwrap()
375 }
376
377 fn cat<T: Display>(&self, rhs: T) -> String
378 where
379 Self: Display,
380 {
381 std::format!("{self}{rhs}")
382 }
383
384 #[cfg(any(
385 feature = "async",
386 feature = "fs",
387 feature = "process",
388 feature = "reqwest",
389 feature = "socket",
390 feature = "tui",
391 ))]
392 fn check_next<T>(self) -> Result<T, AnyhowError>
393 where
394 Self: Is<Option<T>>,
395 {
396 match self.into_self() {
397 Some(item) => item.ok(),
398 None => anyhow::bail!(
399 "sequence of {type_name} items is exhausted",
400 type_name = Self::type_name(),
401 ),
402 }
403 }
404
405 #[cfg(any(
406 feature = "async",
407 feature = "fs",
408 feature = "process",
409 feature = "reqwest",
410 feature = "socket",
411 feature = "tui",
412 ))]
413 fn check_present<T>(self) -> Result<T, AnyhowError>
414 where
415 Self: Is<Option<T>>,
416 {
417 match self.into_self() {
418 Some(item) => item.ok(),
419 None => anyhow::bail!(
420 "keyed entry of type {type_name} is not present in the collection",
421 type_name = Self::type_name(),
422 ),
423 }
424 }
425
426 #[cfg(feature = "reqwest")]
428 async fn check_status(self) -> Result<Response, AnyhowError>
429 where
430 Self: Is<Response>,
431 {
432 let response = self.into_self();
433 let status = response.status();
434
435 if !status.is_client_error() && !status.is_server_error() {
436 return response.ok();
437 }
438
439 let text = match response.text().await {
440 Ok(text) => text,
441 Err(error) => std::format!("unable to read response text: {error}"),
442 };
443
444 anyhow::bail!("({status}) {text}")
445 }
446
447 #[cfg(any(feature = "ropey", feature = "misc", feature = "tui"))]
448 #[must_use]
449 fn clamped(self, min: Self, max: Self) -> Self
450 where
451 Self: PartialOrd + Sized,
452 {
453 num::clamp(self, min, max)
454 }
455
456 fn convert<T: From<Self>>(self) -> T
457 where
458 Self: Sized,
459 {
460 self.into()
461 }
462
463 fn contains_eq<Q, K>(&self, query: Q) -> bool
464 where
465 Self: AsRef<[K]>,
466 for<'a> &'a K: PartialEq<Q>,
467 {
468 self.find_eq(query).is_some()
469 }
470
471 #[cfg(any(
472 feature = "async",
473 feature = "fs",
474 feature = "process",
475 feature = "reqwest",
476 feature = "socket",
477 feature = "tui",
478 ))]
479 fn context_path<T, E, C: 'static + Display + Send + Sync, P: AsRef<Path>>(
480 self,
481 context: C,
482 path: P,
483 ) -> Result<T, AnyhowError>
484 where
485 Self: Context<T, E> + Sized,
486 {
487 let context = std::format!("{context}: {path}", path = path.as_ref().display());
488
489 self.context(context)
490 }
491
492 #[must_use]
493 fn copied(&self) -> Self
494 where
495 Self: Copy + Sized,
496 {
497 *self
498 }
499
500 #[cfg(feature = "process")]
501 async fn write_to_clipboard(&self) -> Result<ExitStatus, AnyhowError>
502 where
503 Self: AsRef<[u8]>,
504 {
505 let mut process = ProcessBuilder::new(Self::WRITE_TO_CLIPBOARD_COMMAND).build()?;
506
507 process
508 .stdin_mut()
509 .write_all_then_async(self.as_ref())
510 .await?
511 .flush()
512 .await?;
513
514 process.run().await?.ok()
515 }
516
517 #[cfg(feature = "process")]
518 #[must_use]
519 async fn read_from_clipboard() -> Result<String, AnyhowError> {
520 let mut process = ProcessBuilder::new(Self::READ_FROM_CLIPBOARD_COMMAND).build()?;
521 let string = process.stdout_mut().read_to_string_async().await?;
522
523 process.run().await?;
524
525 string.ok()
526 }
527
528 fn create(&self) -> Result<File, IoError>
529 where
530 Self: AsRef<Path>,
531 {
532 File::create(self)
533 }
534
535 fn create_dir_all(&self) -> Result<(), IoError>
536 where
537 Self: AsRef<Path>,
538 {
539 std::fs::create_dir_all(self)
540 }
541
542 #[cfg(feature = "misc")]
543 fn cycle_in_place(&mut self, amount: isize, total: usize)
544 where
545 Self: BorrowMut<usize>,
546 {
547 let current = self.borrow_mut();
548
549 *current = amount
553 .saturating_add_unsigned(*current)
554 .rem_euclid(total.cast_or_max())
555 .cast_or_max();
556 }
557
558 #[cfg(feature = "fmt")]
559 fn debug(&self) -> Debugged<'_, Self> {
560 Debugged::new(self)
561 }
562
563 #[cfg(any(feature = "serde", feature = "tui"))]
564 fn deserialize_from_seq<'de, D: Deserializer<'de>, X: Deserialize<'de>, Y, E: Display, F: Fn(X) -> Result<Y, E>>(
565 deserializer: D,
566 func: F,
567 ) -> Result<Self, D::Error>
568 where
569 Self: Default + Extend<Y>,
570 {
571 let seq_visitor = SeqVisitor::new(func);
572
573 deserializer.deserialize_seq(seq_visitor)
574 }
575
576 #[cfg(feature = "output")]
577 fn end_err<T>(self) -> Output<T, Self>
578 where
579 Self: Sized,
580 {
581 Output::EndErr(self)
582 }
583
584 #[cfg(feature = "output")]
585 fn end_ok<T, E>(&self) -> Output<T, E> {
586 Output::EndOk
587 }
588
589 fn err<T>(self) -> Result<T, Self>
590 where
591 Self: Sized,
592 {
593 Err(self)
594 }
595
596 #[cfg(feature = "fs")]
597 fn expand_user(&self) -> Cow<'_, Utf8Path>
598 where
599 Self: AsRef<str>,
600 {
601 let path_str = self.as_ref();
602
603 if let Some(relative_path_str) = path_str.strip_prefix("~/")
604 && let Some(home_dirpath) = Self::home_dirpath()
605 {
606 home_dirpath.join(relative_path_str).owned()
607 } else {
608 path_str.as_utf8_path().borrowed()
609 }
610 }
611
612 #[cfg(feature = "fs")]
613 fn unexpand_user(&self) -> Cow<'_, Utf8Path>
614 where
615 Self: AsRef<str>,
616 {
617 let path_str = self.as_ref();
618
619 if let Some(home_dirpath) = Self::home_dirpath()
620 && let Some(relative_path_str) = path_str.strip_prefix(home_dirpath.as_str())
621 {
622 if relative_path_str.is_empty() {
623 "~".convert::<Utf8PathBuf>().owned()
624 } else if relative_path_str.as_utf8_path().is_absolute() {
625 "~".cat(relative_path_str).convert::<Utf8PathBuf>().owned()
626 } else {
627 path_str.as_utf8_path().borrowed()
628 }
629 } else {
630 path_str.as_utf8_path().borrowed()
631 }
632 }
633
634 #[cfg(any(feature = "ropey", feature = "tui"))]
635 fn extended_graphemes(&self) -> Graphemes<'_>
636 where
637 Self: AsRef<str>,
638 {
639 self.as_ref().graphemes(Self::IS_EXTENDED)
640 }
641
642 #[cfg(any(feature = "ropey", feature = "tui"))]
643 fn extended_grapheme_indices(&self) -> GraphemeIndices<'_>
644 where
645 Self: AsRef<str>,
646 {
647 self.as_ref().grapheme_indices(Self::IS_EXTENDED)
648 }
649
650 #[cfg(feature = "ropey")]
651 fn extended_graphemes_at<'a>(self, extended_graphemes_index_range: Range<usize>) -> impl Iterator<Item = &'a str>
652 where
653 Self: Is<RopeSlice<'a>>,
654 {
655 let extended_graphemes_index_range = extended_graphemes_index_range.borrow();
656
657 self.into_self()
658 .chunks()
659 .flat_map(str::extended_graphemes)
660 .skip(extended_graphemes_index_range.start)
661 .take(extended_graphemes_index_range.len())
662 }
663
664 #[cfg(feature = "ropey")]
665 fn extended_graphemes_at_rect<'a>(
666 self,
667 lines_index_range: Range<usize>,
668 extended_graphemes_index_range: Range<usize>,
669 ) -> impl Iterator<Item = impl Iterator<Item = &'a str>>
670 where
671 Self: Is<RopeSlice<'a>>,
672 {
673 self.into_self()
674 .saturating_lines_at(lines_index_range.start)
675 .take(lines_index_range.len())
676 .map(move |line_rope_slice| line_rope_slice.extended_graphemes_at(extended_graphemes_index_range.clone()))
677 }
678
679 #[cfg(any(feature = "ropey", feature = "tui"))]
680 fn extended_grapheme_substring(&self, range: Range<usize>) -> &str
681 where
682 Self: AsRef<str>,
683 {
684 let string = self.as_ref();
685 let mut extended_grapheme_indices = string.extended_grapheme_indices().skip(range.start);
686 let Some((begin_byte_offset, _begin_extended_grapheme)) = extended_grapheme_indices.next() else {
687 return "";
688 };
689 let mut extended_grapheme_indices = extended_grapheme_indices.skip(range.len());
690 let end_byte_offset = if let Some((end_byte_offset, _end_extended_grapheme)) = extended_grapheme_indices.next()
691 {
692 end_byte_offset
693 } else {
694 string.len()
695 };
696
697 &string[begin_byte_offset..end_byte_offset]
698 }
699
700 #[cfg(feature = "async")]
701 fn filter_sync(
702 self,
703 mut func: impl FnMut(&Self::Item) -> bool,
704 ) -> Filter<Self, Ready<bool>, impl FnMut(&Self::Item) -> Ready<bool>>
705 where
706 Self: Sized + StreamExt,
707 {
708 self.filter(move |x| func(x).ready())
710 }
711
712 #[cfg(feature = "fs")]
713 fn file_name_ok(&self) -> Result<&str, AnyhowError>
714 where
715 Self: AsRef<Utf8Path>,
716 {
717 self.as_ref().file_name().context("path has no file name")
718 }
719
720 fn find_eq<Q, K>(&self, query: Q) -> Option<(usize, &K)>
721 where
722 Self: AsRef<[K]>,
723 for<'a> &'a K: PartialEq<Q>,
724 {
725 self.as_ref().iter().enumerate().find(|(_index, key)| *key == query)
726 }
727
728 fn has_happened(self) -> bool
729 where
730 Self: Is<Instant>,
731 {
732 self.into_self() <= Instant::now()
733 }
734
735 #[cfg(feature = "fs")]
736 #[must_use]
737 fn home_dirpath() -> Option<Utf8PathBuf> {
738 home::home_dir()?.try_convert::<Utf8PathBuf>().ok()
739 }
740
741 fn if_else<T>(self, true_value: T, false_value: T) -> T
742 where
743 Self: Is<bool>,
744 {
745 if self.into_self() { true_value } else { false_value }
746 }
747
748 fn immutable(&mut self) -> &Self {
749 self
750 }
751
752 fn inc(&self) -> usize
753 where
754 Self: Borrow<AtomicUsize>,
755 {
756 self.borrow().fetch_add(1, Ordering::SeqCst)
757 }
758
759 fn insert_mut<'a, K: 'a + Eq + Hash, V>(&'a mut self, key: K, value: V) -> &'a mut V
760 where
761 Self: BorrowMut<HashMap<K, V>>,
762 {
763 self.borrow_mut().entry(key).insert_entry(value).into_mut()
764 }
765
766 #[cfg(any(feature = "ropey", feature = "misc", feature = "tui"))]
767 #[must_use]
768 fn interpolate(
769 self,
770 old_min: impl ToPrimitive,
771 old_max: impl ToPrimitive,
772 new_min: impl ToPrimitive,
773 new_max: impl ToPrimitive,
774 ) -> Self
775 where
776 Self: Bounded + NumCast + ToPrimitive,
777 {
778 let old_min = old_min.cast_or_max::<f64>();
779 let old_max = old_max.cast_or_max::<f64>();
780 let new_min = new_min.cast_or_max::<f64>();
781 let new_max = new_max.cast_or_max::<f64>();
782 let old_value = self.cast_or_max::<f64>().clamped(old_min, old_max);
783 let new_value = new_min + (new_max - new_min) * (old_value - old_min) / (old_max - old_min);
784 let new_value = new_value.clamped(new_min, new_max);
785
786 new_value.cast_or_max()
787 }
788
789 fn into_box(self) -> Box<Self>
790 where
791 Self: Sized,
792 {
793 Box::new(self)
794 }
795
796 fn into_break<C>(self) -> ControlFlow<Self, C>
797 where
798 Self: Sized,
799 {
800 ControlFlow::Break(self)
801 }
802
803 fn into_continue<B>(self) -> ControlFlow<B, Self>
804 where
805 Self: Sized,
806 {
807 ControlFlow::Continue(self)
808 }
809
810 #[cfg(feature = "poem")]
811 fn into_endpoint(self) -> impl Endpoint<Output = Self>
812 where
813 Self: Clone + IntoResponse + Sync,
814 {
815 let func = move |_request| self.clone();
816
817 poem::endpoint::make_sync(func)
818 }
819
820 #[cfg(feature = "async")]
821 fn into_interval(self) -> Interval
822 where
823 Self: Is<Duration>,
824 {
825 tokio::time::interval(self.into_self())
826 }
827
828 #[cfg(feature = "async")]
829 fn into_left<R>(self) -> Either<Self, R>
830 where
831 Self: Sized,
832 {
833 Either::Left(self)
834 }
835
836 #[cfg(feature = "tui")]
837 fn into_line<'a>(self) -> Line<'a>
838 where
839 Self: Into<Cow<'a, str>>,
840 {
841 self.into().into()
842 }
843
844 fn into_manually_drop(self) -> ManuallyDrop<Self>
845 where
846 Self: Sized,
847 {
848 ManuallyDrop::new(self)
849 }
850
851 #[cfg(feature = "async")]
852 fn into_stream_reader<B: Buf, E: Into<IoError>>(self) -> StreamReader<Self, B>
853 where
854 Self: Sized + Stream<Item = Result<B, E>>,
855 {
856 StreamReader::new(self)
857 }
858
859 #[cfg(feature = "async")]
860 fn into_length_delimited_frames(self) -> Framed<Self, LengthDelimitedCodec>
861 where
862 Self: Sized,
863 {
864 Framed::new(self, LengthDelimitedCodec::new())
865 }
866
867 #[cfg(feature = "async")]
868 fn into_line_frames(self) -> Framed<Self, LinesCodec>
869 where
870 Self: Sized,
871 {
872 Framed::new(self, LinesCodec::new())
873 }
874
875 #[cfg(feature = "async")]
876 fn into_right<L>(self) -> Either<L, Self>
877 where
878 Self: Sized,
879 {
880 Either::Right(self)
881 }
882
883 #[cfg(feature = "poem")]
885 fn into_parse_request_payload_result<T>(self) -> Result<T, ParseRequestPayloadError>
886 where
887 Self: Is<Result<T, SerdeJsonError>>,
888 {
889 match self.into_self() {
890 Ok(value) => value.ok(),
891 Err(serde_json_error) => ParseRequestPayloadError {
892 reason: serde_json_error.to_string(),
893 }
894 .err(),
895 }
896 }
897
898 #[cfg(feature = "async")]
899 async fn into_select<T: Future>(self, rhs: T) -> Either<Self::Output, T::Output>
900 where
901 Self: Future + Sized,
902 {
903 tokio::select! {
904 value = self => value.into_left(),
905 value = rhs => value.into_right(),
906 }
907 }
908
909 #[cfg(feature = "tracing")]
910 fn into_status<T, E>(self) -> Status<T, E>
911 where
912 Self: Is<Result<T, E>>,
913 {
914 Status::new(self.into_self())
915 }
916
917 #[cfg(feature = "async")]
918 fn into_stream(self) -> Self::Stream
919 where
920 Self: IntoStream + Sized,
921 {
922 IntoStream::into_stream(self)
923 }
924
925 #[cfg(feature = "fs")]
926 fn into_string(self) -> Result<String, AnyhowError>
927 where
928 Self: Is<PathBuf>,
929 {
930 match self.into_self().into_os_string().into_string() {
931 Ok(string) => string.ok(),
932 Err(os_string) => os_string.invalid_utf8_err(),
933 }
934 }
935
936 #[cfg(feature = "serde")]
937 fn into_value_from_json<T: DeserializeOwned>(self) -> Result<T, SerdeJsonError>
938 where
939 Self: Is<Json>,
940 {
941 serde_json::from_value(self.into_self())
942 }
943
944 #[cfg(feature = "fs")]
945 fn invalid_utf8_err<T>(&self) -> Result<T, AnyhowError>
946 where
947 Self: Debug,
948 {
949 anyhow::bail!("{self:?} is not valid utf-8")
950 }
951
952 fn io_error(self) -> IoError
953 where
954 Self: Into<Box<dyn StdError + Send + Sync>>,
955 {
956 IoError::other(self)
957 }
958
959 fn io_result<T, E: Into<Box<dyn StdError + Send + Sync>>>(self) -> Result<T, IoError>
960 where
961 Self: Is<Result<T, E>>,
962 {
963 self.into_self().map_err(E::io_error)
964 }
965
966 #[allow(clippy::wrong_self_convention)]
967 fn is_less_than<T: PartialOrd>(self, rhs: T) -> bool
968 where
969 Self: Into<T>,
970 {
971 self.into() < rhs
972 }
973
974 #[cfg(any(feature = "ropey", feature = "misc", feature = "tui"))]
975 fn is_positive(&self) -> bool
976 where
977 Self: PartialOrd + Zero,
978 {
979 &Self::zero() < self
980 }
981
982 #[cfg(feature = "async")]
983 async fn join_all<T>(self) -> T
984 where
985 Self: IntoIterator<Item: Future> + Sized,
986 T: FromIterator<<Self::Item as Future>::Output>,
987 {
988 futures::future::join_all(self).await.into_iter().collect()
989 }
990
991 #[cfg(any(feature = "ropey", feature = "tui"))]
992 fn len_extended_graphemes(&self) -> usize
993 where
994 Self: AsRef<str>,
995 {
996 self.as_ref().extended_graphemes().count()
997 }
998
999 #[cfg(feature = "tracing")]
1000 fn level<T, E>(&self) -> Level
1001 where
1002 Self: Borrow<Result<T, E>>,
1003 {
1004 if self.borrow().is_ok() {
1005 Level::INFO
1006 } else {
1007 Level::WARN
1008 }
1009 }
1010
1011 #[cfg(any(feature = "tui", feature = "tracing"))]
1012 fn log_error(&self)
1013 where
1014 Self: Display,
1015 {
1016 tracing::warn!(error = %self, "error: {self:#}");
1017 }
1018
1019 #[cfg(any(feature = "tui", feature = "tracing"))]
1020 #[must_use]
1021 fn log_if_error<T, E: Display>(self) -> Self
1022 where
1023 Self: Borrow<Result<T, E>> + Sized,
1024 {
1025 if let Err(error) = self.borrow() {
1026 error.log_error();
1027 }
1028
1029 self
1030 }
1031
1032 fn map_collect<Y, T: FromIterator<Y>>(self, func: impl FnMut(Self::Item) -> Y) -> T
1033 where
1034 Self: IntoIterator + Sized,
1035 {
1036 self.into_iter().map(func).collect::<T>()
1037 }
1038
1039 fn map_into<Y, X: Into<Y>>(self) -> Option<Y>
1040 where
1041 Self: Is<Option<X>>,
1042 {
1043 self.into_self().map(X::into)
1044 }
1045
1046 fn map_as_ref<'a, Y: ?Sized, X: 'a + AsRef<Y>>(&'a self) -> Option<&'a Y>
1047 where
1048 Self: Borrow<Option<X>>,
1049 {
1050 self.borrow().as_ref().map(X::as_ref)
1051 }
1052
1053 fn mem_drop(self)
1054 where
1055 Self: Sized,
1056 {
1057 std::mem::drop(self);
1058 }
1059
1060 #[must_use]
1061 fn mem_replace(&mut self, value: Self) -> Self
1062 where
1063 Self: Sized,
1064 {
1065 std::mem::replace(self, value)
1066 }
1067
1068 #[must_use]
1069 fn mem_take(&mut self) -> Self
1070 where
1071 Self: Default,
1072 {
1073 std::mem::take(self)
1074 }
1075
1076 #[cfg(feature = "async")]
1077 async fn metadata_async(&self) -> Result<Metadata, IoError>
1078 where
1079 Self: AsRef<Path>,
1080 {
1081 tokio::fs::metadata(self).await
1082 }
1083
1084 fn mut_push<T>(&mut self, item: T) -> &mut T
1086 where
1087 Self: BorrowMut<Vec<T>>,
1088 {
1089 let vec = self.borrow_mut();
1090
1091 vec.push(item);
1092
1093 vec.last_mut().unwrap()
1094 }
1095
1096 #[cfg(feature = "ropey")]
1097 fn num_lines_and_extended_graphemes<'a>(self) -> PointUsize
1098 where
1099 Self: Is<RopeSlice<'a>>,
1100 {
1101 let rope_slice = self.into_self();
1102 let y = rope_slice.len_lines();
1103 let x = rope_slice
1104 .lines()
1105 .map(|line_rope| line_rope.chunks().map(str::len_extended_graphemes).sum())
1106 .max()
1107 .unwrap_or(0);
1108
1109 PointUsize::new(x, y)
1110 }
1111
1112 fn ok<E>(self) -> Result<Self, E>
1113 where
1114 Self: Sized,
1115 {
1116 Ok(self)
1117 }
1118
1119 fn once(self) -> Once<Self>
1120 where
1121 Self: Sized,
1122 {
1123 std::iter::once(self)
1124 }
1125
1126 fn open(&self) -> Result<File, IoError>
1127 where
1128 Self: AsRef<Path>,
1129 {
1130 File::open(self)
1131 }
1132
1133 #[cfg(any(feature = "ropey", feature = "async"))]
1134 async fn open_async(&self) -> Result<TokioFile, IoError>
1135 where
1136 Self: AsRef<Path>,
1137 {
1138 TokioFile::open(self).await
1139 }
1140
1141 #[cfg(feature = "fmt")]
1142 fn optional_display(&self) -> OptionalDisplay<'_, Self> {
1143 OptionalDisplay::new(self)
1144 }
1145
1146 #[cfg(feature = "output")]
1147 fn output_ok<E>(self) -> Output<Self, E>
1148 where
1149 Self: Sized,
1150 {
1151 Output::Ok(self)
1152 }
1153
1154 fn owned<B: ?Sized + ToOwned<Owned = Self>>(self) -> Cow<'static, B>
1155 where
1156 Self: Sized,
1157 {
1158 Cow::Owned(self)
1159 }
1160
1161 fn pair<T>(self, rhs: T) -> (Self, T)
1162 where
1163 Self: Sized,
1164 {
1165 (self, rhs)
1166 }
1167
1168 fn pin(self) -> Pin<Box<Self>>
1169 where
1170 Self: Sized,
1171 {
1172 Box::pin(self)
1173 }
1174
1175 fn pipe<X, Y, Z, F: FnMut(Y) -> Z>(mut self, mut func: F) -> impl FnMut(X) -> Z
1176 where
1177 Self: Sized + FnMut(X) -> Y,
1178 {
1179 move |x| self(x).pipe_into(&mut func)
1180 }
1181
1182 fn poll_ready(self) -> Poll<Self>
1183 where
1184 Self: Sized,
1185 {
1186 Poll::Ready(self)
1187 }
1188
1189 fn pipe_into<T, F: FnOnce(Self) -> T>(self, func: F) -> T
1190 where
1191 Self: Sized,
1192 {
1193 func(self)
1194 }
1195
1196 #[cfg(feature = "poem")]
1197 fn poem_binary(self) -> PoemBinary<Self>
1198 where
1199 Self: Sized,
1200 {
1201 PoemBinary(self)
1202 }
1203
1204 #[cfg(feature = "poem")]
1205 fn poem_binary_message(self) -> PoemMessage
1206 where
1207 Self: Is<Vec<u8>>,
1208 {
1209 PoemMessage::Binary(self.into_self())
1210 }
1211
1212 #[cfg(feature = "poem")]
1213 fn poem_json(self) -> PoemJson<Self>
1214 where
1215 Self: Sized,
1216 {
1217 PoemJson(self)
1218 }
1219
1220 #[cfg(feature = "poem")]
1221 fn poem_stream_body<O: 'static + Into<Bytes>, E: 'static + Into<IoError>>(self) -> PoemBinary<PoemBody>
1222 where
1223 Self: 'static + Send + Sized + Stream<Item = Result<O, E>>,
1224 {
1225 PoemBody::from_bytes_stream(self).poem_binary()
1226 }
1227
1228 #[cfg(feature = "poem")]
1229 fn poem_text_message(self) -> PoemMessage
1230 where
1231 Self: Is<String>,
1232 {
1233 PoemMessage::Text(self.into_self())
1234 }
1235
1236 fn println(&self)
1237 where
1238 Self: Display,
1239 {
1240 std::println!("{self}");
1241 }
1242
1243 fn print(&self)
1244 where
1245 Self: Display,
1246 {
1247 std::print!("{self}");
1248 }
1249
1250 fn push_to<T: Extend<Self>>(self, collection: &mut T)
1251 where
1252 Self: Sized,
1253 {
1254 collection.extend(self.once());
1255 }
1256
1257 fn push_all_to<T: Extend<Self::Item>>(self, collection: &mut T)
1258 where
1259 Self: IntoIterator + Sized,
1260 {
1261 collection.extend(self);
1262 }
1263
1264 #[cfg(feature = "reqwest")]
1265 fn query_all<T: Serialize>(self, name: &str, values: impl IntoIterator<Item = T>) -> RequestBuilder
1266 where
1267 Self: Is<RequestBuilder>,
1268 {
1269 let mut request_builder = self.into_self();
1270
1271 for value in values {
1272 request_builder = request_builder.query_one(name, value);
1273 }
1274
1275 request_builder
1276 }
1277
1278 #[cfg(feature = "reqwest")]
1279 fn query_one<T: Serialize>(self, name: &str, value: impl Into<Option<T>>) -> RequestBuilder
1280 where
1281 Self: Is<RequestBuilder>,
1282 {
1283 let query: &[(&str, T)] = if let Some(value) = value.into() {
1284 &[(name, value)]
1285 } else {
1286 &[]
1287 };
1288 let request_builder = self.into_self();
1289
1290 request_builder.query(query)
1291 }
1292
1293 fn range_from_len(self, len: Self) -> Range<Self>
1294 where
1295 Self: Add<Output = Self> + Copy,
1296 {
1297 let end = self + len;
1298
1299 self..end
1300 }
1301
1302 #[cfg(feature = "tui")]
1303 fn ratatui_rect(self) -> Rect
1304 where
1305 Self: Into<(u16, u16)>,
1306 {
1307 let (width, height) = self.into();
1308 let x = 0;
1309 let y = 0;
1310
1311 Rect { x, y, width, height }
1312 }
1313
1314 #[cfg(any(feature = "async", feature = "process"))]
1315 async fn read_to_string_async(&mut self) -> Result<String, IoError>
1316 where
1317 Self: AsyncReadExt + Unpin,
1318 {
1319 let mut string = String::new();
1320
1321 self.read_to_string(&mut string).await?;
1322
1323 string.ok()
1324 }
1325
1326 #[cfg(feature = "async")]
1327 async fn read_to_string_fs_async(self) -> ReadValue<Self>
1328 where
1329 Self: AsRef<Path> + Sized,
1330 {
1331 let result = tokio::fs::read_to_string(self.as_ref()).await;
1332
1333 ReadValue::new(self, result)
1334 }
1335
1336 fn ready(self) -> Ready<Self>
1337 where
1338 Self: Sized,
1339 {
1340 std::future::ready(self)
1341 }
1342
1343 fn ref_immut(&self) -> &Self {
1344 self
1345 }
1346
1347 fn ref_mut(&mut self) -> &mut Self {
1348 self
1349 }
1350
1351 #[cfg(feature = "tui")]
1352 fn render_to(self, frame: &mut Frame, rect: Rect)
1353 where
1354 Self: Widget + Sized,
1355 {
1356 frame.render_widget(self, rect);
1357 }
1358
1359 fn repeat(self) -> Repeat<Self>
1360 where
1361 Self: Clone,
1362 {
1363 std::iter::repeat(self)
1364 }
1365
1366 fn reversed<X, Y>(self) -> (Y, X)
1367 where
1368 Self: Is<(X, Y)>,
1369 {
1370 let (x, y) = self.into_self();
1371
1372 y.pair(x)
1373 }
1374
1375 #[cfg(feature = "ropey")]
1376 async fn rope<const N: usize>(&self) -> Result<Rope, IoError>
1377 where
1378 Self: AsRef<Path>,
1379 {
1380 self.open_async()
1381 .await?
1382 .buf_reader_async()
1383 .pipe_into(RopeBuilder::<_, N>::new)
1384 .build()
1385 .await
1386 }
1387
1388 #[cfg(feature = "async")]
1389 async fn run_for(mut self, duration: Duration) -> Result<Self, RunForError<Self::Output>>
1390 where
1391 Self: Future + Sized + Unpin,
1392 {
1393 tokio::select! {
1394 output = &mut self => RunForError::new(output).err(),
1395 () = tokio::time::sleep(duration) => self.ok(),
1396 }
1397 }
1398
1399 #[cfg(feature = "async")]
1400 async fn run_local(self) -> Self::Output
1401 where
1402 Self: Future + Sized,
1403 {
1404 LocalSet::new().run_until(self).await
1405 }
1406
1407 fn remove_file(&self) -> Result<(), IoError>
1408 where
1409 Self: AsRef<Path>,
1410 {
1411 std::fs::remove_file(self)
1412 }
1413
1414 #[cfg(feature = "socket")]
1415 async fn respond_to<T: Request<Response = Self>>(
1416 &self,
1417 mut socket: impl BorrowMut<Socket>,
1418 ) -> Result<(), AnyhowError> {
1419 socket.borrow_mut().respond::<T>(self).await
1420 }
1421
1422 #[cfg(feature = "ropey")]
1426 fn saturating_chunks_at_extended_grapheme<'a>(self, extended_grapheme_index: usize) -> Chunks<'a>
1427 where
1428 Self: Is<RopeSlice<'a>>,
1429 {
1430 self.saturating_chunks_at_char(extended_grapheme_index)
1431 }
1432
1433 #[cfg(feature = "ropey")]
1435 fn saturating_chunks_at_char<'a>(self, char_index: usize) -> Chunks<'a>
1436 where
1437 Self: Is<RopeSlice<'a>>,
1438 {
1439 let rope_slice = self.into_self();
1440 let char_index = rope_slice.len_chars().min(char_index);
1441
1442 rope_slice.chunks_at_char(char_index).0
1443 }
1444
1445 #[cfg(feature = "ropey")]
1447 fn saturating_lines_at<'a>(self, line_index: usize) -> Lines<'a>
1448 where
1449 Self: Is<RopeSlice<'a>>,
1450 {
1451 let rope_slice = self.into_self();
1452 let line_index = rope_slice.len_lines().min(line_index);
1453
1454 rope_slice.lines_at(line_index)
1455 }
1456
1457 #[cfg(feature = "tui")]
1458 fn saturating_add_or_sub_in_place_with_max(&mut self, rhs: Self, max_value: Self, add: bool)
1459 where
1460 Self: Ord + SaturatingAdd + SaturatingSub + Sized,
1461 {
1462 let value = if add {
1463 self.saturating_add(&rhs)
1464 } else {
1465 self.saturating_sub(&rhs)
1466 };
1467
1468 *self = value.min(max_value);
1469 }
1470
1471 #[cfg(feature = "tui")]
1472 fn scroll_count(&self, scroll_count: ScrollCount, orientation: Orientation) -> usize
1473 where
1474 Self: Scrollable,
1475 {
1476 match scroll_count {
1477 ScrollCount::Fixed(scroll_count) => scroll_count,
1478 ScrollCount::PageSize => *self.latest_content_render_size().get(orientation),
1479 }
1480 }
1481
1482 #[cfg(feature = "tui")]
1483 fn max_scroll_offset(&self, scroll_when: ScrollWhen, content_size: PointUsize) -> PointUsize
1484 where
1485 Self: Scrollable,
1486 {
1487 match scroll_when {
1488 ScrollWhen::Always => content_size.saturating_sub_scalar(&1),
1489 ScrollWhen::ForLargeContent => content_size.saturating_sub(&self.latest_content_render_size()),
1490 }
1491 }
1492
1493 #[cfg(feature = "tui")]
1494 fn scroll(&mut self, scroll_count: ScrollCount, scroll_when: ScrollWhen, content_size: PointUsize, orientation: Orientation, add: bool)
1495 where
1496 Self: Scrollable,
1497 {
1498 let scroll_count = self.as_immut().scroll_count(scroll_count, orientation);
1499 let max_scroll_offset = *self.as_immut().max_scroll_offset(scroll_when, content_size).get(orientation);
1500
1501 self.scroll_offset_mut()
1502 .get_mut(orientation)
1503 .saturating_add_or_sub_in_place_with_max(scroll_count, max_scroll_offset, add);
1504 }
1505
1506 #[cfg(feature = "tui")]
1507 fn scroll_down(&mut self, scroll_count: ScrollCount, content_size: PointUsize, scroll_when: ScrollWhen)
1508 where
1509 Self: Scrollable,
1510 {
1511 self.scroll(scroll_count, scroll_when, content_size, Orientation::Vertical, true);
1512 }
1513
1514 #[cfg(feature = "tui")]
1515 fn scroll_up(&mut self, scroll_count: ScrollCount, content_size: PointUsize, scroll_when: ScrollWhen)
1516 where
1517 Self: Scrollable,
1518 {
1519 self.scroll(scroll_count, scroll_when, content_size, Orientation::Vertical, false);
1520 }
1521
1522 #[cfg(feature = "tui")]
1523 fn scroll_left(&mut self, scroll_count: ScrollCount, content_size: PointUsize, scroll_when: ScrollWhen)
1524 where
1525 Self: Scrollable,
1526 {
1527 self.scroll(scroll_count, scroll_when, content_size, Orientation::Horizontal, false);
1528 }
1529
1530 #[cfg(feature = "tui")]
1531 fn scroll_right(&mut self, scroll_count: ScrollCount, content_size: PointUsize, scroll_when: ScrollWhen)
1532 where
1533 Self: Scrollable,
1534 {
1535 self.scroll(scroll_count, scroll_when, content_size, Orientation::Horizontal, true);
1536 }
1537
1538 #[cfg(feature = "async")]
1539 async fn select_all(self) -> <<Self as IntoIterator>::Item as Future>::Output
1540 where
1541 Self: IntoIterator + Sized,
1542 <Self as IntoIterator>::Item: Future,
1543 {
1544 self.into_iter()
1545 .collect::<FuturesUnordered<_>>()
1546 .next()
1547 .wait_then_unwrap_or_pending()
1548 .await
1549 }
1550
1551 #[cfg(feature = "async")]
1552 async fn send_to<T: Sink<Self> + Unpin>(self, mut sink: T) -> Result<(), T::Error>
1553 where
1554 Self: Sized,
1555 {
1556 sink.send(self).await
1557 }
1558
1559 #[cfg(feature = "async")]
1560 fn send_to_oneshot(self, sender: OneshotSender<Self>) -> Result<(), AnyhowError>
1561 where
1562 Self: Sized,
1563 {
1564 sender
1566 .send(self)
1567 .ok()
1568 .context("unable to send value over oneshot channel")
1569 }
1570
1571 fn set_true(&mut self) -> bool
1572 where
1573 Self: BorrowMut<bool>,
1574 {
1575 self.borrow_mut().mem_replace(true)
1576 }
1577
1578 fn set_false(&mut self) -> bool
1579 where
1580 Self: BorrowMut<bool>,
1581 {
1582 self.borrow_mut().mem_replace(false)
1583 }
1584
1585 #[cfg(feature = "async")]
1586 fn sleep(self) -> Sleep
1587 where
1588 Self: Is<Duration>,
1589 {
1590 tokio::time::sleep(self.into_self())
1591 }
1592
1593 fn some(self) -> Option<Self>
1594 where
1595 Self: Sized,
1596 {
1597 Some(self)
1598 }
1599
1600 #[cfg(feature = "async")]
1601 fn spawn_task(self) -> JoinHandle<Self::Output>
1602 where
1603 Self: 'static + Future + Sized + Send,
1604 Self::Output: 'static + Send,
1605 {
1606 tokio::spawn(self)
1607 }
1608
1609 fn substr_interval(&self, query: &[u8]) -> Option<(usize, usize)>
1611 where
1612 Self: AsRef<[u8]>,
1613 {
1614 let byte_str = self.as_ref();
1615 let predicate = |substr| substr == query;
1616 let query_len = query.len();
1617 let begin = byte_str.windows(query_len).position(predicate)?;
1618 let end = begin + query_len;
1619
1620 (begin, end).some()
1621 }
1622
1623 #[cfg(feature = "serde")]
1624 fn take_json<T: DeserializeOwned>(&mut self, index: impl Index) -> Result<T, SerdeJsonError>
1625 where
1626 Self: BorrowMut<Json>,
1627 {
1628 self.borrow_mut()
1629 .get_mut(index)
1630 .unwrap_or(&mut Json::Null)
1631 .mem_take()
1632 .into_value_from_json()
1633 }
1634
1635 #[cfg(feature = "async")]
1636 fn timeout(self, duration: Duration) -> Timeout<Self>
1637 where
1638 Self: Future + Sized,
1639 {
1640 tokio::time::timeout(duration, self)
1641 }
1642
1643 fn toggle(&mut self)
1644 where
1645 Self: BorrowMut<bool>,
1646 {
1647 let bool_value = self.borrow_mut();
1648
1649 *bool_value = !*bool_value;
1650 }
1651
1652 #[cfg(feature = "serde")]
1653 fn to_json(&self) -> Result<Json, SerdeJsonError>
1654 where
1655 Self: Serialize,
1656 {
1657 serde_json::to_value(self)
1658 }
1659
1660 #[cfg(feature = "serde")]
1661 fn to_json_byte_str(&self) -> Result<Vec<u8>, SerdeJsonError>
1662 where
1663 Self: Serialize,
1664 {
1665 serde_json::to_vec(self)
1666 }
1667
1668 #[cfg(feature = "serde")]
1669 fn to_json_object(&self, key: &str) -> Json
1670 where
1671 Self: Serialize,
1672 {
1673 serde_json::json!({key: self})
1674 }
1675
1676 #[cfg(feature = "serde")]
1677 fn to_json_str(&self) -> Result<String, SerdeJsonError>
1678 where
1679 Self: Serialize,
1680 {
1681 serde_json::to_string(self)
1682 }
1683
1684 #[cfg(feature = "rmp")]
1685 fn to_rmp_byte_str(&self) -> Result<Vec<u8>, RmpEncodeError>
1686 where
1687 Self: Serialize,
1688 {
1689 rmp_serde::to_vec(self)
1690 }
1691
1692 #[cfg(feature = "fs")]
1693 fn to_uri(&self) -> Result<String, IoError>
1694 where
1695 Self: AsRef<Utf8Path>,
1696 {
1697 "file://".cat(self.absolute_utf8()?).ok()
1698 }
1699
1700 #[cfg(feature = "serde")]
1701 fn to_value_from_json_slice<'a, T: Deserialize<'a>>(&'a self) -> Result<T, SerdeJsonError>
1702 where
1703 Self: AsRef<[u8]>,
1704 {
1705 serde_json::from_slice(self.as_ref())
1706 }
1707
1708 #[cfg(feature = "serde")]
1709 fn to_value_from_json_reader<T: DeserializeOwned>(self) -> Result<T, SerdeJsonError>
1710 where
1711 Self: Read + Sized,
1712 {
1713 serde_json::from_reader(self)
1714 }
1715
1716 #[cfg(feature = "rmp")]
1717 fn to_value_from_rmp_slice<'a, T: Deserialize<'a>>(&'a self) -> Result<T, RmpDecodeError>
1718 where
1719 Self: AsRef<[u8]>,
1720 {
1721 rmp_serde::from_slice(self.as_ref())
1722 }
1723
1724 #[cfg(feature = "serde")]
1725 fn to_value_from_value<T: DeserializeOwned>(&self) -> Result<T, SerdeJsonError>
1726 where
1727 Self: Serialize,
1728 {
1729 self.to_json()?.into_value_from_json()
1730 }
1731
1732 #[cfg(feature = "serde")]
1733 fn to_value_from_yaml_slice<'a, T: Deserialize<'a>>(&'a self) -> Result<T, SerdeYamlError>
1734 where
1735 Self: AsRef<[u8]>,
1736 {
1737 serde_yaml_ng::from_slice(self.as_ref())
1738 }
1739
1740 #[cfg(feature = "serde")]
1741 fn to_value_from_yaml_reader<T: DeserializeOwned>(self) -> Result<T, SerdeYamlError>
1742 where
1743 Self: Read + Sized,
1744 {
1745 serde_yaml_ng::from_reader(self)
1746 }
1747
1748 #[cfg(any(feature = "ropey", feature = "tui"))]
1749 #[must_use]
1750 fn transpose(&self) -> Self
1751 where
1752 Self: Transpose + Sized,
1753 {
1754 Transpose::to_transpose(self)
1755 }
1756
1757 fn try_convert<T: TryFrom<Self>>(self) -> Result<T, T::Error>
1758 where
1759 Self: Sized,
1760 {
1761 self.try_into()
1762 }
1763
1764 #[cfg(feature = "async")]
1765 async fn try_join_all<T, E>(self) -> Result<T, E>
1766 where
1767 Self: IntoIterator<Item: TryFuture> + Sized,
1768 T: FromIterator<<Self::Item as TryFuture>::Ok>,
1769 E: From<<Self::Item as TryFuture>::Error>,
1770 {
1771 futures::future::try_join_all(self)
1772 .await?
1773 .into_iter()
1774 .collect::<T>()
1775 .ok()
1776 }
1777
1778 #[cfg(feature = "async")]
1779 async fn try_wait<T, E: 'static + Send + Sync>(self) -> Result<T, AnyhowError>
1780 where
1781 Self: Is<JoinHandle<Result<T, E>>>,
1782 AnyhowError: From<E>,
1783 {
1784 self.into_self().await??.ok()
1785 }
1786
1787 #[must_use]
1788 fn type_name() -> &'static str {
1789 std::any::type_name::<Self>()
1790 }
1791
1792 fn unit(&self) {}
1793
1794 async fn wait_then_unwrap_or_pending<T>(self) -> T
1796 where
1797 Self: Future<Output = Option<T>> + Sized,
1798 {
1799 match self.await {
1800 Some(value) => value,
1801 None => std::future::pending().await,
1802 }
1803 }
1804
1805 async fn unwrap_or_pending_then_wait<F: Future + Unpin>(&mut self) -> F::Output
1807 where
1808 Self: BorrowMut<Option<F>>,
1809 {
1810 if let Some(future) = self.borrow_mut().as_mut() {
1811 future.await
1812 } else {
1813 std::future::pending().await
1814 }
1815 }
1816
1817 fn with<T>(&self, value: T) -> T {
1818 value
1819 }
1820
1821 fn with_item_pushed<T>(self, item: T) -> Vec<T>
1822 where
1823 Self: Is<Vec<T>>,
1824 {
1825 let mut vec = self.into_self();
1826
1827 vec.push(item);
1828
1829 vec
1830 }
1831
1832 fn with_str_pushed(self, rhs: &str) -> String
1833 where
1834 Self: Is<String>,
1835 {
1836 let mut string = self.into_self();
1837
1838 string.push_str(rhs);
1839
1840 string
1841 }
1842
1843 #[cfg(feature = "serde")]
1844 fn write_as_json_to<T: Write>(&self, writer: T) -> Result<(), SerdeJsonError>
1845 where
1846 Self: Serialize,
1847 {
1848 serde_json::to_writer(writer, self)
1849 }
1850
1851 fn write_all_then(&mut self, byte_str: &[u8]) -> Result<&mut Self, IoError>
1852 where
1853 Self: Write,
1854 {
1855 self.write_all(byte_str)?.with(self).ok()
1856 }
1857
1858 #[cfg(any(feature = "async", feature = "process"))]
1859 async fn write_all_then_async(&mut self, byte_str: &[u8]) -> Result<&mut Self, IoError>
1860 where
1861 Self: AsyncWriteExt + Unpin,
1862 {
1863 self.write_all(byte_str).await?.with(self).ok()
1864 }
1865}
1866
1867impl<T: ?Sized> Utils for T {}