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
use bluejay_core::executable::ExecutableDocument;
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::hash::{Hash, Hasher};

pub struct Path<'a, E: ExecutableDocument> {
    root: PathRoot<'a, E>,
    members: Vec<&'a E::Selection>,
}

impl<'a, E: ExecutableDocument> Clone for Path<'a, E> {
    fn clone(&self) -> Self {
        Self {
            root: self.root,
            members: self.members.clone(),
        }
    }
}

impl<'a, E: ExecutableDocument> Path<'a, E> {
    pub fn new(root: PathRoot<'a, E>) -> Self {
        Self {
            root,
            members: Vec::new(),
        }
    }

    pub fn root(&self) -> &PathRoot<'a, E> {
        &self.root
    }

    pub fn with_selection(&self, selection: &'a E::Selection) -> Self {
        let mut clone = self.clone();
        clone.members.push(selection);
        clone
    }
}

pub enum PathRoot<'a, E: ExecutableDocument> {
    Operation(&'a E::OperationDefinition),
    Fragment(&'a E::FragmentDefinition),
}

impl<'a, E: ExecutableDocument> Clone for PathRoot<'a, E> {
    fn clone(&self) -> Self {
        match self {
            Self::Operation(o) => Self::Operation(o),
            Self::Fragment(f) => Self::Fragment(f),
        }
    }
}

impl<'a, E: ExecutableDocument> Copy for PathRoot<'a, E> {}

impl<'a, E: ExecutableDocument> Hash for PathRoot<'a, E> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            Self::Operation(o) => o.hash(state),
            Self::Fragment(f) => f.hash(state),
        }
    }
}

impl<'a, E: ExecutableDocument> PartialEq for PathRoot<'a, E> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Operation(l), Self::Operation(r)) if l == r => true,
            (Self::Fragment(l), Self::Fragment(r)) if l == r => true,
            _ => false,
        }
    }
}

impl<'a, E: ExecutableDocument> Eq for PathRoot<'a, E> {}

impl<'a, E: ExecutableDocument> Ord for PathRoot<'a, E> {
    fn cmp(&self, other: &Self) -> Ordering {
        match (self, other) {
            (Self::Fragment(l), Self::Fragment(r)) => l.cmp(r),
            (Self::Fragment(_), Self::Operation(_)) => Ordering::Greater,
            (Self::Operation(_), Self::Fragment(_)) => Ordering::Less,
            (Self::Operation(l), Self::Operation(r)) => l.cmp(r),
        }
    }
}

impl<'a, E: ExecutableDocument> PartialOrd for PathRoot<'a, E> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}