diff options
Diffstat (limited to 'nix-rust/src/store/path.rs')
-rw-r--r-- | nix-rust/src/store/path.rs | 224 |
1 files changed, 0 insertions, 224 deletions
diff --git a/nix-rust/src/store/path.rs b/nix-rust/src/store/path.rs deleted file mode 100644 index 99f7a1f18..000000000 --- a/nix-rust/src/store/path.rs +++ /dev/null @@ -1,224 +0,0 @@ -use crate::error::Error; -use crate::util::base32; -use std::fmt; -use std::path::Path; - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct StorePath { - pub hash: StorePathHash, - pub name: StorePathName, -} - -pub const STORE_PATH_HASH_BYTES: usize = 20; -pub const STORE_PATH_HASH_CHARS: usize = 32; - -impl StorePath { - pub fn new(path: &Path, store_dir: &Path) -> Result<Self, Error> { - if path.parent() != Some(store_dir) { - return Err(Error::NotInStore(path.into())); - } - Self::new_from_base_name( - path.file_name() - .ok_or_else(|| Error::BadStorePath(path.into()))? - .to_str() - .ok_or_else(|| Error::BadStorePath(path.into()))?, - ) - } - - pub fn from_parts(hash: [u8; STORE_PATH_HASH_BYTES], name: &str) -> Result<Self, Error> { - Ok(StorePath { - hash: StorePathHash(hash), - name: StorePathName::new(name)?, - }) - } - - pub fn new_from_base_name(base_name: &str) -> Result<Self, Error> { - if base_name.len() < STORE_PATH_HASH_CHARS + 1 - || base_name.as_bytes()[STORE_PATH_HASH_CHARS] != b'-' - { - return Err(Error::BadStorePath(base_name.into())); - } - - Ok(StorePath { - hash: StorePathHash::new(&base_name[0..STORE_PATH_HASH_CHARS])?, - name: StorePathName::new(&base_name[STORE_PATH_HASH_CHARS + 1..])?, - }) - } -} - -impl fmt::Display for StorePath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}-{}", self.hash, self.name) - } -} - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct StorePathHash([u8; STORE_PATH_HASH_BYTES]); - -impl StorePathHash { - pub fn new(s: &str) -> Result<Self, Error> { - assert_eq!(s.len(), STORE_PATH_HASH_CHARS); - let v = base32::decode(s)?; - assert_eq!(v.len(), STORE_PATH_HASH_BYTES); - let mut bytes: [u8; 20] = Default::default(); - bytes.copy_from_slice(&v[0..STORE_PATH_HASH_BYTES]); - Ok(Self(bytes)) - } - - pub fn hash(&self) -> &[u8; STORE_PATH_HASH_BYTES] { - &self.0 - } -} - -impl fmt::Display for StorePathHash { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut buf = vec![0; STORE_PATH_HASH_CHARS]; - base32::encode_into(&self.0, &mut buf); - f.write_str(std::str::from_utf8(&buf).unwrap()) - } -} - -impl Ord for StorePathHash { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - // Historically we've sorted store paths by their base32 - // serialization, but our base32 encodes bytes in reverse - // order. So compare them in reverse order as well. - self.0.iter().rev().cmp(other.0.iter().rev()) - } -} - -impl PartialOrd for StorePathHash { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct StorePathName(String); - -impl StorePathName { - pub fn new(s: &str) -> Result<Self, Error> { - if s.is_empty() { - return Err(Error::StorePathNameEmpty); - } - - if s.len() > 211 { - return Err(Error::StorePathNameTooLong); - } - - let is_good_path_name = s.chars().all(|c| { - c.is_ascii_alphabetic() - || c.is_ascii_digit() - || c == '+' - || c == '-' - || c == '.' - || c == '_' - || c == '?' - || c == '=' - }); - if s.starts_with('.') || !is_good_path_name { - return Err(Error::BadStorePathName); - } - - Ok(Self(s.to_string())) - } - - pub fn name(&self) -> &str { - &self.0 - } -} - -impl fmt::Display for StorePathName { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use assert_matches::assert_matches; - - #[test] - fn test_parse() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-konsole-18.12.3"; - let p = StorePath::new_from_base_name(&s).unwrap(); - assert_eq!(p.name.0, "konsole-18.12.3"); - assert_eq!( - p.hash.0, - [ - 0x9f, 0x76, 0x49, 0x20, 0xf6, 0x5d, 0xe9, 0x71, 0xc4, 0xca, 0x46, 0x21, 0xab, 0xff, - 0x9b, 0x44, 0xef, 0x87, 0x0f, 0x3c - ] - ); - } - - #[test] - fn test_no_name() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::StorePathNameEmpty) - ); - } - - #[test] - fn test_no_dash() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::BadStorePath(_)) - ); - } - - #[test] - fn test_short_hash() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxl-konsole-18.12.3"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::BadStorePath(_)) - ); - } - - #[test] - fn test_invalid_hash() { - let s = "7h7qgvs4kgzsn8e6rb273saxyqh4jxlz-konsole-18.12.3"; - assert_matches!(StorePath::new_from_base_name(&s), Err(Error::BadBase32)); - } - - #[test] - fn test_long_name() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assert_matches!(StorePath::new_from_base_name(&s), Ok(_)); - } - - #[test] - fn test_too_long_name() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::StorePathNameTooLong) - ); - } - - #[test] - fn test_bad_name() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-foo bar"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::BadStorePathName) - ); - - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-kónsole"; - assert_matches!( - StorePath::new_from_base_name(&s), - Err(Error::BadStorePathName) - ); - } - - #[test] - fn test_roundtrip() { - let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-konsole-18.12.3"; - assert_eq!(StorePath::new_from_base_name(&s).unwrap().to_string(), s); - } -} |