@ -1,4 +1,4 @@
use anyhow ::bail ;
use anyhow ::{ anyhow , bail } ;
use clap ::{ Parser , Subcommand } ;
use clap ::{ Parser , Subcommand } ;
use flate2 ::read ::MultiGzDecoder ;
use flate2 ::read ::MultiGzDecoder ;
use oxhttp ::model ::{ Body , HeaderName , HeaderValue , Request , Response , Status } ;
use oxhttp ::model ::{ Body , HeaderName , HeaderValue , Request , Response , Status } ;
@ -177,7 +177,7 @@ enum GraphOrDatasetFormat {
impl GraphOrDatasetFormat {
impl GraphOrDatasetFormat {
fn from_path ( path : & Path ) -> anyhow ::Result < Self > {
fn from_path ( path : & Path ) -> anyhow ::Result < Self > {
if let Some ( ext ) = path . extension ( ) . and_then ( | ext | ext . to_str ( ) ) {
if let Some ( ext ) = path . extension ( ) . and_then ( | ext | ext . to_str ( ) ) {
Self ::from_name ( ext ) . map_err ( | e | {
Self ::from_extension ( ext ) . map_err ( | e | {
e . context ( format! (
e . context ( format! (
"Not able to guess the file format from file name extension '{}'" ,
"Not able to guess the file format from file name extension '{}'" ,
ext
ext
@ -191,31 +191,30 @@ impl GraphOrDatasetFormat {
}
}
}
}
fn from_name ( name : & str ) -> anyhow ::Result < Self > {
fn from_extension ( name : & str ) -> anyhow ::Result < Self > {
let mut candidates = Vec ::with_capacity ( 4 ) ;
match ( GraphFormat ::from_extension ( name ) , DatasetFormat ::from_extension ( name ) ) {
if let Some ( f ) = GraphFormat ::from_extension ( name ) {
( Some ( g ) , Some ( d ) ) = > Err ( anyhow ! ( "The file extension '{}' can be resolved to both '{}' and '{}', not sure what to pick" , name , g . file_extension ( ) , d . file_extension ( ) ) ) ,
candidates . push ( GraphOrDatasetFormat ::Graph ( f ) ) ;
( Some ( g ) , None ) = > Ok ( GraphOrDatasetFormat ::Graph ( g ) ) ,
( None , Some ( d ) ) = > Ok ( GraphOrDatasetFormat ::Dataset ( d ) ) ,
( None , None ) = >
Err ( anyhow ! ( "The file extension '{}' is unknown" , name ) )
}
}
if let Some ( f ) = DatasetFormat ::from_extension ( name ) {
}
candidates . push ( GraphOrDatasetFormat ::Dataset ( f ) ) ;
}
fn from_media_type ( name : & str ) -> anyhow ::Result < Self > {
if let Some ( f ) = GraphFormat ::from_media_type ( name ) {
match (
candidates . push ( GraphOrDatasetFormat ::Graph ( f ) ) ;
GraphFormat ::from_media_type ( name ) ,
}
DatasetFormat ::from_media_type ( name ) ,
if let Some ( f ) = DatasetFormat ::from_media_type ( name ) {
) {
candidates . push ( GraphOrDatasetFormat ::Dataset ( f ) ) ;
( Some ( g ) , Some ( d ) ) = > Err ( anyhow ! (
}
"The media type '{}' can be resolved to both '{}' and '{}', not sure what to pick" ,
if candidates . is_empty ( ) {
name ,
bail ! ( "The format '{}' is unknown" , name )
g . file_extension ( ) ,
} else if candidates . len ( ) = = 1 {
d . file_extension ( )
Ok ( candidates [ 0 ] )
) ) ,
} else {
( Some ( g ) , None ) = > Ok ( GraphOrDatasetFormat ::Graph ( g ) ) ,
bail ! ( "The format '{}' can be resolved to multiple known formats, not sure what to pick ({})" , name , candidates . iter ( ) . fold ( String ::new ( ) , | a , f | {
( None , Some ( d ) ) = > Ok ( GraphOrDatasetFormat ::Dataset ( d ) ) ,
a + " " + match f {
( None , None ) = > Err ( anyhow ! ( "The media type '{}' is unknown" , name ) ) ,
GraphOrDatasetFormat ::Graph ( f ) = > f . file_extension ( ) ,
GraphOrDatasetFormat ::Dataset ( f ) = > f . file_extension ( ) ,
}
} ) . trim ( ) )
}
}
}
}
}
}
@ -442,41 +441,45 @@ fn handle_request(request: &mut Request, store: Store) -> Result<Response, HttpE
let content_type =
let content_type =
content_type ( request ) . ok_or_else ( | | bad_request ( "No Content-Type given" ) ) ? ;
content_type ( request ) . ok_or_else ( | | bad_request ( "No Content-Type given" ) ) ? ;
if let Some ( target ) = store_target ( request ) ? {
if let Some ( target ) = store_target ( request ) ? {
if let Some ( format ) = GraphFormat ::from_media_type ( & content_type ) {
let format = GraphFormat ::from_media_type ( & content_type )
let new = assert_that_graph_exists ( & store , & target ) . is_ok ( ) ;
. ok_or_else ( | | unsupported_media_type ( & content_type ) ) ? ;
store
let new = assert_that_graph_exists ( & store , & target ) . is_ok ( ) ;
. load_graph (
BufReader ::new ( request . body_mut ( ) ) ,
format ,
GraphName ::from ( target ) . as_ref ( ) ,
None ,
)
. map_err ( bad_request ) ? ;
Ok ( Response ::builder ( if new {
Status ::CREATED
} else {
Status ::NO_CONTENT
} )
. build ( ) )
} else {
Err ( unsupported_media_type ( & content_type ) )
}
} else if let Some ( format ) = DatasetFormat ::from_media_type ( & content_type ) {
store
. load_dataset ( BufReader ::new ( request . body_mut ( ) ) , format , None )
. map_err ( bad_request ) ? ;
Ok ( Response ::builder ( Status ::NO_CONTENT ) . build ( ) )
} else if let Some ( format ) = GraphFormat ::from_media_type ( & content_type ) {
let graph = resolve_with_base ( request , & format! ( "/store/{:x}" , random ::< u128 > ( ) ) ) ? ;
store
store
. load_graph ( BufReader ::new ( request . body_mut ( ) ) , format , & graph , None )
. load_graph (
BufReader ::new ( request . body_mut ( ) ) ,
format ,
GraphName ::from ( target ) . as_ref ( ) ,
None ,
)
. map_err ( bad_request ) ? ;
. map_err ( bad_request ) ? ;
Ok ( Response ::builder ( Status ::CREATED )
Ok ( Response ::builder ( if new {
. with_header ( HeaderName ::LOCATION , graph . into_string ( ) )
Status ::CREATED
. unwrap ( )
} else {
. build ( ) )
Status ::NO_CONTENT
} )
. build ( ) )
} else {
} else {
Err ( unsupported_media_type ( & content_type ) )
match GraphOrDatasetFormat ::from_media_type ( & content_type )
. map_err ( | _ | unsupported_media_type ( & content_type ) ) ?
{
GraphOrDatasetFormat ::Graph ( format ) = > {
let graph =
resolve_with_base ( request , & format! ( "/store/{:x}" , random ::< u128 > ( ) ) ) ? ;
store
. load_graph ( BufReader ::new ( request . body_mut ( ) ) , format , & graph , None )
. map_err ( bad_request ) ? ;
Ok ( Response ::builder ( Status ::CREATED )
. with_header ( HeaderName ::LOCATION , graph . into_string ( ) )
. unwrap ( )
. build ( ) )
}
GraphOrDatasetFormat ::Dataset ( format ) = > {
store
. load_dataset ( BufReader ::new ( request . body_mut ( ) ) , format , None )
. map_err ( bad_request ) ? ;
Ok ( Response ::builder ( Status ::NO_CONTENT ) . build ( ) )
}
}
}
}
}
}
( path , "HEAD" ) if path . starts_with ( "/store" ) = > {
( path , "HEAD" ) if path . starts_with ( "/store" ) = > {