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
/*
* Copyright [2022] [Kevin Velasco]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::ops::Deref;
/// Marker trait that some type corresponds to the identity of
/// some value. Used for graph traversal book-keeping (seen set, querying, etc)
///
/// This type must be cheaply clonable. Clones that re-allocate will negatively affect
/// performance of graph traversal
pub trait Identity: Hash + PartialEq + Eq + PartialOrd + Ord + Clone + Display + Debug {
fn escaped(&self) -> String {
let id = self.to_string();
let mut output = String::new();
let mut chars = id.chars();
if let Some(first) = chars.next() {
if first.is_ascii_alphabetic() || first == '_' {
output.push(first);
} else if first.is_ascii_alphanumeric() {
output.push('_');
output.push(first);
} else {
output.push('_');
}
}
for character in chars {
if character.is_ascii_alphanumeric() || character == '_' {
output.push(character)
} else {
output.push('_')
}
}
output
}
}
macro_rules! impl_identity {
($($t:ty) +) => {
$(impl Identity for $t {})*
}
}
impl_identity! {
i8 u8 i16 u16 i32 u32 i64 u64
usize isize
&'static str
}
/// A type is able to extract an Identifer from itself. The identifier
/// type is provided as an argument to the trait
///
/// struct Module {
/// id: Identifier
/// }
///
/// impl Identity for Identity {}
///
/// impl Identifialbe<Identity> for Module {
/// fn get_id(&self) -> Identity::Id {
/// &self.id
/// }
/// }
pub trait Identifiable<T: Identity> {
fn get_id(&self) -> T;
}
impl<T, I: Identity, D> Identifiable<I> for D
where
T: Identifiable<I>,
D: Deref<Target = T>,
{
fn get_id(&self) -> I {
self.deref().get_id()
}
}