1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::buf::{Buf, Load};
use crate::endian::ByteOrder;
use crate::error::Error;
use crate::pointer::{Pointee, Ref, Size};

/// Trait used for accessing the value behind a reference when interacting with
/// higher level containers such as [`phf`] or [`swiss`].
///
/// This is a high level trait which can be implemented safely, typically it's
/// used to build facade types for when you want some type to behave like a
/// different type, but have a different layout.
///
/// See the [module level documentation][crate::buf#extension-traits] for an
/// example.
///
/// [`phf`]: crate::phf
/// [`swiss`]: crate::swiss
pub trait Visit {
    /// The target type being visited.
    type Target: ?Sized;

    /// Validate the value.
    fn visit<V, O>(&self, buf: &Buf, visitor: V) -> Result<O, Error>
    where
        V: FnOnce(&Self::Target) -> O;
}

impl<T: ?Sized> Visit for &T {
    type Target = T;

    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
    where
        V: FnOnce(&Self::Target) -> O,
    {
        Ok(visitor(*self))
    }
}

impl<T: ?Sized, E: ByteOrder, O: Size> Visit for Ref<T, E, O>
where
    T: Pointee,
    Self: Load,
{
    type Target = <Ref<T, E, O> as Load>::Target;

    #[inline]
    fn visit<V, U>(&self, buf: &Buf, visitor: V) -> Result<U, Error>
    where
        V: FnOnce(&Self::Target) -> U,
    {
        let value = buf.load(*self)?;
        Ok(visitor(value))
    }
}

impl Visit for str {
    type Target = str;

    #[inline]
    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
    where
        V: FnOnce(&Self::Target) -> O,
    {
        Ok(visitor(self))
    }
}

impl<T> Visit for [T] {
    type Target = [T];

    #[inline]
    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
    where
        V: FnOnce(&Self::Target) -> O,
    {
        Ok(visitor(self))
    }
}