1use std::hash::Hash;
2use std::io;
3
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Clone, Debug, Eq, PartialEq, Hash)]
6pub struct Bucket {
7 name: String,
8}
9
10impl Bucket {
11 pub fn try_from(name: &str) -> io::Result<Bucket> {
12 if name.is_empty() {
13 return Err(io::Error::new(io::ErrorKind::InvalidInput, "Bucket name is empty"));
14 }
15
16 let ok_chars: bool = name
17 .chars()
18 .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_');
19
20 if !ok_chars {
21 return Err(io::Error::new(
22 io::ErrorKind::InvalidInput,
23 "Bucket name must match [A-Za-z0-9_-]+",
24 ));
25 }
26
27 Ok(Bucket {
28 name: name.to_ascii_lowercase(),
29 })
30 }
31}
32
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[derive(Clone, Debug, Eq, PartialEq, Hash)]
35pub struct EntryId {
36 pub bucket: Bucket,
37 pub name: String,
38}
39
40impl EntryId {
41 pub fn from(bucket: &Bucket, name: &str) -> EntryId {
42 EntryId { bucket: bucket.clone(), name: name.to_string() }
43 }
44}
45
46#[cfg(test)]
47#[path = "../tests/unit_tests/bucket.rs"]
48pub mod tests;