1use std::borrow::Borrow;
4use std::collections::HashMap;
5use std::fmt;
6use std::hash::Hash;
7
8use crate::Specifier;
9
10pub trait FormatArgument {
13 fn supports_format(&self, specifier: &Specifier) -> bool;
15 fn fmt_display(&self, f: &mut fmt::Formatter) -> fmt::Result;
17 fn fmt_debug(&self, f: &mut fmt::Formatter) -> fmt::Result;
19 fn fmt_octal(&self, f: &mut fmt::Formatter) -> fmt::Result;
21 fn fmt_lower_hex(&self, f: &mut fmt::Formatter) -> fmt::Result;
23 fn fmt_upper_hex(&self, f: &mut fmt::Formatter) -> fmt::Result;
25 fn fmt_binary(&self, f: &mut fmt::Formatter) -> fmt::Result;
27 fn fmt_lower_exp(&self, f: &mut fmt::Formatter) -> fmt::Result;
29 fn fmt_upper_exp(&self, f: &mut fmt::Formatter) -> fmt::Result;
31 fn to_usize(&self) -> Result<usize, ()> {
36 Err(())
37 }
38}
39
40pub struct ArgumentFormatter<'v, V: FormatArgument>(pub &'v V);
42
43impl<'v, V: FormatArgument> fmt::Display for ArgumentFormatter<'v, V> {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 self.0.fmt_display(f)
46 }
47}
48
49impl<'v, V: FormatArgument> fmt::Debug for ArgumentFormatter<'v, V> {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 self.0.fmt_debug(f)
52 }
53}
54
55impl<'v, V: FormatArgument> fmt::Octal for ArgumentFormatter<'v, V> {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 self.0.fmt_octal(f)
58 }
59}
60
61impl<'v, V: FormatArgument> fmt::LowerHex for ArgumentFormatter<'v, V> {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 self.0.fmt_lower_hex(f)
64 }
65}
66
67impl<'v, V: FormatArgument> fmt::UpperHex for ArgumentFormatter<'v, V> {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 self.0.fmt_upper_hex(f)
70 }
71}
72
73impl<'v, V: FormatArgument> fmt::Binary for ArgumentFormatter<'v, V> {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 self.0.fmt_binary(f)
76 }
77}
78
79impl<'v, V: FormatArgument> fmt::LowerExp for ArgumentFormatter<'v, V> {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 self.0.fmt_lower_exp(f)
82 }
83}
84
85impl<'v, V: FormatArgument> fmt::UpperExp for ArgumentFormatter<'v, V> {
86 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87 self.0.fmt_upper_exp(f)
88 }
89}
90
91pub trait NamedArguments<V: FormatArgument> {
93 fn get(&self, key: &str) -> Option<&V>;
95}
96
97impl<K, V> NamedArguments<V> for HashMap<K, V>
98where
99 K: Borrow<str> + Hash + Eq,
100 V: FormatArgument,
101{
102 fn get(&self, key: &str) -> Option<&V> {
103 <HashMap<K, V>>::get(self, key)
104 }
105}
106
107impl<K, V> NamedArguments<V> for HashMap<K, &V>
108where
109 K: Borrow<str> + Hash + Eq,
110 V: FormatArgument,
111{
112 fn get(&self, key: &str) -> Option<&V> {
113 <HashMap<K, &V>>::get(self, key).map(|v| *v)
114 }
115}
116
117pub struct NoNamedArguments;
119
120impl<V> NamedArguments<V> for NoNamedArguments
121where
122 V: FormatArgument,
123{
124 fn get(&self, _: &str) -> Option<&V> {
125 None
126 }
127}
128
129pub trait PositionalArguments<'v, V>
131where
132 V: 'v + FormatArgument,
133{
134 type Iter: Iterator<Item = &'v V>;
136
137 fn get(&self, index: usize) -> Option<&V>;
139
140 fn iter(&'v self) -> Self::Iter;
142}
143
144impl<'v, V, T> PositionalArguments<'v, V> for T
145where
146 V: 'v + FormatArgument,
147 T: AsRef<[V]> + ?Sized,
148{
149 type Iter = std::slice::Iter<'v, V>;
150
151 fn get(&self, index: usize) -> Option<&V> {
152 <[V]>::get(self.as_ref(), index)
153 }
154
155 fn iter(&'v self) -> Self::Iter {
156 <[V]>::iter(self.as_ref())
157 }
158}
159
160pub struct NoPositionalArguments;
162
163impl<'v, V> PositionalArguments<'v, V> for NoPositionalArguments
164where
165 V: 'v + FormatArgument,
166{
167 type Iter = std::iter::Empty<&'v V>;
168
169 fn get(&self, _: usize) -> Option<&V> {
170 None
171 }
172
173 fn iter(&'v self) -> Self::Iter {
174 std::iter::empty()
175 }
176}
177
178pub trait ArgumentSource<V>
180where
181 V: FormatArgument,
182{
183 fn next_argument(&mut self) -> Option<&V>;
186
187 fn lookup_argument_by_index(&self, idx: usize) -> Option<&V>;
191
192 fn lookup_argument_by_name(&self, name: &str) -> Option<&V>;
194}