use crate::PrfVisitorError;
pub enum ResolvedPrf<Block, Passthrough> {
Block(Block),
Sequence(Vec<ResolvedPrf<Block, Passthrough>>),
Map(Vec<(String, ResolvedPrf<Block, Passthrough>)>),
Absent,
Passthrough(Passthrough),
}
impl<Block, Passthrough> ResolvedPrf<Block, Passthrough> {
pub fn visit<V>(self, visitor: V) -> Result<V::Value, PrfVisitorError>
where
V: PrfVisitor<Block, Passthrough>,
{
match self {
Self::Block(block) => visitor.visit_block(block),
Self::Sequence(values) => visitor.visit_seq(SeqAccess::new(values)),
Self::Map(entries) => visitor.visit_map(MapAccess::new(entries)),
Self::Absent => visitor.visit_absent(),
Self::Passthrough(value) => visitor.visit_passthrough(value),
}
}
}
pub struct SeqAccess<Block, Passthrough> {
values: std::vec::IntoIter<ResolvedPrf<Block, Passthrough>>,
}
impl<Block, Passthrough> SeqAccess<Block, Passthrough> {
pub fn new(values: Vec<ResolvedPrf<Block, Passthrough>>) -> Self {
Self {
values: values.into_iter(),
}
}
pub fn next_node(&mut self) -> Option<ResolvedPrf<Block, Passthrough>> {
self.values.next()
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn is_empty(&self) -> bool {
self.values.len() == 0
}
}
impl<Block, Passthrough> Iterator for SeqAccess<Block, Passthrough> {
type Item = ResolvedPrf<Block, Passthrough>;
fn next(&mut self) -> Option<Self::Item> {
self.next_node()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.values.size_hint()
}
}
impl<Block, Passthrough> ExactSizeIterator for SeqAccess<Block, Passthrough> {}
pub struct MapAccess<Block, Passthrough> {
entries: std::vec::IntoIter<(String, ResolvedPrf<Block, Passthrough>)>,
}
impl<Block, Passthrough> MapAccess<Block, Passthrough> {
pub fn new(entries: Vec<(String, ResolvedPrf<Block, Passthrough>)>) -> Self {
Self {
entries: entries.into_iter(),
}
}
pub fn next_entry(&mut self) -> Option<(String, ResolvedPrf<Block, Passthrough>)> {
self.entries.next()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.len() == 0
}
}
impl<Block, Passthrough> Iterator for MapAccess<Block, Passthrough> {
type Item = (String, ResolvedPrf<Block, Passthrough>);
fn next(&mut self) -> Option<Self::Item> {
self.next_entry()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.entries.size_hint()
}
}
impl<Block, Passthrough> ExactSizeIterator for MapAccess<Block, Passthrough> {}
#[cfg(test)]
mod access_tests {
use super::{MapAccess, ResolvedPrf, SeqAccess};
#[test]
fn sequence_access_reports_its_exact_remaining_length() {
let mut seq = SeqAccess::<u8, ()>::new(vec![ResolvedPrf::Block(1), ResolvedPrf::Block(2)]);
assert_eq!(seq.len(), 2);
assert_eq!(seq.size_hint(), (2, Some(2)));
assert!(!seq.is_empty());
assert!(seq.next().is_some());
assert_eq!(seq.len(), 1);
assert!(seq.next().is_some());
assert_eq!(seq.size_hint(), (0, Some(0)));
assert!(seq.is_empty());
}
#[test]
fn map_access_reports_its_exact_remaining_length() {
let mut map = MapAccess::<u8, ()>::new(vec![
(String::from("one"), ResolvedPrf::Block(1)),
(String::from("two"), ResolvedPrf::Block(2)),
]);
assert_eq!(map.len(), 2);
assert_eq!(map.size_hint(), (2, Some(2)));
assert!(!map.is_empty());
assert!(map.next().is_some());
assert_eq!(map.len(), 1);
assert!(map.next().is_some());
assert_eq!(map.size_hint(), (0, Some(0)));
assert!(map.is_empty());
}
}
pub trait PrfVisitor<Block, Passthrough>: Sized + 'static {
type Value: Send + 'static;
fn visit_block(self, _block: Block) -> Result<Self::Value, PrfVisitorError> {
Err(PrfVisitorError::UnexpectedShape)
}
fn visit_seq(
self,
_seq: SeqAccess<Block, Passthrough>,
) -> Result<Self::Value, PrfVisitorError> {
Err(PrfVisitorError::UnexpectedShape)
}
fn visit_map(
self,
_map: MapAccess<Block, Passthrough>,
) -> Result<Self::Value, PrfVisitorError> {
Err(PrfVisitorError::UnexpectedShape)
}
fn visit_absent(self) -> Result<Self::Value, PrfVisitorError> {
Err(PrfVisitorError::UnexpectedShape)
}
fn visit_passthrough(self, _value: Passthrough) -> Result<Self::Value, PrfVisitorError> {
Err(PrfVisitorError::UnexpectedShape)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BlockVisitor;
impl<Block, Passthrough> PrfVisitor<Block, Passthrough> for BlockVisitor
where
Block: Send + 'static,
{
type Value = Block;
fn visit_block(self, block: Block) -> Result<Self::Value, PrfVisitorError> {
Ok(block)
}
}
impl<Block, Passthrough> PrfVisitor<Block, Passthrough> for ResolvedVisitor
where
Block: Send + 'static,
Passthrough: Send + 'static,
{
type Value = ResolvedPrf<Block, Passthrough>;
fn visit_block(self, block: Block) -> Result<Self::Value, PrfVisitorError> {
Ok(ResolvedPrf::Block(block))
}
fn visit_seq(self, seq: SeqAccess<Block, Passthrough>) -> Result<Self::Value, PrfVisitorError> {
Ok(ResolvedPrf::Sequence(seq.collect()))
}
fn visit_map(self, map: MapAccess<Block, Passthrough>) -> Result<Self::Value, PrfVisitorError> {
Ok(ResolvedPrf::Map(map.collect()))
}
fn visit_absent(self) -> Result<Self::Value, PrfVisitorError> {
Ok(ResolvedPrf::Absent)
}
fn visit_passthrough(self, value: Passthrough) -> Result<Self::Value, PrfVisitorError> {
Ok(ResolvedPrf::Passthrough(value))
}
}
#[derive(Clone, Copy)]
pub struct ResolvedVisitor;