ifc_validate/report/
path.rs1use std::fmt;
4
5use ifc_model::EntityId;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub enum Path {
14 File,
16 Entity(EntityId),
18 Attribute {
20 entity: EntityId,
22 index: usize,
24 name: Option<String>,
26 },
27}
28
29impl fmt::Display for Path {
30 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::File => formatter.write_str("<file>"),
33 Self::Entity(id) => write!(formatter, "{id}"),
34 Self::Attribute {
35 entity,
36 index,
37 name,
38 } => match name {
39 Some(name) => write!(formatter, "{entity}.{name}"),
40 None => write!(formatter, "{entity}[{index}]"),
41 },
42 }
43 }
44}
45
46#[must_use]
51pub(crate) fn path_key(path: &Path) -> (u64, usize) {
52 match path {
53 Path::File => (0, 0),
54 Path::Entity(id) => (id.0, 0),
55 Path::Attribute { entity, index, .. } => (entity.0, *index + 1),
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn an_attribute_path_names_the_slot_when_the_schema_does() {
65 let named = Path::Attribute {
66 entity: EntityId(7),
67 index: 2,
68 name: Some("Name".into()),
69 };
70 assert_eq!(named.to_string(), "#7.Name");
71 let anonymous = Path::Attribute {
72 entity: EntityId(7),
73 index: 2,
74 name: None,
75 };
76 assert_eq!(anonymous.to_string(), "#7[2]");
77 }
78
79 #[test]
81 fn the_file_path_sorts_first() {
82 assert!(path_key(&Path::File) < path_key(&Path::Entity(EntityId(1))));
83 }
84}