mmap_vec/
segment_builder.rs

1use std::{
2    env, fs, io,
3    path::{Path, PathBuf},
4    sync::Arc,
5};
6
7use uuid::Uuid;
8
9/// Trait that contains everything we need to deals with unique segment creation.
10pub trait SegmentBuilder: Default {
11    /// Create path for new unique segment.
12    fn new_segment_path(&self) -> PathBuf;
13}
14
15/// Default implementation for `SegmentBuilder` trait.
16#[derive(Debug, Clone)]
17pub struct DefaultSegmentBuilder {
18    /// Base folder where all segment will be created.
19    ///
20    /// When custom segment builder is used, this struct will be clone and
21    /// associated to every vec. So using `Arc` save some memory space here.
22    /// Performances impact for reading it is negligible compared to new segment creation.
23    store_path: Arc<PathBuf>,
24}
25
26impl DefaultSegmentBuilder {
27    /// Init struct with given path.
28    ///
29    /// Folder needs to exists and have correct permissions.
30    /// This will not be checked here and it is the responsibility of the user to do
31    /// this work.
32    ///
33    /// In case folder does not exists segment creation may failed.
34    #[inline(always)]
35    pub fn with_path<P: AsRef<Path>>(store_path: P) -> Self {
36        Self {
37            store_path: Arc::new(store_path.as_ref().to_path_buf()),
38        }
39    }
40
41    /// Make sure store folder exists.
42    #[inline]
43    pub fn create_dir_all(&self) -> io::Result<()> {
44        fs::create_dir_all(self.store_path.as_ref())
45    }
46}
47
48impl Default for DefaultSegmentBuilder {
49    fn default() -> Self {
50        #[cfg(not(feature = "cache-dir"))]
51        let mut path = env::temp_dir();
52        #[cfg(feature = "cache-dir")]
53        let mut path = dirs::cache_dir().unwrap_or_else(env::temp_dir);
54
55        path.push("mmap-vec-rs");
56
57        let out = Self::with_path(path);
58
59        // Ignore create dir fail
60        let _ = out.create_dir_all();
61
62        out
63    }
64}
65
66impl SegmentBuilder for DefaultSegmentBuilder {
67    fn new_segment_path(&self) -> PathBuf {
68        let segment_id = Uuid::new_v4().as_hyphenated().to_string();
69        self.store_path.join(format!("{segment_id}.seg"))
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_uniqueness() {
79        let builder = DefaultSegmentBuilder::default();
80        let path1 = builder.new_segment_path();
81        let path2 = builder.new_segment_path();
82        assert_ne!(path1, path2);
83    }
84}