Skip to main content

oino_resources/
source.rs

1//! Resource provenance (`source-info`, `PathMetadata`).
2
3use std::path::{Path, PathBuf};
4
5use serde::{Deserialize, Serialize};
6
7/// Where a resource was configured.
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "lowercase")]
10pub enum SourceScope {
11    /// Agent dir / user settings.
12    User,
13    /// Project `.oino` / project settings / project `.agents`.
14    Project,
15    /// CLI flags or other session-only sources.
16    #[default]
17    Temporary,
18}
19
20/// Whether a resource came from a package or a top-level path.
21#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[serde(rename_all = "kebab-case")]
23pub enum SourceOrigin {
24    /// Provided by an installed package.
25    Package,
26    /// A path from settings, auto-discovery or the CLI.
27    #[default]
28    TopLevel,
29}
30
31/// Resolution metadata of a discovered path.
32#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(rename_all = "camelCase")]
34pub struct PathMetadata {
35    /// `auto`, `local`, `cli`, a package source, … (a free string).
36    pub source: String,
37    /// Scope.
38    pub scope: SourceScope,
39    /// Origin.
40    pub origin: SourceOrigin,
41    /// Directory relative entries resolve against.
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub base_dir: Option<PathBuf>,
44}
45
46/// Provenance attached to a loaded resource.
47#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub struct SourceInfo {
50    /// Resource path.
51    pub path: PathBuf,
52    /// Source kind (see [`PathMetadata::source`]).
53    pub source: String,
54    /// Scope.
55    pub scope: SourceScope,
56    /// Origin.
57    pub origin: SourceOrigin,
58    /// Base dir.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub base_dir: Option<PathBuf>,
61}
62
63impl SourceInfo {
64    /// C r e a t e   S o u r c e   I n f o.
65    #[must_use]
66    pub fn from_metadata(path: &Path, metadata: &PathMetadata) -> Self {
67        Self {
68            path: path.to_path_buf(),
69            source: metadata.source.clone(),
70            scope: metadata.scope,
71            origin: metadata.origin,
72            base_dir: metadata.base_dir.clone(),
73        }
74    }
75
76    /// Creates synthetic source info (scope defaults to temporary, origin to top-level).
77    #[must_use]
78    pub fn synthetic(
79        path: &Path,
80        source: &str,
81        scope: Option<SourceScope>,
82        base_dir: Option<PathBuf>,
83    ) -> Self {
84        Self {
85            path: path.to_path_buf(),
86            source: source.to_owned(),
87            scope: scope.unwrap_or_default(),
88            origin: SourceOrigin::TopLevel,
89            base_dir,
90        }
91    }
92}