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