tfparser_core/ir/
files.rs1use std::{path::Path, sync::Arc};
10
11use serde::{Deserialize, Serialize};
12use typed_builder::TypedBuilder;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[serde(rename_all = "kebab-case")]
17#[non_exhaustive]
18pub enum FileExt {
19 Tf,
21 Tfvars,
23 Hcl,
25 TerragruntHcl,
28 Json,
31}
32
33impl FileExt {
34 #[must_use]
44 pub fn classify(path: &Path) -> Option<Self> {
45 let name = path.file_name()?.to_str()?;
46 if name == "terragrunt.hcl" {
47 return Some(Self::TerragruntHcl);
48 }
49 let ext = path.extension()?.to_str()?;
50 match ext {
51 "tf" => Some(Self::Tf),
52 "tfvars" => Some(Self::Tfvars),
53 "hcl" => Some(Self::Hcl),
54 "json" => Some(Self::Json),
55 _ => None,
56 }
57 }
58
59 #[must_use]
62 pub const fn is_hcl(self) -> bool {
63 matches!(
64 self,
65 Self::Tf | Self::Hcl | Self::TerragruntHcl | Self::Tfvars
66 )
67 }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, TypedBuilder)]
74#[non_exhaustive]
75#[serde(rename_all = "camelCase")]
76#[builder(field_defaults(setter(into)))]
77pub struct SourceFile {
78 #[serde(with = "crate::ir::path_serde::arc_path")]
80 pub path: Arc<Path>,
81 pub ext: FileExt,
83 pub size: u64,
85}
86
87#[cfg(test)]
88mod tests {
89 use std::path::PathBuf;
90
91 use super::*;
92
93 #[test]
94 fn test_should_classify_terraform_extensions() {
95 assert_eq!(
96 FileExt::classify(&PathBuf::from("main.tf")),
97 Some(FileExt::Tf)
98 );
99 assert_eq!(
100 FileExt::classify(&PathBuf::from("prod.tfvars")),
101 Some(FileExt::Tfvars)
102 );
103 assert_eq!(
104 FileExt::classify(&PathBuf::from("root.hcl")),
105 Some(FileExt::Hcl)
106 );
107 assert_eq!(
108 FileExt::classify(&PathBuf::from("path/to/terragrunt.hcl")),
109 Some(FileExt::TerragruntHcl)
110 );
111 assert_eq!(
112 FileExt::classify(&PathBuf::from("policy.json")),
113 Some(FileExt::Json)
114 );
115 }
116
117 #[test]
118 fn test_should_reject_unknown_extension() {
119 assert!(FileExt::classify(&PathBuf::from("README.md")).is_none());
120 }
121
122 #[test]
123 fn test_should_classify_hcl_files_as_hcl_input() {
124 for ext in [
125 FileExt::Tf,
126 FileExt::Tfvars,
127 FileExt::Hcl,
128 FileExt::TerragruntHcl,
129 ] {
130 assert!(ext.is_hcl(), "{ext:?} should be HCL-shaped");
131 }
132 assert!(!FileExt::Json.is_hcl());
133 }
134}