meshed/identify.rs
1/*
2 * Copyright [2022] [Kevin Velasco]
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use std::fmt::{Debug, Display};
18use std::hash::Hash;
19use std::ops::Deref;
20
21/// Marker trait that some type corresponds to the identity of
22/// some value. Used for graph traversal book-keeping (seen set, querying, etc)
23///
24/// This type must be cheaply clonable. Clones that re-allocate will negatively affect
25/// performance of graph traversal
26pub trait Identity: Hash + PartialEq + Eq + PartialOrd + Ord + Clone + Display + Debug {
27 fn escaped(&self) -> String {
28 let id = self.to_string();
29
30 let mut output = String::new();
31 let mut chars = id.chars();
32
33 if let Some(first) = chars.next() {
34 if first.is_ascii_alphabetic() || first == '_' {
35 output.push(first);
36 } else if first.is_ascii_alphanumeric() {
37 output.push('_');
38 output.push(first);
39 } else {
40 output.push('_');
41 }
42 }
43
44 for character in chars {
45 if character.is_ascii_alphanumeric() || character == '_' {
46 output.push(character)
47 } else {
48 output.push('_')
49 }
50 }
51
52 output
53 }
54}
55
56macro_rules! impl_identity {
57 ($($t:ty) +) => {
58 $(impl Identity for $t {})*
59 }
60}
61
62impl_identity! {
63 i8 u8 i16 u16 i32 u32 i64 u64
64 usize isize
65 &'static str
66}
67
68/// A type is able to extract an Identifer from itself. The identifier
69/// type is provided as an argument to the trait
70///
71/// struct Module {
72/// id: Identifier
73/// }
74///
75/// impl Identity for Identity {}
76///
77/// impl Identifialbe<Identity> for Module {
78/// fn get_id(&self) -> Identity::Id {
79/// &self.id
80/// }
81/// }
82pub trait Identifiable<T: Identity> {
83 fn get_id(&self) -> T;
84}
85
86impl<T, I: Identity, D> Identifiable<I> for D
87where
88 T: Identifiable<I>,
89 D: Deref<Target = T>,
90{
91 fn get_id(&self) -> I {
92 self.deref().get_id()
93 }
94}