apollo_federation/utils/
human_readable.rs1pub(crate) struct JoinStringsOptions<'a> {
2 pub(crate) separator: &'a str,
3 pub(crate) first_separator: Option<&'a str>,
4 pub(crate) last_separator: Option<&'a str>,
5 pub(crate) output_length_limit: Option<usize>,
9}
10
11impl Default for JoinStringsOptions<'_> {
12 fn default() -> Self {
13 Self {
14 separator: ", ",
15 first_separator: None,
16 last_separator: Some(" and "),
17 output_length_limit: None,
18 }
19 }
20}
21
22pub(crate) fn join_strings(
31 mut iter: impl Iterator<Item = impl AsRef<str>>,
32 options: JoinStringsOptions,
33) -> String {
34 let mut output = String::new();
35 let Some(first) = iter.next() else {
36 return output;
37 };
38 output.push_str(first.as_ref());
39 let Some(second) = iter.next() else {
40 return output;
41 };
42 let mut element_length = first.as_ref().chars().count();
45 let mut push_sep_and_element = |sep: &str, element: &str| {
47 if let Some(output_length_limit) = options.output_length_limit {
48 let new_element_length = element_length + element.chars().count();
52 return if new_element_length <= output_length_limit {
53 element_length = new_element_length;
54 output.push_str(sep);
55 output.push_str(element);
56 false
57 } else {
58 output.push_str(options.separator);
59 output.push_str("...");
60 true
61 };
62 }
63 output.push_str(sep);
64 output.push_str(element);
65 false
66 };
67 let last_sep = options.last_separator.unwrap_or(options.separator);
68 let Some(mut current) = iter.next() else {
69 push_sep_and_element(options.first_separator.unwrap_or(last_sep), second.as_ref());
70 return output;
71 };
72 if push_sep_and_element(
73 options.first_separator.unwrap_or(options.separator),
74 second.as_ref(),
75 ) {
76 return output;
77 }
78 for next in iter {
79 if push_sep_and_element(options.separator, current.as_ref()) {
80 return output;
81 }
82 current = next;
83 }
84 push_sep_and_element(last_sep, current.as_ref());
85 output
86}
87
88pub(crate) struct HumanReadableListOptions<'a> {
89 pub(crate) prefix: Option<HumanReadableListPrefix<'a>>,
90 pub(crate) last_separator: Option<&'a str>,
91 pub(crate) output_length_limit: usize,
94 pub(crate) empty_output: &'a str,
96}
97
98pub(crate) struct HumanReadableListPrefix<'a> {
99 pub(crate) singular: &'a str,
100 pub(crate) plural: &'a str,
101}
102
103impl Default for HumanReadableListOptions<'_> {
104 fn default() -> Self {
105 Self {
106 prefix: None,
107 last_separator: Some(" and "),
108 output_length_limit: 100,
109 empty_output: "",
110 }
111 }
112}
113
114pub(crate) fn human_readable_list(
124 mut iter: impl Iterator<Item = impl AsRef<str>>,
125 options: HumanReadableListOptions,
126) -> String {
127 let Some(first) = iter.next() else {
128 return options.empty_output.to_owned();
129 };
130 let Some(second) = iter.next() else {
131 return if let Some(prefix) = options.prefix {
132 format!("{} {}", prefix.singular, first.as_ref())
133 } else {
134 first.as_ref().to_owned()
135 };
136 };
137 let joined_strings = join_strings(
138 [first, second].into_iter().chain(iter),
139 JoinStringsOptions {
140 last_separator: options.last_separator,
141 output_length_limit: Some(options.output_length_limit),
142 ..Default::default()
143 },
144 );
145 if let Some(prefix) = options.prefix {
146 format!("{} {}", prefix.plural, joined_strings)
147 } else {
148 joined_strings
149 }
150}
151
152pub(crate) fn human_readable_subgraph_names(
155 subgraph_names: impl Iterator<Item = impl AsRef<str>>,
156) -> String {
157 human_readable_list(
158 subgraph_names.map(|name| format!("\"{}\"", name.as_ref())),
159 HumanReadableListOptions {
160 prefix: Some(HumanReadableListPrefix {
161 singular: "subgraph",
162 plural: "subgraphs",
163 }),
164 ..Default::default()
165 },
166 )
167}
168
169pub(crate) fn human_readable_types(types: impl Iterator<Item = impl AsRef<str>>) -> String {
172 human_readable_list(
173 types.map(|t| format!("\"{}\"", t.as_ref())),
174 HumanReadableListOptions {
175 prefix: Some(HumanReadableListPrefix {
176 singular: "type",
177 plural: "types",
178 }),
179 ..Default::default()
180 },
181 )
182}