Skip to content

Commit 8dd259e

Browse files
committed
move
- Add #[must_use] attribute to detect_mime_type for better usage indication - Replace empty byte check with is_empty() for clarity - Update tests for improved readability with formatted assertions - Remove unnecessary blank lines in sql_to_json.rs Benefits: - Improved code clarity and maintainability - Enhanced test readability
1 parent 40c5c39 commit 8dd259e

File tree

4 files changed

+206
-14
lines changed

4 files changed

+206
-14
lines changed

src/webserver/database/blob_to_data_url.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// Detects MIME type based on file signatures (magic bytes).
22
/// Returns the most appropriate MIME type for common file formats.
3-
#[must_use] pub fn detect_mime_type(bytes: &[u8]) -> &'static str {
3+
#[must_use]
4+
pub fn detect_mime_type(bytes: &[u8]) -> &'static str {
45
if bytes.is_empty() {
56
return "application/octet-stream";
67
}
@@ -70,14 +71,16 @@
7071
/// Converts binary data to a data URL string.
7172
/// This function is used by both SQL type conversion and file reading functions.
7273
/// Automatically detects common file types based on magic bytes.
73-
#[must_use] pub fn vec_to_data_uri(bytes: &[u8]) -> String {
74+
#[must_use]
75+
pub fn vec_to_data_uri(bytes: &[u8]) -> String {
7476
let mime_type = detect_mime_type(bytes);
7577
vec_to_data_uri_with_mime(bytes, mime_type)
7678
}
7779

7880
/// Converts binary data to a data URL string with a specific MIME type.
7981
/// This function is used by both SQL type conversion and file reading functions.
80-
#[must_use] pub fn vec_to_data_uri_with_mime(bytes: &[u8], mime_type: &str) -> String {
82+
#[must_use]
83+
pub fn vec_to_data_uri_with_mime(bytes: &[u8], mime_type: &str) -> String {
8184
let mut data_url = format!("data:{mime_type};base64,");
8285
base64::Engine::encode_string(
8386
&base64::engine::general_purpose::STANDARD,
@@ -89,7 +92,8 @@
8992

9093
/// Converts binary data to a data URL JSON value.
9194
/// This is a convenience function for SQL type conversion.
92-
#[must_use] pub fn vec_to_data_uri_value(bytes: &[u8]) -> serde_json::Value {
95+
#[must_use]
96+
pub fn vec_to_data_uri_value(bytes: &[u8]) -> serde_json::Value {
9397
serde_json::Value::String(vec_to_data_uri(bytes))
9498
}
9599

@@ -187,7 +191,9 @@ mod tests {
187191
// Test that it returns a JSON string value
188192
let result = vec_to_data_uri_value(b"test");
189193
match result {
190-
serde_json::Value::String(s) => assert_eq!(s, "data:application/octet-stream;base64,dGVzdA=="),
194+
serde_json::Value::String(s) => {
195+
assert_eq!(s, "data:application/octet-stream;base64,dGVzdA==")
196+
}
191197
_ => panic!("Expected String value"),
192198
}
193199
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/// Detects MIME type based on file signatures (magic bytes).
2+
/// Returns the most appropriate MIME type for common file formats.
3+
#[must_use] pub fn detect_mime_type(bytes: &[u8]) -> &'static str {
4+
if bytes.is_empty() {
5+
return "application/octet-stream";
6+
}
7+
8+
// PNG: 89 50 4E 47 0D 0A 1A 0A
9+
if bytes.starts_with(b"\x89PNG\r\n\x1a\n") {
10+
return "image/png";
11+
}
12+
// JPEG: FF D8
13+
if bytes.starts_with(b"\xFF\xD8") {
14+
return "image/jpeg";
15+
}
16+
// GIF87a/89a: GIF87a or GIF89a
17+
if bytes.starts_with(b"GIF87a") || bytes.starts_with(b"GIF89a") {
18+
return "image/gif";
19+
}
20+
// BMP: 42 4D
21+
if bytes.starts_with(b"BM") {
22+
return "image/bmp";
23+
}
24+
// WebP: RIFF....WEBP
25+
if bytes.starts_with(b"RIFF") && bytes.len() >= 12 && &bytes[8..12] == b"WEBP" {
26+
return "image/webp";
27+
}
28+
// PDF: %PDF
29+
if bytes.starts_with(b"%PDF") {
30+
return "application/pdf";
31+
}
32+
// ZIP: 50 4B 03 04
33+
if bytes.starts_with(b"PK\x03\x04") {
34+
// Check for Office document types in ZIP central directory
35+
if bytes.len() >= 50 {
36+
let central_dir = &bytes[30..bytes.len().min(50)];
37+
if central_dir.windows(6).any(|w| w == b"word/") {
38+
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
39+
}
40+
if central_dir.windows(3).any(|w| w == b"xl/") {
41+
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
42+
}
43+
if central_dir.windows(4).any(|w| w == b"ppt/") {
44+
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
45+
}
46+
}
47+
return "application/zip";
48+
}
49+
50+
// Text-based formats - check first few bytes for ASCII patterns
51+
if !bytes.is_empty() {
52+
match bytes[0] {
53+
b'<' => {
54+
if bytes.len() >= 4 && bytes.starts_with(b"<svg") {
55+
return "image/svg+xml";
56+
}
57+
if bytes.len() >= 5 && bytes.starts_with(b"<?xml") {
58+
return "application/xml";
59+
}
60+
return "application/xml";
61+
}
62+
b'{' | b'[' => return "application/json",
63+
_ => {}
64+
}
65+
}
66+
67+
"application/octet-stream"
68+
}
69+
70+
/// Converts binary data to a data URL string.
71+
/// This function is used by both SQL type conversion and file reading functions.
72+
/// Automatically detects common file types based on magic bytes.
73+
#[must_use] pub fn vec_to_data_uri(bytes: &[u8]) -> String {
74+
let mime_type = detect_mime_type(bytes);
75+
vec_to_data_uri_with_mime(bytes, mime_type)
76+
}
77+
78+
/// Converts binary data to a data URL string with a specific MIME type.
79+
/// This function is used by both SQL type conversion and file reading functions.
80+
#[must_use] pub fn vec_to_data_uri_with_mime(bytes: &[u8], mime_type: &str) -> String {
81+
let mut data_url = format!("data:{mime_type};base64,");
82+
base64::Engine::encode_string(
83+
&base64::engine::general_purpose::STANDARD,
84+
bytes,
85+
&mut data_url,
86+
);
87+
data_url
88+
}
89+
90+
/// Converts binary data to a data URL JSON value.
91+
/// This is a convenience function for SQL type conversion.
92+
#[must_use] pub fn vec_to_data_uri_value(bytes: &[u8]) -> serde_json::Value {
93+
serde_json::Value::String(vec_to_data_uri(bytes))
94+
}
95+
96+
#[cfg(test)]
97+
mod tests {
98+
use super::*;
99+
100+
#[test]
101+
fn test_detect_mime_type() {
102+
// Test empty data
103+
assert_eq!(detect_mime_type(&[]), "application/octet-stream");
104+
105+
// Test PNG
106+
assert_eq!(detect_mime_type(b"\x89PNG\r\n\x1a\n"), "image/png");
107+
108+
// Test JPEG
109+
assert_eq!(detect_mime_type(b"\xFF\xD8\xFF\xE0"), "image/jpeg");
110+
111+
// Test GIF87a
112+
assert_eq!(detect_mime_type(b"GIF87a"), "image/gif");
113+
114+
// Test GIF89a
115+
assert_eq!(detect_mime_type(b"GIF89a"), "image/gif");
116+
117+
// Test BMP
118+
assert_eq!(detect_mime_type(b"BM\x00\x00"), "image/bmp");
119+
120+
// Test PDF
121+
assert_eq!(detect_mime_type(b"%PDF-"), "application/pdf");
122+
123+
// Test SVG
124+
assert_eq!(
125+
detect_mime_type(b"<svg xmlns=\"http://www.w3.org/2000/svg\">"),
126+
"image/svg+xml"
127+
);
128+
129+
// Test XML (non-SVG)
130+
assert_eq!(
131+
detect_mime_type(b"<?xml version=\"1.0\"?><root><data>test</data></root>"),
132+
"application/xml"
133+
);
134+
135+
// Test JSON
136+
assert_eq!(
137+
detect_mime_type(b"{\"key\": \"value\"}"),
138+
"application/json"
139+
);
140+
141+
// Test ZIP
142+
assert_eq!(detect_mime_type(b"PK\x03\x04"), "application/zip");
143+
144+
// Test unknown data
145+
assert_eq!(
146+
detect_mime_type(&[0x00, 0x01, 0x02, 0x03]),
147+
"application/octet-stream"
148+
);
149+
}
150+
151+
#[test]
152+
fn test_vec_to_data_uri() {
153+
// Test with empty bytes
154+
let result = vec_to_data_uri(&[]);
155+
assert_eq!(result, "data:application/octet-stream;base64,");
156+
157+
// Test with simple text
158+
let result = vec_to_data_uri(b"Hello World");
159+
assert_eq!(
160+
result,
161+
"data:application/octet-stream;base64,SGVsbG8gV29ybGQ="
162+
);
163+
164+
// Test with binary data
165+
let binary_data = [0, 1, 2, 255, 254, 253];
166+
let result = vec_to_data_uri(&binary_data);
167+
assert_eq!(result, "data:application/octet-stream;base64,AAEC//79");
168+
}
169+
170+
#[test]
171+
fn test_vec_to_data_uri_with_mime() {
172+
// Test with custom MIME type
173+
let result = vec_to_data_uri_with_mime(b"Hello", "text/plain");
174+
assert_eq!(result, "data:text/plain;base64,SGVsbG8=");
175+
176+
// Test with image MIME type
177+
let result = vec_to_data_uri_with_mime(&[255, 216, 255], "image/jpeg");
178+
assert_eq!(result, "data:image/jpeg;base64,/9j/");
179+
180+
// Test with empty bytes and custom MIME
181+
let result = vec_to_data_uri_with_mime(&[], "application/json");
182+
assert_eq!(result, "data:application/json;base64,");
183+
}
184+
185+
#[test]
186+
fn test_vec_to_data_uri_value() {
187+
// Test that it returns a JSON string value
188+
let result = vec_to_data_uri_value(b"test");
189+
match result {
190+
serde_json::Value::String(s) => assert_eq!(s, "data:application/octet-stream;base64,dGVzdA=="),
191+
_ => panic!("Expected String value"),
192+
}
193+
}
194+
}

src/webserver/database/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
pub mod blob_to_data_url;
12
mod connect;
23
mod csv_import;
34
pub mod execute_queries;
45
pub mod migrations;
5-
pub mod blob_to_data_url;
66
mod sql;
77
mod sqlpage_functions;
88
mod syntax_tree;

src/webserver/database/sql_to_json.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,6 @@ pub fn vec_to_data_uri(bytes: &[u8]) -> String {
121121
crate::webserver::database::blob_to_data_url::vec_to_data_uri(bytes)
122122
}
123123

124-
/// Converts binary data to a data URL string with a specific MIME type.
125-
/// This function is used by both SQL type conversion and file reading functions.
126-
pub fn vec_to_data_uri_with_mime(bytes: &[u8], mime_type: &str) -> String {
127-
crate::webserver::database::blob_to_data_url::vec_to_data_uri_with_mime(bytes, mime_type)
128-
}
129-
130124
/// Converts binary data to a data URL JSON value.
131125
/// This is a convenience function for SQL type conversion.
132126
pub fn vec_to_data_uri_value(bytes: &[u8]) -> Value {
@@ -470,8 +464,6 @@ mod tests {
470464
Ok(())
471465
}
472466

473-
474-
475467
fn expect_json_object_equal(actual: &Value, expected: &Value) {
476468
use std::fmt::Write;
477469

0 commit comments

Comments
 (0)