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
use super::*;

/// Failure yielded by [`Origin`].
#[derive(Debug)]
pub enum ResolutionError<L, P> {
    /// Usually comes from [`Resolver::resolve`].
    Lookup(L),
    /// Usually comes from [`FactoryParse::deserialize`].
    Parse(P),
}

impl<L, P> ResolutionError<L, P> {
    /// Maps only the [`ResolutionError::Parse`] variant of the overall error.
    pub fn map_parse<Px>(self, f: impl FnOnce(P) -> Px) -> ResolutionError<L, Px> {
        match self {
            Self::Lookup(l) => ResolutionError::Lookup(l),
            Self::Parse(p) => ResolutionError::Parse(f(p)),
        }
    }
}

/// [`Context::LookupError`]. Mostly useful for `type` definitions.
pub type LookupError<'a, Ctx> = <Ctx as Context<'a>>::LookupError;

/// See [`ResolutionResult`].
pub type ResolutionFailure<'a, Ctx, A> = ResolutionError<LookupError<'a, Ctx>, ParseErrorA<'a, A>>;

/// Result yielded by [`Origin`].
pub type ResolutionResult<'a, Ctx, A> = Result<Arc<A>, ResolutionFailure<'a, Ctx, A>>;

/// Wrapped result returned by [`Origin`].
pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>;

/// Underlying [`Result`] of [`HashResolution`].
/// In case of success, contains byte data and the resolver for points appearing inside that data.
pub type HashResolutionResult<'a, Ctx> =
    Result<(Vec<u8>, Arc<dyn Resolver<'a, Ctx>>), LookupError<'a, Ctx>>;

/// Shorthand for the type of values returned by [`Resolver::resolve`].
pub type HashResolution<'a, Ctx> = Wrapped<'a, Ctx, HashResolutionResult<'a, Ctx>>;

/// Value accepted by [`Resolver::resolve`]. Includes index to make it order-sensitive.
#[derive(Clone, Copy, Debug)]
pub struct Address {
    pub point: Hash,
    /// Index of the point in the [`MentionableTop::points_typed()`].
    pub index: usize,
}

/// Trait representing the "rainbow table" behaviour.
pub trait Resolver<'a, Ctx: Context<'a>>: 'a + Send + Sync {
    /// Successfully returned value should be the inverse of the point passed
    /// with topology header ([`MentionableTop::topology_hash()`]) omitted.
    fn resolve(self: Arc<Self>, address: Address) -> HashResolution<'a, Ctx>;
}

/// [`ResolverMap::resolve_map`].
pub trait ResolverMap<'a, Ctx: Context<'a>>: Resolver<'a, Ctx> {
    /// Resolve the [Address], then map the [`HashResolutionResult`].
    fn resolve_map<T: 'a + Send>(
        self: Arc<Self>,
        address: Address,
        f: impl 'a + Send + FnOnce(HashResolutionResult<'a, Ctx>) -> T,
    ) -> Wrapped<'a, Ctx, T> {
        Ctx::fmap(self.resolve(address), f)
    }
}

impl<'a, Ctx: Context<'a>, R: ?Sized + Resolver<'a, Ctx>> ResolverMap<'a, Ctx> for R {}