actix_web_rust_embed_responder/
rust_embed.rs1use base64::{engine::general_purpose::STANDARD_NO_PAD as Base64Encoder, Engine};
2use chrono::TimeZone;
3use rust_embed::EmbeddedFile;
4use std::{borrow::Cow, ops::Deref};
5
6use crate::embed::{EmbedRespondable, EmbedResponse, IntoResponse};
7
8impl From<EmbeddedFile> for EmbedResponse<EmbeddedFile> {
9 fn from(file: EmbeddedFile) -> Self {
10 EmbedResponse {
11 file: Some(file),
12 compress: Default::default(),
13 }
14 }
15}
16
17impl From<Option<EmbeddedFile>> for EmbedResponse<EmbeddedFile> {
18 fn from(file: Option<EmbeddedFile>) -> Self {
19 EmbedResponse {
20 file,
21 compress: Default::default(),
22 }
23 }
24}
25
26impl IntoResponse<EmbeddedFile> for EmbeddedFile {
27 fn into_response(self) -> EmbedResponse<EmbeddedFile> {
28 self.into()
29 }
30}
31
32impl IntoResponse<EmbeddedFile> for Option<EmbeddedFile> {
33 fn into_response(self) -> EmbedResponse<EmbeddedFile> {
34 self.into()
35 }
36}
37
38impl EmbedRespondable for EmbeddedFile {
39 type Data = Cow<'static, [u8]>;
40 type DataGzip = Vec<u8>;
41 type DataBr = Vec<u8>;
42 type DataZstd = Vec<u8>;
43 type ETag = String;
44 type LastModified = String;
45 type MimeType = String;
46
47 fn data(&self) -> Self::Data {
48 self.data.clone()
49 }
50
51 fn data_gzip(&self) -> Option<Self::DataGzip> {
52 None
53 }
54
55 fn data_br(&self) -> Option<Self::DataBr> {
56 None
57 }
58
59 fn data_zstd(&self) -> Option<Self::DataZstd> {
60 None
61 }
62
63 fn last_modified(&self) -> Option<Self::LastModified> {
64 self.last_modified_timestamp().map(|timestamp| {
65 chrono::Utc
66 .timestamp_opt(timestamp, 0)
67 .unwrap()
68 .to_rfc2822()
69 })
70 }
71
72 fn last_modified_timestamp(&self) -> Option<i64> {
73 self.metadata
74 .last_modified()
75 .and_then(|v| v.try_into().ok())
78 }
79
80 fn etag(&self) -> Self::ETag {
81 format!("\"{}\"", Base64Encoder.encode(self.metadata.sha256_hash()))
82 }
83
84 fn mime_type(&self) -> Option<Self::MimeType> {
85 None
91 }
92}
93
94impl Deref for EmbedResponse<EmbeddedFile> {
95 type Target = Option<EmbeddedFile>;
96
97 fn deref(&self) -> &Self::Target {
98 &self.file
99 }
100}