@@ -18,26 +18,28 @@ use std::{collections::HashMap, ops::Deref, rc::Rc, sync::Arc};
1818
1919pub type DefaultResourceFiles = HashMap < & ' static str , Resource > ;
2020
21- pub trait ResourceFilesCollection {
22- fn get_resource ( & self , path : & str ) -> Option < & Resource > ;
23- fn contains_key ( & self , path : & str ) -> bool ;
21+ /// Resource file with static data and metadata.
22+ pub trait ResourceFile {
23+ fn data ( & self ) -> & ' static [ u8 ] ;
24+ fn modified ( & self ) -> u64 ;
25+ fn mime_type ( & self ) -> & str ;
2426}
2527
26- impl ResourceFilesCollection for DefaultResourceFiles {
27- fn get_resource ( & self , path : & str ) -> Option < & Resource > {
28- self . get ( path)
29- }
30-
31- fn contains_key ( & self , path : & str ) -> bool {
32- self . contains_key ( path)
33- }
28+ /// Basic abstraction for a dictionary of resources.
29+ pub trait ResourceFilesCollection {
30+ type Resource : ResourceFile ;
31+ /// Get a resource by path
32+ fn get_resource ( & self , path : & str ) -> Option < & Self :: Resource > ;
33+ /// Check if a resource exists by path
34+ fn contains_key ( & self , path : & str ) -> bool ;
3435}
3536
3637impl < R > ResourceFilesCollection for Rc < R >
3738where
3839 R : ResourceFilesCollection ,
3940{
40- fn get_resource ( & self , path : & str ) -> Option < & Resource > {
41+ type Resource = R :: Resource ;
42+ fn get_resource ( & self , path : & str ) -> Option < & Self :: Resource > {
4143 let r: & R = self ;
4244 r. get_resource ( path)
4345 }
@@ -52,7 +54,8 @@ impl<R> ResourceFilesCollection for Arc<R>
5254where
5355 R : ResourceFilesCollection ,
5456{
55- fn get_resource ( & self , path : & str ) -> Option < & Resource > {
57+ type Resource = R :: Resource ;
58+ fn get_resource ( & self , path : & str ) -> Option < & Self :: Resource > {
5659 let r: & R = self ;
5760 r. get_resource ( path)
5861 }
6366 }
6467}
6568
69+ mod legacy_static_files {
70+ use super :: * ;
71+
72+ impl ResourceFile for Resource {
73+ fn data ( & self ) -> & ' static [ u8 ] {
74+ self . data
75+ }
76+
77+ fn modified ( & self ) -> u64 {
78+ self . modified
79+ }
80+
81+ fn mime_type ( & self ) -> & str {
82+ self . mime_type
83+ }
84+ }
85+
86+ impl ResourceFilesCollection for DefaultResourceFiles {
87+ type Resource = Resource ;
88+ fn get_resource ( & self , path : & str ) -> Option < & Self :: Resource > {
89+ self . get ( path)
90+ }
91+
92+ fn contains_key ( & self , path : & str ) -> bool {
93+ self . contains_key ( path)
94+ }
95+ }
96+ }
97+
6698/// Static resource files handling
6799///
68100/// `ResourceFiles` service must be registered with `App::service` method.
@@ -100,9 +132,12 @@ pub struct ResourceFilesInner<C> {
100132
101133const INDEX_HTML : & str = "index.html" ;
102134
103- impl ResourceFiles {
135+ impl < F > ResourceFiles < F >
136+ where
137+ F : ResourceFilesCollection + ' static ,
138+ {
104139 #[ must_use]
105- pub fn new ( path : & str , files : HashMap < & ' static str , Resource > ) -> Self {
140+ pub fn new ( path : & str , files : F ) -> Self {
106141 let inner = ResourceFilesInner {
107142 path : path. into ( ) ,
108143 files,
@@ -328,20 +363,20 @@ where
328363 }
329364}
330365
331- fn respond_to ( req : & HttpRequest , item : Option < & Resource > ) -> HttpResponse {
366+ fn respond_to < Resource : ResourceFile > ( req : & HttpRequest , item : Option < & Resource > ) -> HttpResponse {
332367 if let Some ( file) = item {
333368 let etag = Some ( header:: EntityTag :: new_strong ( format ! (
334369 "{:x}:{:x}" ,
335- file. data. len( ) ,
336- file. modified
370+ file. data( ) . len( ) ,
371+ file. modified( )
337372 ) ) ) ;
338373
339374 let precondition_failed = !any_match ( etag. as_ref ( ) , req) ;
340375
341376 let not_modified = !none_match ( etag. as_ref ( ) , req) ;
342377
343378 let mut resp = HttpResponse :: build ( StatusCode :: OK ) ;
344- resp. insert_header ( ( header:: CONTENT_TYPE , file. mime_type ) ) ;
379+ resp. insert_header ( ( header:: CONTENT_TYPE , file. mime_type ( ) ) ) ;
345380
346381 if let Some ( etag) = etag {
347382 resp. insert_header ( header:: ETag ( etag) ) ;
@@ -353,7 +388,7 @@ fn respond_to(req: &HttpRequest, item: Option<&Resource>) -> HttpResponse {
353388 return resp. status ( StatusCode :: NOT_MODIFIED ) . finish ( ) ;
354389 }
355390
356- resp. body ( file. data )
391+ resp. body ( file. data ( ) )
357392 } else {
358393 HttpResponse :: NotFound ( ) . body ( "Not found" )
359394 }
0 commit comments