tf_bindgen_core/
path.rs

1use std::fmt::{Display, Formatter, Write};
2
3use sha1::{Digest, Sha1};
4
5/// Used to store the id of a construct.
6#[derive(Clone)]
7pub struct Path {
8    segments: Vec<String>,
9}
10
11impl Path {
12    /// Returns the name of the associated object.
13    pub fn name(&self) -> &str {
14        self.segments
15            .iter()
16            .last()
17            .expect("Path expects at least one element")
18    }
19
20    /// Returns the id of this object.
21    pub fn id(&self) -> String {
22        let name = self.name();
23        let mut hasher = Sha1::default();
24        for segment in &self.segments {
25            hasher.update(segment);
26        }
27        let hash: String = hasher
28            .finalize()
29            .as_slice()
30            .iter()
31            .map(|by| format!("{by:x}"))
32            .collect();
33        format!("{name}-{hash}")
34    }
35
36    /// Extend this path with new `identifier`.
37    pub fn push(&mut self, identifier: impl Into<String>) {
38        self.segments.push(identifier.into())
39    }
40}
41
42impl From<String> for Path {
43    fn from(segment: String) -> Self {
44        Path {
45            segments: vec![segment],
46        }
47    }
48}
49
50impl From<Vec<String>> for Path {
51    fn from(segments: Vec<String>) -> Self {
52        Path { segments }
53    }
54}
55
56impl Display for Path {
57    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58        if let Some(first) = self.segments.first() {
59            f.write_str(first)?;
60        }
61        for segment in self.segments.iter().skip(1) {
62            f.write_char('/')?;
63            f.write_str(segment)?;
64        }
65        Ok(())
66    }
67}