sara_core/model/
metadata.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::path::PathBuf;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct SourceLocation {
10 pub repository: PathBuf,
12
13 pub file_path: PathBuf,
15
16 pub line: usize,
18
19 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub git_ref: Option<String>,
22}
23
24impl SourceLocation {
25 pub fn new(repository: impl Into<PathBuf>, file_path: impl Into<PathBuf>, line: usize) -> Self {
27 Self {
28 repository: repository.into(),
29 file_path: file_path.into(),
30 line,
31 git_ref: None,
32 }
33 }
34
35 pub fn with_git_ref(
37 repository: impl Into<PathBuf>,
38 file_path: impl Into<PathBuf>,
39 line: usize,
40 git_ref: impl Into<String>,
41 ) -> Self {
42 Self {
43 repository: repository.into(),
44 file_path: file_path.into(),
45 line,
46 git_ref: Some(git_ref.into()),
47 }
48 }
49
50 pub fn full_path(&self) -> PathBuf {
52 self.repository.join(&self.file_path)
53 }
54
55 pub fn display(&self) -> String {
57 format!("{}:{}", self.file_path.display(), self.line)
58 }
59
60 pub fn display_full(&self) -> String {
62 if let Some(ref git_ref) = self.git_ref {
63 format!(
64 "{}:{}:{} (at {})",
65 self.repository.display(),
66 self.file_path.display(),
67 self.line,
68 git_ref
69 )
70 } else {
71 format!(
72 "{}:{}:{}",
73 self.repository.display(),
74 self.file_path.display(),
75 self.line
76 )
77 }
78 }
79}
80
81impl fmt::Display for SourceLocation {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}", self.display())
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_source_location_display() {
93 let loc = SourceLocation::new("/repo", "docs/SOL-001.md", 5);
94 assert_eq!(loc.display(), "docs/SOL-001.md:5");
95 }
96
97 #[test]
98 fn test_source_location_full_path() {
99 let loc = SourceLocation::new("/repo", "docs/SOL-001.md", 5);
100 assert_eq!(loc.full_path(), PathBuf::from("/repo/docs/SOL-001.md"));
101 }
102
103 #[test]
104 fn test_source_location_with_git_ref() {
105 let loc = SourceLocation::with_git_ref("/repo", "docs/SOL-001.md", 5, "main");
106 assert_eq!(loc.git_ref, Some("main".to_string()));
107 }
108}