use std::{
cmp,
fmt::{self, Display},
};
use sway_types::{SourceEngine, SourceId};
pub(crate) fn get_file_name(
source_engine: &SourceEngine,
source_id: Option<&SourceId>,
) -> Option<String> {
match source_id {
Some(source_id) => source_engine.get_file_name(source_id),
None => None,
}
}
pub(crate) fn number_to_str(number: usize) -> String {
match number {
0 => "zero".to_string(),
1 => "one".to_string(),
2 => "two".to_string(),
3 => "three".to_string(),
4 => "four".to_string(),
5 => "five".to_string(),
6 => "six".to_string(),
7 => "seven".to_string(),
8 => "eight".to_string(),
9 => "nine".to_string(),
10 => "ten".to_string(),
_ => format!("{number}"),
}
}
pub(crate) enum Enclosing {
#[allow(dead_code)]
None,
DoubleQuote,
}
impl Display for Enclosing {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::None => "",
Self::DoubleQuote => "\"",
},
)
}
}
pub(crate) enum Indent {
#[allow(dead_code)]
None,
Single,
Double,
}
impl Display for Indent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::None => "",
Self::Single => " ",
Self::Double => " ",
},
)
}
}
pub(crate) fn sequence_to_str<T>(sequence: &[T], enclosing: Enclosing, max_items: usize) -> String
where
T: Display,
{
assert!(
!sequence.is_empty(),
"Sequence to display must not be empty."
);
assert!(
max_items > 0,
"Maximum number of items to display must be greater than zero."
);
let max_items = cmp::min(max_items, sequence.len());
let (to_display, remaining) = sequence.split_at(max_items);
let fmt_item = |item: &T| format!("{enclosing}{item}{enclosing}");
if !remaining.is_empty() {
format!(
"{}, and {} more",
to_display
.iter()
.map(fmt_item)
.collect::<Vec<_>>()
.join(", "),
number_to_str(remaining.len())
)
} else {
match to_display {
[] => unreachable!("There must be at least one item in the sequence."),
[item] => fmt_item(item),
[first_item, second_item] => {
format!("{} and {}", fmt_item(first_item), fmt_item(second_item))
}
_ => format!(
"{}, and {}",
to_display
.split_last()
.unwrap()
.1
.iter()
.map(fmt_item)
.collect::<Vec::<_>>()
.join(", "),
fmt_item(to_display.last().unwrap())
),
}
}
}
pub(crate) fn sequence_to_list<T>(sequence: &[T], indent: Indent, max_items: usize) -> Vec<String>
where
T: Display,
{
assert!(
!sequence.is_empty(),
"Sequence to display must not be empty."
);
assert!(
max_items > 0,
"Maximum number of items to display must be greater than zero."
);
let mut result = vec![];
let max_items = cmp::min(max_items, sequence.len());
let (to_display, remaining) = sequence.split_at(max_items);
for item in to_display {
result.push(format!("{indent}- {item}"));
}
if !remaining.is_empty() {
result.push(format!(
"{indent}- and {} more",
number_to_str(remaining.len())
));
}
result
}
pub(crate) fn plural_s(count: usize) -> &'static str {
if count == 1 {
""
} else {
"s"
}
}
pub(crate) fn is_are(count: usize) -> &'static str {
if count == 1 {
"is"
} else {
"are"
}
}
pub(crate) fn singular_plural<'a>(count: usize, singular: &'a str, plural: &'a str) -> &'a str {
if count == 1 {
singular
} else {
plural
}
}