Skip to main content

detritus_protocol/
source.rs

1//! Source identity for observability payloads.
2
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6/// Identifies the game build and installation that produced a payload.
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct SourceId {
9    /// Project or product identifier.
10    pub project: String,
11    /// Runtime platform, such as `linux`, `windows`, or `android`.
12    pub platform: String,
13    /// User-facing application version.
14    pub version: String,
15    /// Stable installation identifier.
16    pub install_id: Uuid,
17}
18
19impl SourceId {
20    /// Returns `<project>/<platform>/<version>/<install_id>`.
21    ///
22    /// This canonical form is used in storage paths and rate-limit keys.
23    #[must_use]
24    pub fn canonical(&self) -> String {
25        format!(
26            "{}/{}/{}/{}",
27            self.project, self.platform, self.version, self.install_id
28        )
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    #[cfg_attr(coverage_nightly, coverage(off))]
38    fn canonical_joins_fields_with_slashes() {
39        // The canonical form is a storage-path and rate-limit-key contract, so
40        // pin its exact shape.
41        let source = SourceId {
42            project: "detritus".to_owned(),
43            platform: "linux".to_owned(),
44            version: "1.2.3".to_owned(),
45            install_id: Uuid::nil(),
46        };
47        assert_eq!(
48            source.canonical(),
49            "detritus/linux/1.2.3/00000000-0000-0000-0000-000000000000"
50        );
51    }
52}