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 std::sync::Arc;

use crate::rcore::*;

use super::{singular::*, *};

pub trait CastMentionable<'a, Ctx: Context<'a>>: Mentionable<'a, Ctx> {
    fn m_cast<A: Mentionable<'a, Ctx>>(&self, factory: &Fctr<'a, A>) -> ParseResultA<'a, A> {
        factory.parse_slice(
            &self.bytes(),
            &SingularResolver::from_mentionable(self).into_rc(),
        )
    }
}

impl<'a, Ctx: Context<'a>, B: Mentionable<'a, Ctx>> CastMentionable<'a, Ctx> for B {}

struct CastedOrigin<O: ?Sized, F> {
    origin: Arc<O>,
    factory: F,
}

impl<'a, Ctx: Context<'a>, O: ?Sized + Origin<'a, Ctx>, F: Factory<'a, Ctx>> Origin<'a, Ctx>
    for CastedOrigin<O, F>
{
    type Mtbl = F::Mtbl;

    fn factory(&self) -> OFctr<'a, Ctx, Self> {
        self.factory.clone()
    }

    fn resolve(self: Arc<Self>) -> Resolution<'a, Ctx, Self::Mtbl>
    where
        OFctr<'a, Ctx, Self>: FactoryParse<'a, Ctx>,
    {
        self.clone().origin.resolve_bytes_map(move |resolved| {
            resolved
                .map_err(ResolutionError::Lookup)
                .and_then(|(src, resolver)| {
                    self.factory
                        .parse_slice(&src, &resolver)
                        .map_err(ResolutionError::Parse)
                })
                .map(Arc::new)
        })
    }

    fn resolve_bytes(self: Arc<Self>) -> HashResolution<'a, Ctx> {
        self.origin.ref_resolve_bytes()
    }
}

pub trait CastOrigin<'a, Ctx: Context<'a>>: Origin<'a, Ctx> {
    fn o_cast<A: Mentionable<'a, Ctx>>(
        self: &Arc<Self>,
        factory: Fctr<'a, A>,
    ) -> Arc<dyn Origin<'a, Ctx, Mtbl = A>> {
        Arc::new(CastedOrigin {
            origin: self.clone(),
            factory,
        }) as _
    }
}

impl<'a, Ctx: Context<'a>, O: ?Sized + Origin<'a, Ctx>> CastOrigin<'a, Ctx> for O {}

pub trait CastPoint<'a, Ctx: Context<'a>> {
    fn p_cast<A: Mentionable<'a, Ctx>>(self, factory: Fctr<'a, A>) -> Point<'a, Ctx, A>;
}

impl<'a, Ctx: Context<'a>, B: Mentionable<'a, Ctx>> CastPoint<'a, Ctx> for Point<'a, Ctx, B> {
    fn p_cast<A: Mentionable<'a, Ctx>>(self, factory: Fctr<'a, A>) -> Point<'a, Ctx, A> {
        Point {
            point: self.point,
            origin: self.origin.o_cast(factory),
        }
    }
}