use crate::FixValue;
use std::iter::FusedIterator;
pub trait FieldAccess<F> {
type Group: RepeatingGroup<Entry = Self>;
fn group(&self, field: &F) -> Result<Self::Group, Option<<usize as FixValue>::Error>> {
match self.group_opt(field) {
Some(Ok(group)) => Ok(group),
Some(Err(e)) => Err(Some(e)),
None => Err(None),
}
}
fn group_opt(&self, field: &F) -> Option<Result<Self::Group, <usize as FixValue>::Error>>;
fn fv_raw(&self, field: &F) -> Option<&[u8]>;
#[inline]
fn fv<'a, V>(&'a self, field: &F) -> Result<V, Option<V::Error>>
where
V: FixValue<'a>,
{
match self.fv_opt(field) {
Some(Ok(x)) => Ok(x),
Some(Err(err)) => Err(Some(err)),
None => Err(None),
}
}
#[inline]
fn fvl<'a, V>(&'a self, field: &F) -> Result<V, Option<V::Error>>
where
V: FixValue<'a>,
{
match self.fvl_opt(field) {
Some(Ok(x)) => Ok(x),
Some(Err(err)) => Err(Some(err)),
None => Err(None),
}
}
#[inline]
fn fv_opt<'a, V>(&'a self, field: &F) -> Option<Result<V, V::Error>>
where
V: FixValue<'a>,
{
self.fv_raw(field).map(|raw| match V::deserialize(raw) {
Ok(value) => Ok(value),
Err(err) => Err(err.into()),
})
}
#[inline]
fn fvl_opt<'a, V>(&'a self, field: &F) -> Option<Result<V, V::Error>>
where
V: FixValue<'a>,
{
self.fv_raw(field)
.map(|raw| match V::deserialize_lossy(raw) {
Ok(value) => Ok(value),
Err(err) => Err(err.into()),
})
}
}
pub trait RepeatingGroup: Sized {
type Entry;
fn len(&self) -> usize;
fn entry(&self, i: usize) -> Self::Entry;
fn entries(&self) -> Entries<Self> {
Entries {
group: self,
i: 0,
max_i_plus_one: self.len(),
}
}
}
#[derive(Debug, Clone)]
pub struct Entries<'a, G> {
group: &'a G,
i: usize,
max_i_plus_one: usize,
}
impl<'a, G> Iterator for Entries<'a, G>
where
G: RepeatingGroup,
{
type Item = G::Entry;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.max_i_plus_one {
None
} else {
let entry = self.group.entry(self.i);
self.i += 1;
Some(entry)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.group.len() - self.i;
(n, Some(n))
}
}
impl<'a, G> FusedIterator for Entries<'a, G> where G: RepeatingGroup {}
impl<'a, G> DoubleEndedIterator for Entries<'a, G>
where
G: RepeatingGroup,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.i == self.max_i_plus_one {
None
} else {
self.max_i_plus_one -= 1;
let entry = self.group.entry(self.max_i_plus_one);
Some(entry)
}
}
}
impl<'a, G> ExactSizeIterator for Entries<'a, G>
where
G: RepeatingGroup,
{
fn len(&self) -> usize {
self.group.len()
}
}