diff options
Diffstat (limited to 'src/command.rs')
-rw-r--r-- | src/command.rs | 629 |
1 files changed, 281 insertions, 348 deletions
diff --git a/src/command.rs b/src/command.rs index deab0eb..a0c9e23 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,14 +1,11 @@ //! OpenGL command. -use quick_xml::events::BytesStart; - -use crate::deserialization::{ - Deserialize, - DeserializeWithFn, - Deserializer, - DeserializerError, - IgnoreEnd, - ResultExt, -}; +use std::convert::Infallible; + +use xml_stinks::deserializer::{Deserializer, Error as DeserializerError, IgnoreEnd}; +use xml_stinks::tagged::{TagStart, TagStartError}; +use xml_stinks::{impl_from_deserializer_error, DeserializeTagged, ResultExt}; + +use crate::util::impl_from_deserializer_err_wrapped; use crate::DeserializationError; /// A command. @@ -48,21 +45,20 @@ impl Command } } -impl Deserialize for Command +impl DeserializeTagged for Command { type Error = Error; fn deserialize<TDeserializer: Deserializer>( - start: &BytesStart, + start: &TagStart, deserializer: &mut TDeserializer, ) -> Result<Self, Self::Error> { let prototype = deserializer.de_tag::<Prototype>("proto", IgnoreEnd::No)?; - let parameters = deserializer.de_tag_list::<Parameter>("param")?; + let parameters = deserializer.de_tag_list::<Parameter, _>(Some("param"))?; - deserializer - .skip_to_tag_end(std::str::from_utf8(start.name().as_ref()).unwrap())?; + deserializer.skip_to_tag_end(start.name()?)?; Ok(Self { prototype, @@ -90,16 +86,15 @@ pub enum Error /// Deserialization failed. #[error("Deserialization failed")] DeserializationFailed(#[from] DeserializationError), -} -impl From<DeserializerError> for Error -{ - fn from(err: DeserializerError) -> Self - { - DeserializationError(err).into() - } + /// Invalid tag start. + #[error("Invalid tag start")] + InvalidTagStart(#[from] TagStartError), } +impl_from_deserializer_err_wrapped!(Error); +impl_from_deserializer_error!(Error); + /// A command prototype. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Prototype @@ -134,22 +129,22 @@ impl Prototype } } -impl Deserialize for Prototype +impl DeserializeTagged for Prototype { type Error = PrototypeError; fn deserialize<TDeserializer: Deserializer>( - _start: &BytesStart, + _start: &TagStart, deserializer: &mut TDeserializer, ) -> Result<Self, Self::Error> { let return_type = deserialize_type::<PrototypeError>(deserializer)?; - let name = deserializer.de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( - "name", - IgnoreEnd::No, - |_, deserializer| deserializer.de_text(), - )?; + // let name = deserializer.de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( + let name = + deserializer.de_tag_with("name", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; Ok(Self { name, return_type }) } @@ -172,13 +167,8 @@ pub enum PrototypeError DeserializationFailed(#[from] DeserializationError), } -impl From<DeserializerError> for PrototypeError -{ - fn from(err: DeserializerError) -> Self - { - DeserializationError(err).into() - } -} +impl_from_deserializer_err_wrapped!(PrototypeError); +impl_from_deserializer_error!(PrototypeError); /// A command parameter. #[derive(Debug, Clone, PartialEq, Eq)] @@ -214,22 +204,22 @@ impl Parameter } } -impl Deserialize for Parameter +impl DeserializeTagged for Parameter { type Error = ParameterError; fn deserialize<TDeserializer: Deserializer>( - _start: &BytesStart, + _start: &TagStart, deserializer: &mut TDeserializer, ) -> Result<Self, Self::Error> { let ty = deserialize_type::<ParameterError>(deserializer)?; - let name = deserializer.de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( - "name", - IgnoreEnd::No, - |_, deserializer| deserializer.de_text(), - )?; + // let name = deserializer.de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( + let name = + deserializer.de_tag_with("name", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; Ok(Self { name, ty }) } @@ -248,27 +238,22 @@ pub enum ParameterError DeserializationFailed(#[from] DeserializationError), } -impl From<DeserializerError> for ParameterError -{ - fn from(err: DeserializerError) -> Self - { - DeserializationError(err).into() - } -} +impl_from_deserializer_err_wrapped!(ParameterError); +impl_from_deserializer_error!(ParameterError); fn deserialize_type<Err>(deserializer: &mut impl Deserializer) -> Result<String, Err> where - Err: From<DeserializerError>, + Err: From<DeserializerError<Infallible>>, { let type_before = deserializer.de_text().try_event()?; + //.de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( let type_ptype = deserializer - .de_tag_with::<_, _, DeserializeWithFn<_, _, _>>( - "ptype", - IgnoreEnd::No, - |_, deserializer| deserializer.de_text(), - ) - .try_event()?; + .de_tag_with("ptype", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + }) + .try_event() + .map_err(Into::into)?; let type_after = deserializer.de_text().try_event()?; @@ -308,92 +293,83 @@ where #[cfg(test)] mod tests { + use mockall::predicate::{always, eq, function}; use pretty_assertions::assert_str_eq; - use quick_xml::events::Event; - use ridicule::predicate::{always, eq, function}; use super::*; - use crate::deserialization::MockDeserializer; + use crate::test_utils::MockDeserializer; #[test] fn deserialize_prototype_works_with_ptype() { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("ptype")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "ptype".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("GLuint".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("GLuint".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("name")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "name".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("glDoComplicatedThing".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() - .with( - eq("name"), - function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), - always(), - ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) - }) - .times(1); - } + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() + .with( + eq("name"), + function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), + always(), + ) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("glDoComplicatedThing".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) + }) + .times(1); let prototype = - Prototype::deserialize(&BytesStart::new("proto"), &mut mock_deserializer) + Prototype::deserialize(&TagStart::new("proto"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(prototype.name, "glDoComplicatedThing"); @@ -405,70 +381,60 @@ mod tests { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("void".to_string())) - .times(1); - } + mock_deserializer + .expect_de_text() + .returning(|| Ok("void".to_string())) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|_, _, _, _| { + .returning(|_, _, _| { Err(DeserializerError::UnexpectedEvent { expected_event_name: "start".to_string(), - found_event: Event::Start(BytesStart::new("name")), + found_event: "name".to_string(), }) }) .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("name")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "name".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("glDoSomeThing".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("name"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("glDoSomeThing".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } let prototype = - Prototype::deserialize(&BytesStart::new("proto"), &mut mock_deserializer) + Prototype::deserialize(&TagStart::new("proto"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(prototype.name, "glDoSomeThing"); @@ -480,80 +446,72 @@ mod tests { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("ptype")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "ptype".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("GLenum".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("GLenum".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("name")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "name".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("value".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("name"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("value".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } let parameter = - Parameter::deserialize(&BytesStart::new("param"), &mut mock_deserializer) + Parameter::deserialize(&TagStart::new("param"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(parameter.name, "value"); @@ -565,74 +523,67 @@ mod tests { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("ptype")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "ptype".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("GLchar".to_string())) - .times(1); - } + }) + .times(1); - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("GLchar".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("*".to_string())) - .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("source".to_string())) - .times(1); - } + mock_deserializer + .expect_de_text() + .returning(|| Ok("*".to_string())) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("name"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("source".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } let parameter = - Parameter::deserialize(&BytesStart::new("param"), &mut mock_deserializer) + Parameter::deserialize(&TagStart::new("param"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(parameter.name, "source"); @@ -644,70 +595,62 @@ mod tests { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("const".to_string())) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("GLchar".to_string())) - .times(1); - } + mock_deserializer + .expect_de_text() + .returning(|| Ok("const".to_string())) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("GLchar".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("*".to_string())) - .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("name".to_string())) - .times(1); - } + mock_deserializer + .expect_de_text() + .returning(|| Ok("*".to_string())) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("name"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("name".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } let parameter = - Parameter::deserialize(&BytesStart::new("param"), &mut mock_deserializer) + Parameter::deserialize(&TagStart::new("param"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(parameter.name, "name"); @@ -719,70 +662,60 @@ mod tests { let mut mock_deserializer = MockDeserializer::new(); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("void *".to_string())) - .times(1); - } + mock_deserializer + .expect_de_text() + .returning(|| Ok("void *".to_string())) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("ptype"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|_, _, _, _| { + .returning(|_, _, _| { Err(DeserializerError::UnexpectedEvent { expected_event_name: "start".to_string(), - found_event: Event::Start(BytesStart::new("name")), + found_event: "name".to_string(), }) }) .times(1); - } - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| { - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: Event::Start(BytesStart::new("name")), - }) + mock_deserializer + .expect_de_text() + .returning(|| { + Err(DeserializerError::UnexpectedEvent { + expected_event_name: "text".to_string(), + found_event: "start".to_string(), }) - .times(1); - } - - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_text() - .returning(|_| Ok("pixels".to_string())) - .times(1); - } + }) + .times(1); - // SAFETY: No argument lifetime is mistreated - unsafe { - mock_deserializer - .expect_de_tag_with::<String, DeserializerError, DeserializeWithFn<_, _, _>>() + mock_deserializer + .expect_de_tag_with::<String, DeserializerError<Infallible>>() .with( eq("name"), function(|ignore_end| matches!(ignore_end, IgnoreEnd::No)), always(), ) - .returning(|deserializer, tag_name, _, func| { - func(&BytesStart::new(tag_name), deserializer) + .returning(|tag_name, _, func| { + let mut inner_mock_deserializer = MockDeserializer::new(); + + inner_mock_deserializer + .expect_de_text() + .returning(|| Ok("pixels".to_string())) + .times(1); + + Ok(func( + &TagStart::new(tag_name), + &mut inner_mock_deserializer, + )?) }) .times(1); - } let parameter = - Parameter::deserialize(&BytesStart::new("param"), &mut mock_deserializer) + Parameter::deserialize(&TagStart::new("param"), &mut mock_deserializer) .expect("Expected Ok"); assert_str_eq!(parameter.name, "pixels"); |