microcad_lang/src_ref/
refer.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::src_ref::*;
5use derive_more::{Deref, DerefMut};
6
7/// Packs any value together with a source reference
8#[derive(Clone, Default, Ord, PartialEq, PartialOrd, Deref, DerefMut)]
9pub struct Refer<T> {
10    /// Value
11    #[deref]
12    #[deref_mut]
13    pub value: T,
14    /// Source code reference
15    pub src_ref: SrcRef,
16}
17
18impl<T> Refer<T> {
19    /// Create a `Refer` instance without source code reference
20    pub fn none(value: T) -> Self {
21        Self {
22            value,
23            src_ref: SrcRef(None),
24        }
25    }
26    /// Create a `Refer` instance with source code reference
27    pub fn new(value: T, src_ref: SrcRef) -> Self {
28        Self { value, src_ref }
29    }
30    /// Create a `Refer` instance with two source code references
31    #[cfg(test)]
32    pub fn merge<U, V>(left: Refer<U>, right: Refer<V>, f: fn(U, V) -> T) -> Self {
33        Self {
34            value: f(left.value, right.value),
35            src_ref: SrcRef::merge(&left.src_ref, &right.src_ref),
36        }
37    }
38    /// Map a `Refer` instance to a new one
39    pub fn map<U>(self, f: fn(T) -> U) -> Refer<U> {
40        Refer::<U> {
41            value: f(self.value),
42            src_ref: self.src_ref,
43        }
44    }
45}
46
47impl<T> SrcReferrer for Refer<T> {
48    fn src_ref(&self) -> SrcRef {
49        self.src_ref.clone()
50    }
51}
52
53impl<T: Eq> Eq for Refer<T> {}
54
55impl<T: std::fmt::Display> std::fmt::Display for Refer<T> {
56    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
57        self.value.fmt(f)
58    }
59}
60impl<T: std::fmt::Debug> std::fmt::Debug for Refer<T> {
61    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
62        write!(f, "{:?}, Refer: {:?}", self.value, self.src_ref)
63    }
64}
65
66impl<T: std::hash::Hash> std::hash::Hash for Refer<T> {
67    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
68        self.value.hash(state);
69    }
70}
71
72impl<T: std::iter::IntoIterator> std::iter::IntoIterator for Refer<T> {
73    type Item = T::Item;
74    type IntoIter = T::IntoIter;
75
76    fn into_iter(self) -> Self::IntoIter {
77        self.value.into_iter()
78    }
79}