Skip to main content

rustidy_util/
lib.rs

1//! Utilities
2
3// Features
4#![feature(
5	iter_advance_by,
6	decl_macro,
7	macro_metavar_expr_concat,
8	if_let_guard,
9	macro_derive,
10	thread_local,
11	negative_impls,
12	unsafe_cell_access
13)]
14
15// Modules
16pub mod arena;
17pub mod ast_pos;
18pub mod ast_range;
19pub mod ast_str;
20pub mod config;
21pub mod oob;
22pub mod whitespace;
23
24// Exports
25pub use self::{
26	arena::{Arena, ArenaData, ArenaIdx, decl_arena},
27	ast_pos::AstPos,
28	ast_range::AstRange,
29	ast_str::AstStr,
30	config::Config,
31	oob::Oob,
32	whitespace::Whitespace,
33};
34
35// Imports
36use core::iter;
37
38/// Returns if a string is blank
39#[must_use]
40pub fn is_str_blank(s: &str) -> bool {
41	s.chars().all(|ch| ch.is_ascii_whitespace())
42}
43
44/// Counts the number of newlines in a string
45#[must_use]
46pub fn str_count_newlines(s: &str) -> usize {
47	s.chars().filter(|&ch| ch == '\n').count()
48}
49
50#[extend::ext(name = StrPopFirst)]
51pub impl &str {
52	fn pop_first(&mut self) -> Option<char> {
53		let mut chars = self.chars();
54		let ch = chars.next()?;
55		*self = chars.as_str();
56
57		Some(ch)
58	}
59}
60
61#[extend::ext(name = StrChunk)]
62pub impl str {
63	fn chunk(&self, len: usize) -> impl Iterator<Item = &str> {
64		let mut s = self;
65		iter::from_fn(move || match s.is_empty() {
66			true => None,
67			false => {
68				let (cur, next) = s
69					.split_at_checked(len)
70					.unwrap_or_else(|| (s, &s[s.len()..]));
71				s = next;
72				Some(cur)
73			}
74		})
75	}
76}