Skip to main content

dog_blob/
config.rs

1/// Configuration for blob operations
2#[derive(Debug, Clone)]
3pub struct BlobConfig {
4    /// Absolute max size allowed for a single blob (safety guard)
5    pub max_blob_bytes: u64,
6
7    /// If size_hint >= this, prefer multipart/resumable path when available
8    pub multipart_threshold_bytes: u64,
9
10    /// Rules for part-based uploads
11    pub upload_rules: UploadRules,
12
13    /// When a range is requested but store can't do range:
14    /// - if false: fall back to full content (HTTP 200 equivalent)
15    /// - if true: return Unsupported
16    pub require_range_support: bool,
17
18    /// Optional: compute checksums during upload/assembly (streaming)
19    pub checksum_alg: Option<String>,
20}
21
22impl Default for BlobConfig {
23    fn default() -> Self {
24        Self {
25            max_blob_bytes: 5 * 1024 * 1024 * 1024, // 5GB
26            multipart_threshold_bytes: 16 * 1024 * 1024, // 16MB (2x part size)
27            upload_rules: UploadRules::default(),
28            require_range_support: false,
29            checksum_alg: None,
30        }
31    }
32}
33
34/// Rules for multipart uploads
35#[derive(Debug, Clone)]
36pub struct UploadRules {
37    /// Standard part size (bytes). Applies to multipart and staged.
38    pub part_size: u64,
39
40    /// Upper bound to protect memory/state
41    pub max_parts: u32,
42
43    /// If true: all parts except final must be exactly part_size
44    pub require_fixed_part_size: bool,
45
46    /// If true: allow uploading parts in any order
47    pub allow_out_of_order: bool,
48}
49
50impl Default for UploadRules {
51    fn default() -> Self {
52        Self {
53            part_size: 8 * 1024 * 1024, // 8MB
54            max_parts: 10_000,
55            require_fixed_part_size: true,
56            allow_out_of_order: true,
57        }
58    }
59}
60
61impl BlobConfig {
62    /// Create a new config with defaults
63    pub fn new() -> Self {
64        Self::default()
65    }
66
67    /// Set max blob size
68    pub fn with_max_blob_bytes(mut self, bytes: u64) -> Self {
69        self.max_blob_bytes = bytes;
70        self
71    }
72
73    /// Set multipart threshold
74    pub fn with_multipart_threshold(mut self, bytes: u64) -> Self {
75        self.multipart_threshold_bytes = bytes;
76        self
77    }
78
79    /// Set upload rules
80    pub fn with_upload_rules(mut self, rules: UploadRules) -> Self {
81        self.upload_rules = rules;
82        self
83    }
84
85    /// Require range support (no fallback to full content)
86    pub fn require_range_support(mut self) -> Self {
87        self.require_range_support = true;
88        self
89    }
90
91    /// Enable checksum with algorithm
92    pub fn with_checksum<S: Into<String>>(mut self, algorithm: S) -> Self {
93        self.checksum_alg = Some(algorithm.into());
94        self
95    }
96}
97
98impl UploadRules {
99    /// Create new upload rules
100    pub fn new() -> Self {
101        Self::default()
102    }
103
104    /// Set part size
105    pub fn with_part_size(mut self, bytes: u64) -> Self {
106        self.part_size = bytes;
107        self
108    }
109
110    /// Set max parts
111    pub fn with_max_parts(mut self, max: u32) -> Self {
112        self.max_parts = max;
113        self
114    }
115
116    /// Allow variable part sizes (relaxed mode)
117    pub fn allow_variable_part_sizes(mut self) -> Self {
118        self.require_fixed_part_size = false;
119        self
120    }
121
122    /// Require parts to be uploaded in order
123    pub fn require_ordered_parts(mut self) -> Self {
124        self.allow_out_of_order = false;
125        self
126    }
127}