Skip to main content

cubecl_environment/persistence/
namespace.rs

1use alloc::string::{String, ToString};
2
3/// Where a [`Store`](super::Store)'s entries live inside an environment: a
4/// `/`-separated location such as `autotune/0.11.0/cuda-0/matmul`.
5///
6/// The middle segment is this build's version, and the constructors inject it
7/// unconditionally: it is what makes entries written by one cubecl invisible
8/// to another, so a bundle built elsewhere can't be read as if it matched.
9/// The [`From`] impls are the escape hatch that skips versioning, for callers
10/// addressing an explicit [`Storage`](super::Storage) directly.
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct Namespace {
13    full: String,
14}
15
16/// The name used when none is given.
17const DEFAULT_NAME: &str = "cubecl";
18
19impl Namespace {
20    /// The namespace for `path` under the default name:
21    /// `cubecl/<version>/<path>`.
22    pub fn new<P: AsRef<str>>(path: P) -> Self {
23        Self::scoped(DEFAULT_NAME, path)
24    }
25
26    /// The namespace for `path` under `name`: `<name>/<version>/<path>`.
27    pub fn scoped<N: AsRef<str>, P: AsRef<str>>(name: N, path: P) -> Self {
28        let version = env!("CARGO_PKG_VERSION");
29        let name = name.as_ref();
30        let path = path.as_ref().trim_matches('/');
31
32        Self {
33            full: alloc::format!("{name}/{version}/{path}"),
34        }
35    }
36
37    /// The full `/`-separated namespace.
38    pub fn as_str(&self) -> &str {
39        &self.full
40    }
41}
42
43/// Verbatim, with no version segment injected.
44impl From<String> for Namespace {
45    fn from(full: String) -> Self {
46        Self { full }
47    }
48}
49
50/// Verbatim, with no version segment injected.
51impl From<&str> for Namespace {
52    fn from(full: &str) -> Self {
53        full.to_string().into()
54    }
55}
56
57impl core::fmt::Display for Namespace {
58    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59        f.write_str(&self.full)
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn constructors_inject_the_version() {
69        let version = env!("CARGO_PKG_VERSION");
70
71        assert_eq!(
72            Namespace::new("/device0/matmul/").as_str(),
73            alloc::format!("cubecl/{version}/device0/matmul")
74        );
75        assert_eq!(
76            Namespace::scoped("autotune", "cuda-0/matmul").as_str(),
77            alloc::format!("autotune/{version}/cuda-0/matmul")
78        );
79    }
80
81    #[test]
82    fn from_is_verbatim() {
83        assert_eq!(Namespace::from("bench/ns").as_str(), "bench/ns");
84    }
85}