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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Module responsible for making [Point]s [Mentionable].

use std::marker::PhantomData;
use std::{error::Error, fmt::Display};

use crate::mode::*;
use crate::rcore::*;
use crate::rstd::inlining::*;

impl<'a, Ctx: Context<'a>, A: MentionableBase<'a>> Serializable for Point<'a, Ctx, A> {
    fn serialize(&self, serializer: &mut dyn Serializer) {
        serializer.write(&self.point)
    }
}

impl<'a, Ctx: Context<'a>, A: MentionableBase<'a>> MentionableBase<'a> for Point<'a, Ctx, A> {
    type Fctr = PointFactory<Ctx, A::Fctr>;

    fn factory(&self) -> Self::Fctr {
        PointFactory::new(self.origin.factory())
    }
}

impl<Ctx, F> PointFactory<Ctx, F> {
    fn new(factory: F) -> Self {
        Self {
            factory,
            _ctx: PhantomData,
        }
    }
}

impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableTop<'a, Ctx> for Point<'a, Ctx, A> {
    fn topology_hash(&self) -> Hash {
        Ctx::hash(&self.point)
    }

    fn points_typed(&self, points: &mut impl PointsVisitor<'a, Ctx>) {
        points.visit(self)
    }
}

pub struct PointFactory<Ctx, F> {
    factory: F,
    _ctx: PhantomData<Ctx>,
}

impl<Ctx, F: Clone> Clone for PointFactory<Ctx, F> {
    fn clone(&self) -> Self {
        Self::new(self.factory.clone())
    }
}

impl<Ctx, F: Clone> PointFactory<Ctx, F> {
    pub fn inner(&self) -> F {
        self.factory.clone()
    }
}

#[derive(Debug)]
pub enum PointParseError {
    WrongLength(usize),
}

impl Display for PointParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::WrongLength(length) => {
                write!(f, "expected {} bytes, received {}", HASH_SIZE, length)
            }
        }
    }
}

impl Error for PointParseError {}

impl From<&[u8]> for PointParseError {
    fn from(value: &[u8]) -> Self {
        PointParseError::WrongLength(value.len())
    }
}

impl<'a, Ctx: Context<'a>, A: MentionableBase<'a>> AsRef<[u8]> for Point<'a, Ctx, A> {
    fn as_ref(&self) -> &[u8] {
        &self.point
    }
}

impl<'a, Ctx: Context<'a>, F: FactoryBase<'a>> FactoryBase<'a> for PointFactory<Ctx, F> {
    type Mtbl = Point<'a, Ctx, F::Mtbl>;

    type ParseError = PointParseError;
}

impl<Ctx, F> ImplMode for PointFactory<Ctx, F> {
    type Mode = InliningMode;
}

impl<'a, Ctx: Context<'a>, F: FactoryBase<'a>> CInliningFactory<'a, Ctx> for PointFactory<Ctx, F> {
    fn cextension_error(&self, tail: &[u8]) -> Self::ParseError {
        PointParseError::WrongLength(HASH_SIZE + tail.len())
    }

    fn cideserialize<I: InCtx<'a, Ctx>>(&self, inctx: I) -> IParseResult<'a, Self, I> {
        inctx.icnext_point(self.inner(), PointParseError::from_ref)
    }
}

impl<Ctx, F> AlwaysConstSize for PointFactory<Ctx, F> {
    const ASIZE: usize = HASH_SIZE;
}