pi/core/resources/
source_info.rs1use super::discovery::PathMetadata;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum SourceScope {
10 User,
12 Project,
14 Temporary,
16}
17
18impl SourceScope {
19 #[must_use]
21 pub const fn as_str(self) -> &'static str {
22 match self {
23 Self::User => "user",
24 Self::Project => "project",
25 Self::Temporary => "temporary",
26 }
27 }
28}
29
30#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32pub enum SourceOrigin {
33 Package,
35 TopLevel,
37}
38
39impl SourceOrigin {
40 #[must_use]
42 pub const fn as_str(self) -> &'static str {
43 match self {
44 Self::Package => "package",
45 Self::TopLevel => "top-level",
46 }
47 }
48}
49
50#[derive(Clone, Debug, Eq, PartialEq)]
52pub struct SourceInfo {
53 pub path: String,
55 pub source: String,
57 pub scope: SourceScope,
59 pub origin: SourceOrigin,
61 pub base_dir: Option<String>,
63}
64
65#[must_use]
67pub fn create_source_info(path: impl Into<String>, metadata: &PathMetadata) -> SourceInfo {
68 SourceInfo {
69 path: path.into(),
70 source: metadata.source.clone(),
71 scope: metadata.scope,
72 origin: metadata.origin,
73 base_dir: metadata.base_dir.clone(),
74 }
75}
76
77#[derive(Clone, Debug)]
79pub struct SyntheticSourceInfoOptions {
80 pub source: String,
82 pub scope: Option<SourceScope>,
84 pub origin: Option<SourceOrigin>,
86 pub base_dir: Option<String>,
88}
89
90#[must_use]
92pub fn create_synthetic_source_info(
93 path: impl Into<String>,
94 options: SyntheticSourceInfoOptions,
95) -> SourceInfo {
96 SourceInfo {
97 path: path.into(),
98 source: options.source,
99 scope: options.scope.unwrap_or(SourceScope::Temporary),
100 origin: options.origin.unwrap_or(SourceOrigin::TopLevel),
101 base_dir: options.base_dir,
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::core::resources::discovery::PathMetadata;
109
110 #[test]
111 fn create_source_info_copies_metadata() {
112 let metadata = PathMetadata {
113 source: "auto".into(),
114 scope: SourceScope::Project,
115 origin: SourceOrigin::TopLevel,
116 base_dir: Some("/tmp/.pi".into()),
117 };
118 let info = create_source_info("/tmp/.pi/skills/a.md", &metadata);
119 assert_eq!(info.path, "/tmp/.pi/skills/a.md");
120 assert_eq!(info.source, "auto");
121 assert_eq!(info.scope, SourceScope::Project);
122 assert_eq!(info.origin, SourceOrigin::TopLevel);
123 assert_eq!(info.base_dir.as_deref(), Some("/tmp/.pi"));
124 }
125
126 #[test]
127 fn synthetic_defaults_temporary_top_level() {
128 let info = create_synthetic_source_info(
129 "/x",
130 SyntheticSourceInfoOptions {
131 source: "local".into(),
132 scope: None,
133 origin: None,
134 base_dir: None,
135 },
136 );
137 assert_eq!(info.scope, SourceScope::Temporary);
138 assert_eq!(info.origin, SourceOrigin::TopLevel);
139 assert_eq!(info.source, "local");
140 }
141}