taubyte_sdk/storage/
files.rs

1use super::file::{File, VersionedFile};
2use super::{imports, Storage};
3use crate::errno::Error;
4
5impl Storage {
6    pub fn file(&self, file_name: &str) -> File {
7        File::new(self.id, file_name)
8    }
9
10    fn file_versioned(&self, file_name: &str, version: u32) -> VersionedFile {
11        VersionedFile::new(File::new(self.id, file_name), version)
12    }
13
14    fn list_files_size_unsafe(&self, size: *mut usize) -> Error {
15        #[allow(unused_unsafe)]
16        unsafe {
17            imports::storageListFilesSize(self.id, size)
18        }
19    }
20
21    fn list_files_unsafe(&self, files: *mut u8) -> Error {
22        #[allow(unused_unsafe)]
23        unsafe {
24            imports::storageListFiles(self.id, files)
25        }
26    }
27
28    pub fn list_files(&self) -> Result<Vec<VersionedFile>, Box<dyn std::error::Error>> {
29        let mut size: usize = 0;
30        let err = self.list_files_size_unsafe(&mut size);
31        if err.is_err() {
32            return Err(format!("Failed storage list file size with {}", err).into());
33        }
34
35        let mut buf = vec![0_u8; size];
36        let err = self.list_files_unsafe(&mut buf[0]);
37        if err.is_err() {
38            return Err(format!("Failed storage list files with {}", err).into());
39        }
40
41        let mut files: Vec<VersionedFile> = Vec::new();
42
43        let values = String::from_utf8(buf)?;
44        let values_split = values.split('/');
45        let values: Vec<&str> = values_split.collect();
46        for (idx, value) in values.iter().enumerate() {
47            if *value == "file" && values[idx + 1] != "file" {
48                let version = values[idx + 2].trim_matches('\x00');
49                let version = version.parse::<u32>()?;
50                files.push(self.file_versioned(values[idx + 1], version));
51            }
52            continue;
53        }
54
55        Ok(files)
56    }
57}
58
59#[cfg(test)]
60pub mod test {
61    use crate::storage::file::{File, VersionedFile};
62    use crate::storage::new::test as new_test;
63    use crate::storage::Storage;
64
65    pub static FILE_STR: &str = "file/file1/1/file/file2/1/file/file3/2";
66
67    #[test]
68    fn list_files() {
69        let storage = Storage::new(new_test::STORAGE_NAME).unwrap_or_else(|err| {
70            panic!("{}", err);
71        });
72
73        let files = storage.list_files().unwrap_or_else(|err| {
74            panic!("{}", err);
75        });
76
77        let expected_files = vec![
78            VersionedFile::new(File::new(new_test::STORAGE_ID, "file1"), 1),
79            VersionedFile::new(File::new(new_test::STORAGE_ID, "file2"), 1),
80            VersionedFile::new(File::new(new_test::STORAGE_ID, "file3"), 2),
81        ];
82
83        assert_eq!(files, expected_files);
84    }
85}
86
87#[cfg(test)]
88#[allow(non_snake_case)]
89pub mod mock {
90    use crate::{
91        errno::{Errno, Error},
92        storage::new::test as new_test,
93        utils::test as utils,
94    };
95
96    pub fn storageListFilesSize(storage_id: u32, size: *mut usize) -> Error {
97        use super::test;
98
99        if storage_id != new_test::STORAGE_ID {
100            Errno::ErrorCap.error()
101        } else {
102            utils::write_usize(size, test::FILE_STR.len());
103            Errno::ErrorNone.error()
104        }
105    }
106
107    pub fn storageListFiles(storage_id: u32, files: *mut u8) -> Error {
108        use super::test;
109
110        if storage_id != new_test::STORAGE_ID {
111            Errno::ErrorCap.error()
112        } else {
113            utils::write_string(files, test::FILE_STR);
114            Errno::ErrorNone.error()
115        }
116    }
117}