use std::borrow::Borrow;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use crate::Specifier;
pub trait FormatArgument {
fn supports_format(&self, specifier: &Specifier) -> bool;
fn fmt_display(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_debug(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_octal(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_lower_hex(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_upper_hex(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_binary(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_lower_exp(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn fmt_upper_exp(&self, f: &mut fmt::Formatter) -> fmt::Result;
fn to_usize(&self) -> Result<usize, ()> {
Err(())
}
}
pub struct ArgumentFormatter<'v, V: FormatArgument>(pub &'v V);
impl<'v, V: FormatArgument> fmt::Display for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_display(f)
}
}
impl<'v, V: FormatArgument> fmt::Debug for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_debug(f)
}
}
impl<'v, V: FormatArgument> fmt::Octal for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_octal(f)
}
}
impl<'v, V: FormatArgument> fmt::LowerHex for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_lower_hex(f)
}
}
impl<'v, V: FormatArgument> fmt::UpperHex for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_upper_hex(f)
}
}
impl<'v, V: FormatArgument> fmt::Binary for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_binary(f)
}
}
impl<'v, V: FormatArgument> fmt::LowerExp for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_lower_exp(f)
}
}
impl<'v, V: FormatArgument> fmt::UpperExp for ArgumentFormatter<'v, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_upper_exp(f)
}
}
pub trait NamedArguments<V: FormatArgument> {
fn get(&self, key: &str) -> Option<&V>;
}
impl<K, V> NamedArguments<V> for HashMap<K, V>
where
K: Borrow<str> + Hash + Eq,
V: FormatArgument,
{
fn get(&self, key: &str) -> Option<&V> {
<HashMap<K, V>>::get(self, key)
}
}
impl<K, V> NamedArguments<V> for HashMap<K, &V>
where
K: Borrow<str> + Hash + Eq,
V: FormatArgument,
{
fn get(&self, key: &str) -> Option<&V> {
<HashMap<K, &V>>::get(self, key).map(|v| *v)
}
}
pub struct NoNamedArguments;
impl<V> NamedArguments<V> for NoNamedArguments
where
V: FormatArgument,
{
fn get(&self, _: &str) -> Option<&V> {
None
}
}
pub trait PositionalArguments<'v, V>
where
V: 'v + FormatArgument,
{
type Iter: Iterator<Item = &'v V>;
fn get(&self, index: usize) -> Option<&V>;
fn iter(&'v self) -> Self::Iter;
}
impl<'v, V, T> PositionalArguments<'v, V> for T
where
V: 'v + FormatArgument,
T: AsRef<[V]> + ?Sized,
{
type Iter = std::slice::Iter<'v, V>;
fn get(&self, index: usize) -> Option<&V> {
<[V]>::get(self.as_ref(), index)
}
fn iter(&'v self) -> Self::Iter {
<[V]>::iter(self.as_ref())
}
}
pub struct NoPositionalArguments;
impl<'v, V> PositionalArguments<'v, V> for NoPositionalArguments
where
V: 'v + FormatArgument,
{
type Iter = std::iter::Empty<&'v V>;
fn get(&self, _: usize) -> Option<&V> {
None
}
fn iter(&'v self) -> Self::Iter {
std::iter::empty()
}
}
pub trait ArgumentSource<V>
where
V: FormatArgument,
{
fn next_argument(&mut self) -> Option<&V>;
fn lookup_argument_by_index(&self, idx: usize) -> Option<&V>;
fn lookup_argument_by_name(&self, name: &str) -> Option<&V>;
}