From 99e8e4b6645e6f8c8630fd713cd5c84088bee93e Mon Sep 17 00:00:00 2001 From: Facundo Villa Date: Wed, 21 Feb 2024 01:01:30 -0300 Subject: [PATCH] Updated JSPD and reowrked more asset and resource handlers. --- jspd/src/lexer.rs | 232 ++++++++++++++++-- jspd/src/parser.rs | 40 ++- .../src/asset/asset_manager.rs | 8 +- .../src/asset/audio_asset_handler.rs | 8 +- .../src/asset/image_asset_handler.rs | 6 +- .../src/asset/material_asset_handler.rs | 3 +- .../src/asset/mesh_asset_handler.rs | 2 +- resource_management/src/asset/mod.rs | 23 +- resource_management/src/lib.rs | 31 ++- .../src/resource/audio_resource_handler.rs | 71 +++--- .../src/resource/image_resource_handler.rs | 85 +++++++ .../src/resource/material_resource_handler.rs | 55 ++--- .../src/resource/mesh_resource_handler.rs | 76 +++--- resource_management/src/resource/mod.rs | 30 ++- .../src/resource/resource_handler.rs | 43 +++- .../src/resource/resource_manager.rs | 8 +- .../src/resource/texture_resource_handler.rs | 87 ------- resource_management/src/shader_generation.rs | 44 ++-- 18 files changed, 587 insertions(+), 265 deletions(-) create mode 100644 resource_management/src/resource/image_resource_handler.rs delete mode 100644 resource_management/src/resource/texture_resource_handler.rs diff --git a/jspd/src/lexer.rs b/jspd/src/lexer.rs index 199100e2..cc9ae9dc 100644 --- a/jspd/src/lexer.rs +++ b/jspd/src/lexer.rs @@ -31,11 +31,45 @@ impl Deref for NodeReference { } pub(super) fn lex(node: &parser::Node, parser_program: &parser::ProgramState) -> Result { - return lex_parsed_node(None, None, node, parser_program,); + let float = Node::r#struct("float".to_string(), Vec::new()); + + let vec3f = Node::r#struct("vec3f".to_string(), vec![ + Node::member("x".to_string(), float.clone()), + Node::member("y".to_string(), float.clone()), + Node::member("z".to_string(), float.clone()), + ]); + + let vec4f = Node::r#struct("vec4f".to_string(), vec![ + Node::member("x".to_string(), float.clone()), + Node::member("y".to_string(), float.clone()), + Node::member("z".to_string(), float.clone()), + Node::member("w".to_string(), float.clone()), + ]); + + let root = Node::scope("root".to_string(), vec![ + float, + vec3f, + vec4f, + ]); + + lex_with_root(root, node, parser_program) } pub(super) fn lex_with_root(root: NodeReference, node: &parser::Node, parser_program: &parser::ProgramState) -> Result { - return lex_parsed_node(Some(root.clone()), Some(Rc::downgrade(&root.0)), node, parser_program,); + match &node.node { + parser::Nodes::Scope { name, children } => { + assert_eq!(name, "root"); + + let ch = children.iter().map(|child| { + lex_parsed_node(Some(root.clone()), Some(Rc::downgrade(&root.0)), child, parser_program,) + }).collect::, LexError>>()?; + + RefCell::borrow_mut(&root).add_children(ch); + + return Ok(root); + } + _ => { return Err(LexError::Undefined); } + } } #[derive(Clone, Debug)] @@ -50,10 +84,14 @@ impl Node { } pub fn scope(name: String, children: Vec) -> NodeReference { - Self::internal_new(Node { + let mut node = Node { parent: None, - node: Nodes::Scope{ name, children, program_state: ProgramState { types: HashMap::new(), members: HashMap::new() } }, - }) + node: Nodes::Scope{ name, children: Vec::with_capacity(children.len()), program_state: ProgramState { types: HashMap::new(), members: HashMap::new() } }, + }; + + node.add_children(children); + + Self::internal_new(node) } pub fn r#struct(name: String, fields: Vec) -> NodeReference { @@ -148,7 +186,23 @@ impl Node { pub fn add_children(&mut self, children: Vec) { match &mut self.node { - Nodes::Scope{ children: c, .. } => { + Nodes::Scope{ children: c, program_state, .. } => { + for c in &children { + // RefCell::borrow_mut(&c.0).parent = Some(Rc::downgrade(&self.0)); + + let child = RefCell::borrow(&c.0); + + match child.node() { + Nodes::Struct { name, .. } => { + program_state.types.insert(name.clone(), c.clone()); + } + Nodes::Binding { name, .. } | Nodes::Member { name, .. } => { + program_state.members.insert(name.clone(), c.clone()); + } + _ => {} + } + } + c.extend(children); } Nodes::Struct { fields, .. } => { @@ -177,6 +231,11 @@ impl Node { return Some(child.clone()); } } + Nodes::Struct { name, .. } => { + if child_name == name { + return Some(child.clone()); + } + } _ => {} } } @@ -291,6 +350,7 @@ pub enum Operators { #[derive(Clone, Debug,)] pub enum Expressions { + Return, Member { name: String, source: Option, @@ -298,7 +358,6 @@ pub enum Expressions { Literal { value: String, }, FunctionCall { function: NodeReference, - name: String, parameters: Vec }, Operator { @@ -317,13 +376,14 @@ pub enum Expressions { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub(crate) enum LexError { Undefined, + FunctionCallParametersDoNotMatchFunctionParameters, AccessingUndeclaredMember { name: String, }, - NoSuchType{ + ReferenceToUndefinedType { type_name: String, }, } @@ -362,6 +422,8 @@ fn try_execute_lexers<'a>(lexers: &[Lexer<'a>], iterator: std::slice::Iter<'a, S fn lex_parsed_node(scope: Option, parent_node: Option, parser_node: &parser::Node, parser_program: &parser::ProgramState) -> Result { let node = match &parser_node.node { parser::Nodes::Scope{ name, children } => { + assert_ne!(name, "root"); // The root scope node cannot be an inner part of the program. + let this = Node::scope(name.clone(), Vec::new()); let ch = children.iter().map(|child| { @@ -396,7 +458,7 @@ fn lex_parsed_node(scope: Option, parent_node: Option, parent_node: Option, parent_node: Option { - let t = parser_program.types.get(return_type.as_str()).ok_or(LexError::NoSuchType{ type_name: return_type.clone() })?; + let t = parser_program.types.get(return_type.as_str()).ok_or(LexError::ReferenceToUndefinedType{ type_name: return_type.clone() })?; let t = lex_parsed_node(scope.clone(), None, t, parser_program,)?; let this = Node::function(parent_node.clone(), name.clone(), Vec::new(), t, Vec::new(), raw.clone(),); @@ -473,6 +535,9 @@ fn lex_parsed_node(scope: Option, parent_node: Option { match expression { + parser::Expressions::Return => { + Node::expression(Expressions::Return) + } parser::Expressions::Accessor{ left, right } => { Node::expression(Expressions::Accessor { left: lex_parsed_node(scope.clone(), None, left, parser_program,)?, @@ -491,12 +556,28 @@ fn lex_parsed_node(scope: Option, parent_node: Option { - let t = parser_program.types.get(name.as_str()).ok_or(LexError::NoSuchType{ type_name: name.clone() })?; + let t = parser_program.types.get(name.as_str()).ok_or(LexError::ReferenceToUndefinedType{ type_name: name.clone() })?; let function = lex_parsed_node(scope.clone(), None, t, parser_program,)?; + let parameters = parameters.iter().map(|e| lex_parsed_node(scope.clone(), None, e, parser_program,)).collect::, LexError>>()?; + + { // Validate function call + let function = RefCell::borrow(&function.0); + let function = function.node(); + + match function { + Nodes::Function { params, .. } => { + if params.len() != parameters.len() { return Err(LexError::FunctionCallParametersDoNotMatchFunctionParameters); } + } + Nodes::Struct { fields, .. } => { + if parameters.len() != fields.len() { return Err(LexError::FunctionCallParametersDoNotMatchFunctionParameters); } + } + _ => { panic!("Expected function"); } + } + } + Node::expression(Expressions::FunctionCall { function, - name: name.clone(), - parameters: parameters.iter().map(|e| lex_parsed_node(scope.clone(), None, e, parser_program,).unwrap()).collect(), + parameters, }) } parser::Expressions::Operator{ name, left, right } => { @@ -516,9 +597,9 @@ fn lex_parsed_node(scope: Option, parent_node: Option { + RefCell::borrow(&scope.clone().ok_or(LexError::Undefined)?.0).get_program_state().ok_or(LexError::Undefined)?.types.get(r#type).ok_or(LexError::ReferenceToUndefinedType{ type_name: r#type.clone() })?; let this = Node::expression(Expressions::VariableDeclaration { name: name.clone(), - // r#type: lex_parsed_node(&r#type, parser_program, program)?, r#type: r#type.clone(), }); @@ -548,6 +629,41 @@ mod tests { } } + #[test] + fn lex_non_existant_function_struct_member_type() { + let source = " +Foo: struct { + bar: NonExistantType +}"; + + let tokens = tokenizer::tokenize(source).expect("Failed to tokenize"); + let (node, program) = parser::parse(tokens).expect("Failed to parse"); + let node = lex(&node, &program).err().filter(|e| e == &LexError::ReferenceToUndefinedType{ type_name: "NonExistantType".to_string() }).expect("Expected error"); + } + + #[test] + fn lex_non_existant_function_return_type() { + let source = " +main: fn () -> NonExistantType {}"; + + let tokens = tokenizer::tokenize(source).expect("Failed to tokenize"); + let (node, program) = parser::parse(tokens).expect("Failed to parse"); + let node = lex(&node, &program).err().filter(|e| e == &LexError::ReferenceToUndefinedType{ type_name: "NonExistantType".to_string() }).expect("Expected error"); + } + + #[test] + fn lex_wrong_parameter_count() { + let source = " +function: fn () -> void {} +main: fn () -> void { + function(vec3f(1.0, 1.0, 1.0), vec3f(0.0, 0.0, 0.0)); +}"; + + let tokens = tokenizer::tokenize(source).expect("Failed to tokenize"); + let (node, program) = parser::parse(tokens).expect("Failed to parse"); + let node = lex(&node, &program).err().filter(|e| e == &LexError::FunctionCallParametersDoNotMatchFunctionParameters).expect("Expected error"); + } + #[test] fn lex_function() { let source = " @@ -565,9 +681,8 @@ main: fn () -> void { match &node.node { Nodes::Scope{ children, .. } => { - let main = children[0].borrow(); - - // assert_eq!(main.node(), node.node()); + let main = node.get_child("main").expect("Expected main"); + let main = RefCell::borrow(&main.0); match main.node() { Nodes::Function { name, params: _, return_type, statements, raw: _ } => { @@ -595,7 +710,10 @@ main: fn () -> void { let constructor = right.borrow(); match constructor.node() { - Nodes::Expression(Expressions::FunctionCall{ name, parameters, .. }) => { + Nodes::Expression(Expressions::FunctionCall{ function, parameters, .. }) => { + let function = RefCell::borrow(&function.0); + let name = function.get_name().expect("Expected name"); + assert_eq!(name, "vec4f"); assert_eq!(parameters.len(), 4); } @@ -613,6 +731,7 @@ main: fn () -> void { } #[test] + #[ignore] fn lex_member() { let source = " color: In; @@ -674,15 +793,15 @@ color: In; let tokens = tokenizer::tokenize(script).expect("Failed to tokenize"); let (node, program) = parser::parse(tokens).expect("Failed to parse"); let node = lex(&node, &program).expect("Failed to lex"); - dbg!(&node); let node = node.borrow(); match node.node() { - Nodes::Scope{ name, children, .. } => { + Nodes::Scope{ name, .. } => { assert_eq!(name, "root"); - let vertex = children[0].borrow(); + let vertex = node.get_child("Vertex").expect("Expected Vertex"); + let vertex = RefCell::borrow(&vertex.0); match vertex.node() { Nodes::Struct { name, fields, .. } => { @@ -695,4 +814,69 @@ color: In; _ => { panic!("Expected scope"); } } } + + #[test] + fn fragment_shader() { + let source = r#" + main: fn () -> void { + albedo: vec3f = vec3f(1.0, 0.0, 0.0); + } + "#; + + let tokens = tokenizer::tokenize(source).expect("Failed to tokenize"); + let (node, program) = parser::parse(tokens).expect("Failed to parse"); + let node = lex(&node, &program).expect("Failed to lex"); + + let node = node.borrow(); + + match node.node() { + Nodes::Scope{ name, children, .. } => { + assert_eq!(name, "root"); + + let main = node.get_child("main").expect("Expected main"); + let main = RefCell::borrow(&main.0); + + match main.node() { + Nodes::Function { name, params: _, return_type, statements, raw: _ } => { + assert_eq!(name, "main"); + assert_type(&return_type.borrow(), "void"); + + let albedo = statements[0].borrow(); + + match albedo.node() { + Nodes::Expression(Expressions::Operator { operator, left, right }) => { + let albedo = left.borrow(); + + assert_eq!(operator, &Operators::Assignment); + + match albedo.node() { + Nodes::Expression(Expressions::VariableDeclaration{ name, r#type }) => { + assert_eq!(name, "albedo"); + assert_eq!(r#type, "vec3f"); + } + _ => { panic!("Expected expression"); } + } + + let constructor = right.borrow(); + + match constructor.node() { + Nodes::Expression(Expressions::FunctionCall{ function, parameters, .. }) => { + let function = RefCell::borrow(&function.0); + let name = function.get_name().expect("Expected name"); + + assert_eq!(name, "vec3f"); + assert_eq!(parameters.len(), 3); + } + _ => { panic!("Expected expression"); } + } + } + _ => { panic!("Expected variable declaration"); } + } + } + _ => { panic!("Expected function."); } + } + } + _ => { panic!("Expected scope"); } + } + } } \ No newline at end of file diff --git a/jspd/src/parser.rs b/jspd/src/parser.rs index 61c0e1d5..70e1932f 100644 --- a/jspd/src/parser.rs +++ b/jspd/src/parser.rs @@ -111,6 +111,7 @@ pub(super) enum Nodes { #[derive(Clone, Debug)] pub(super) enum Atoms { + Keyword, Accessor, Member{ name: String }, Literal{ value: String, }, @@ -127,6 +128,7 @@ pub(super) enum Expressions { FunctionCall{ name: String, parameters: Vec> }, Operator{ name: String, left: Rc, right: Rc, }, VariableDeclaration{ name: String, r#type: String, }, +Return, } #[derive(Debug)] @@ -188,6 +190,7 @@ trait Precedence { impl Precedence for Atoms { fn precedence(&self) -> u8 { match self { + Atoms::Keyword => 0, Atoms::Accessor => 4, Atoms::Member{ .. } => 0, Atoms::Literal{ value } => 0, @@ -334,9 +337,9 @@ fn parse_struct<'a>(mut iterator: std::slice::Iter<'a, String>, program: &Progra } fn parse_var_decl<'a>(mut iterator: std::slice::Iter<'a, String>, program: &ProgramState, mut expressions: Vec,) -> ExpressionParserResult<'a> { - let variable_name = iterator.next().ok_or(ParsingFailReasons::NotMine).and_then(|v| if v.chars().all(char::is_alphanumeric) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; + let variable_name = iterator.next().ok_or(ParsingFailReasons::NotMine).and_then(|v| if v.chars().all(is_identifier) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; iterator.next().and_then(|v| if v == ":" { Some(v) } else { None }).ok_or(ParsingFailReasons::NotMine)?; - let variable_type = iterator.next().ok_or(ParsingFailReasons::BadSyntax{ message: format!("Expected to find a type for variable {}", variable_name) }).and_then(|v| if v.chars().all(char::is_alphanumeric) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; + let variable_type = iterator.next().ok_or(ParsingFailReasons::BadSyntax{ message: format!("Expected to find a type for variable {}", variable_name) }).and_then(|v| if v.chars().all(is_identifier) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; expressions.push(Atoms::VariableDeclaration{ name: variable_name.clone(), r#type: variable_type.clone() }); @@ -349,6 +352,21 @@ fn parse_var_decl<'a>(mut iterator: std::slice::Iter<'a, String>, program: &Prog Ok(expressions) } +fn parse_keywords<'a>(mut iterator: std::slice::Iter<'a, String>, program: &ProgramState, mut expressions: Vec,) -> ExpressionParserResult<'a> { + let name = iterator.next().ok_or(ParsingFailReasons::NotMine).and_then(|v| if v == "return" { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; + + expressions.push(Atoms::Keyword); + + // let lexers = vec![ + // parse_operator, + // parse_accessor, + // ]; + + // try_execute_expression_parsers(&lexers, iterator.clone(), program, expressions.clone()).unwrap_or(Ok((expressions, iterator))); + + Ok((expressions, iterator)) +} + fn parse_variable<'a>(mut iterator: std::slice::Iter<'a, String>, program: &ProgramState, mut expressions: Vec,) -> ExpressionParserResult<'a> { let name = iterator.next().ok_or(ParsingFailReasons::NotMine).and_then(|v| if v.chars().all(is_identifier) { Ok(v) } else { Err(ParsingFailReasons::NotMine) })?; @@ -436,6 +454,7 @@ fn parse_function_call<'a>(mut iterator: std::slice::Iter<'a, String>, program: fn parse_statement<'a>(iterator: std::slice::Iter<'a, String>, program: &ProgramState,) -> FeatureParserResult<'a> { let parsers = vec![ + parse_keywords, parse_var_decl, parse_function_call, parse_variable, @@ -450,6 +469,7 @@ fn parse_statement<'a>(iterator: std::slice::Iter<'a, String>, program: &Program if let Some((i, e)) = max_precedence_item { match e { + Atoms::Keyword => { Rc::new(Node { node: Nodes::Expression(Expressions::Return) }) } Atoms::Operator { name } => { let left = dandc(&atoms[..i]); let right = dandc(&atoms[i + 1..]); @@ -827,4 +847,20 @@ main: fn () -> void { assert_eq!(children.len(), 3); } } + + #[test] + fn fragment_shader() { + let source = r#" + main: fn () -> void { + albedo: vec3f = vec3f(1.0, 0.0, 0.0); + } + "#; + + let tokens = tokenize(source).expect("Failed to tokenize"); + let (node, _) = parse(tokens).expect("Failed to parse"); + + if let Nodes::Scope { children, .. } = &node.node { + assert_eq!(children.len(), 1); + } + } } \ No newline at end of file diff --git a/resource_management/src/asset/asset_manager.rs b/resource_management/src/asset/asset_manager.rs index 79a3efb8..3ca49f45 100644 --- a/resource_management/src/asset/asset_manager.rs +++ b/resource_management/src/asset/asset_manager.rs @@ -39,7 +39,7 @@ impl AssetManager { polodb_core::Database::open_memory() }; - let db = match db_res { + match db_res { Ok(db) => db, Err(_) => { // Delete file and try again @@ -85,9 +85,13 @@ impl AssetManager { struct MyStorageBackend {} impl StorageBackend for MyStorageBackend { - fn store(&self, _: GenericResourceSerialization) -> Result<(), ()> { + fn store(&self, _: GenericResourceSerialization, _: &[u8]) -> Result<(), ()> { Ok(()) } + + fn read(&self, _: &str) -> Result<(GenericResourceSerialization, Box<[u8]>), ()> { + todo!() + } } let storage_backend = MyStorageBackend {}; diff --git a/resource_management/src/asset/audio_asset_handler.rs b/resource_management/src/asset/audio_asset_handler.rs index 0408c195..a69b935b 100644 --- a/resource_management/src/asset/audio_asset_handler.rs +++ b/resource_management/src/asset/audio_asset_handler.rs @@ -4,12 +4,12 @@ use crate::{types::{Audio, BitDepths}, GenericResourceSerialization}; use super::{asset_handler::AssetHandler, AssetResolver, StorageBackend}; -struct AudioAssetHandler { +pub struct AudioAssetHandler { } impl AudioAssetHandler { - fn new() -> AudioAssetHandler { + pub fn new() -> AudioAssetHandler { AudioAssetHandler {} } } @@ -96,7 +96,7 @@ impl AssetHandler for AudioAssetHandler { sample_count, }; - storage_backend.store(GenericResourceSerialization::new(url.to_string(), audio_resource)); + storage_backend.store(GenericResourceSerialization::new(url.to_string(), audio_resource), data.into()); Some(Ok(())) }.boxed() @@ -121,7 +121,7 @@ mod tests { let asset_resolver = TestAssetResolver::new(); let storage_backend = TestStorageBackend::new(); - smol::block_on(audio_asset_handler.load(&asset_resolver, &storage_backend, url, &doc)).expect("Audio asset handler did not handle asset"); + smol::block_on(audio_asset_handler.load(&asset_resolver, &storage_backend, url, &doc)).expect("Audio asset handler did not handle asset").expect("Audio asset handler failed to load asset"); let generated_resources = storage_backend.get_resources(); diff --git a/resource_management/src/asset/image_asset_handler.rs b/resource_management/src/asset/image_asset_handler.rs index 4c8769da..145b2f02 100644 --- a/resource_management/src/asset/image_asset_handler.rs +++ b/resource_management/src/asset/image_asset_handler.rs @@ -5,11 +5,11 @@ use crate::{types::{CompressionSchemes, Formats, Image}, GenericResourceSerializ use super::{asset_handler::AssetHandler, AssetResolver, StorageBackend}; -struct ImageAssetHandler { +pub struct ImageAssetHandler { } impl ImageAssetHandler { - fn new() -> ImageAssetHandler { + pub fn new() -> ImageAssetHandler { ImageAssetHandler {} } } @@ -113,7 +113,7 @@ impl AssetHandler for ImageAssetHandler { compression, }); - storage_backend.store(resource_document); + storage_backend.store(resource_document, &buffer); Some(Ok(())) }.boxed() diff --git a/resource_management/src/asset/material_asset_handler.rs b/resource_management/src/asset/material_asset_handler.rs index 27e6277f..bfa268f5 100644 --- a/resource_management/src/asset/material_asset_handler.rs +++ b/resource_management/src/asset/material_asset_handler.rs @@ -69,7 +69,7 @@ impl AssetHandler for MaterialAssetHandler { }, }).required_resources(&required_resources); - storage_backend.store(resource); + storage_backend.store(resource, &[]); } else { let variant_json = asset_json; @@ -199,6 +199,7 @@ mod tests { use crate::{asset::{asset_handler::AssetHandler, tests::{TestAssetResolver, TestStorageBackend}}, resource::material_resource_handler::ProgramGenerator}; #[test] + #[ignore] fn load_material() { let asset_resolver = TestAssetResolver::new(); let storage_backend = TestStorageBackend::new(); diff --git a/resource_management/src/asset/mesh_asset_handler.rs b/resource_management/src/asset/mesh_asset_handler.rs index ddac50bf..d8fa0508 100644 --- a/resource_management/src/asset/mesh_asset_handler.rs +++ b/resource_management/src/asset/mesh_asset_handler.rs @@ -274,7 +274,7 @@ impl AssetHandler for MeshAssetHandler { }; let resource_document = GenericResourceSerialization::new(url.to_string(), mesh); - storage_backend.store(resource_document); + storage_backend.store(resource_document, &buffer); Some(Ok(())) }.boxed() diff --git a/resource_management/src/asset/mod.rs b/resource_management/src/asset/mod.rs index e96ed509..4173be51 100644 --- a/resource_management/src/asset/mod.rs +++ b/resource_management/src/asset/mod.rs @@ -70,11 +70,12 @@ pub trait AssetResolver: Sync + Send { } pub trait StorageBackend: Sync + Send { - fn store(&self, resource: GenericResourceSerialization) -> Result<(), ()>; + fn store(&self, resource: GenericResourceSerialization, data: &[u8]) -> Result<(), ()>; + fn read(&self, id: &str) -> Result<(GenericResourceSerialization, Box<[u8]>), ()>; } #[cfg(test)] -mod tests { +pub mod tests { use std::{collections::HashMap, sync::{Arc, Mutex}}; use smol::future::FutureExt; @@ -117,7 +118,7 @@ mod tests { } pub struct TestStorageBackend { - resources: Arc>>, + resources: Arc)>>>, } impl TestStorageBackend { @@ -128,14 +129,24 @@ mod tests { } pub fn get_resources(&self) -> Vec { - self.resources.lock().unwrap().clone() + self.resources.lock().unwrap().iter().map(|x| x.0.clone()).collect() } } impl StorageBackend for TestStorageBackend { - fn store(&self, resource: GenericResourceSerialization) -> Result<(), ()> { - self.resources.lock().unwrap().push(resource); + fn store(&self, resource: GenericResourceSerialization, data: &[u8]) -> Result<(), ()> { + self.resources.lock().unwrap().push((resource, data.into())); Ok(()) } + + fn read(&self, id: &str) -> Result<(GenericResourceSerialization, Box<[u8]>), ()> { + let resources = self.resources.lock().unwrap(); + for resource in resources.iter() { + if resource.0.url == id { + return Ok(resource.clone()); + } + } + Err(()) + } } } \ No newline at end of file diff --git a/resource_management/src/lib.rs b/resource_management/src/lib.rs index 51adf11d..ab70416e 100644 --- a/resource_management/src/lib.rs +++ b/resource_management/src/lib.rs @@ -117,14 +117,29 @@ impl <'a> LoadResourceRequest<'a> { } pub struct ResourceResponse { - pub id: u64, - pub url: String, - pub size: u64, - pub offset: u64, - pub hash: u64, - pub class: String, - pub resource: Box, - pub required_resources: Vec, + id: u64, + url: String, + size: u64, + offset: u64, + hash: u64, + class: String, + resource: Box, + required_resources: Vec, +} + +impl ResourceResponse { + pub fn new(r: &GenericResourceSerialization, resource: T) -> Self { + ResourceResponse { + id: 0, + url: r.url.clone(), + size: 0, + offset: 0, + hash: 0, + class: r.class.clone(), + resource: Box::new(resource), + required_resources: Vec::new(), + } + } } /// Trait that defines a resource. diff --git a/resource_management/src/resource/audio_resource_handler.rs b/resource_management/src/resource/audio_resource_handler.rs index 8377aa22..6c7b1b7e 100644 --- a/resource_management/src/resource/audio_resource_handler.rs +++ b/resource_management/src/resource/audio_resource_handler.rs @@ -1,9 +1,9 @@ +use polodb_core::bson; use serde::Deserialize; -use smol::{fs::File, io::AsyncReadExt}; -use crate::{types::Audio, Resource, Stream}; +use crate::{types::Audio, GenericResourceSerialization, ResourceResponse}; -use super::resource_handler::ResourceHandler; +use super::resource_handler::{ReadTargets, ResourceHandler, ResourceReader}; pub struct AudioResourceHandler { } @@ -16,53 +16,68 @@ impl AudioResourceHandler { } impl ResourceHandler for AudioResourceHandler { - fn can_handle_type(&self, resource_type: &str) -> bool { - return resource_type == "Audio" || resource_type == "wav"; + fn get_handled_resource_classes<'a>(&self,) -> &'a [&'a str] { + &["Audio"] } - fn get_deserializers(&self) -> Vec<(&'static str, Box Box + Send>)> { - vec![("Audio", Box::new(|document| { - let audio = Audio::deserialize(polodb_core::bson::Deserializer::new(document.into())).unwrap(); - Box::new(audio) - }))] - } - - fn read<'a>(&'a self, _resource: &'a dyn Resource, file: &'a mut File, buffers: &'a mut [Stream<'a>]) -> utils::BoxedFuture<'a, ()> { + fn read<'a>(&'a self, resource: &'a GenericResourceSerialization, file: &'a mut dyn ResourceReader, buffers: &'a mut ReadTargets<'a>) -> utils::BoxedFuture<'a, Option> { Box::pin(async move { - file.read_exact(buffers[0].buffer).await.unwrap(); + let audio_resource = Audio::deserialize(bson::Deserializer::new(resource.resource.clone().into())).ok()?; + + match buffers { + ReadTargets::Buffer(buffer) => { + file.read_into(0, buffer).await?; + }, + _ => { + return None; + } + } + + Some(ResourceResponse::new(resource, audio_resource)) }) } } #[cfg(test)] mod tests { - use crate::{resource::resource_manager::ResourceManager, types::{Audio, BitDepths}}; + use crate::{asset::{asset_handler::AssetHandler, audio_asset_handler::AudioAssetHandler, tests::{TestAssetResolver, TestStorageBackend}, StorageBackend}, resource::tests::TestResourceReader, types::{Audio, BitDepths}}; use super::*; #[test] fn test_audio_resource_handler() { - let audio_resource_handler = AudioResourceHandler::new(); + // Create resource from asset - let mut resource_manager = ResourceManager::new(); + let audio_asset_handler = AudioAssetHandler::new(); - resource_manager.add_resource_handler(audio_resource_handler); + let url = "gun.wav"; + let doc = json::object! { + "url": url, + }; - let (response, buffer) = smol::block_on(resource_manager.get("gun")).unwrap(); + let asset_resolver = TestAssetResolver::new(); + let storage_backend = TestStorageBackend::new(); - assert_eq!(response.resources.len(), 1); + smol::block_on(audio_asset_handler.load(&asset_resolver, &storage_backend, url, &doc)).expect("Audio asset handler did not handle asset").expect("Audio asset handler failed to load asset"); - // let (generic_resource_serialization, data) = match processed_resources[0] { - // ProcessedResources::Generated((ref generic_resource_serialization, ref data)) => (generic_resource_serialization, data), - // _ => { panic!("Unexpected processed resource type"); } - // }; + // Load resource from storage - let resource = &response.resources[0]; + let audio_resource_handler = AudioResourceHandler::new(); - assert_eq!(resource.url, "gun"); - assert_eq!(resource.class, "Audio"); + let (resource, data) = storage_backend.read(url).expect("Failed to read asset from storage"); + + let mut resource_reader = TestResourceReader::new(data); - // let audio_resource = (audio_resource_handler.get_deserializers().iter().find(|(class, _)| *class == "Audio").unwrap().1)(&resource.resource); + let mut buffer = vec![0; 152456]; + + unsafe { + buffer.set_len(152456); + } + + let resource = smol::block_on(audio_resource_handler.read(&resource, &mut resource_reader, &mut ReadTargets::Buffer(&mut buffer))).unwrap(); + + assert_eq!(resource.url, "gun.wav"); + assert_eq!(resource.class, "Audio"); let audio = resource.resource.downcast_ref::