diff --git a/crates/stef-build/src/definition.rs b/crates/stef-build/src/definition.rs index 39da5d2..e1cbe8a 100644 --- a/crates/stef-build/src/definition.rs +++ b/crates/stef-build/src/definition.rs @@ -374,370 +374,3 @@ fn compile_literal(literal: &Literal) -> TokenStream { Literal::Bytes(b) => proc_macro2::Literal::byte_string(b).into_token_stream(), } } - -#[cfg(test)] -mod tests { - #![allow(clippy::too_many_lines)] - - use indoc::indoc; - use pretty_assertions::assert_eq; - - use super::*; - - fn parse(input: &str, expect: &str) { - let parsed = Schema::parse(input).unwrap(); - println!("==========\n{parsed}"); - - let compiled = compile_schema(&parsed); - println!("----------\n{compiled}"); - - let pretty = prettyplease::unparse(&syn::parse2(compiled.clone()).unwrap()); - println!("----------\n{pretty}=========="); - - assert_eq!(expect, pretty); - } - - #[test] - fn basic_module() { - let input = indoc! {r#" - /// Hello world! - mod sample {} - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - /// Hello world! - pub mod sample { - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - } - "#}; - - parse(input, expect); - } - - #[test] - fn basic_struct() { - let input = indoc! {r#" - /// Hello world! - struct Sample { - field1: u32 @1, - field2: bytes @2, - field3: (bool, [i16; 4]) @3, - } - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - /// Hello world! - #[derive(Clone, Debug, PartialEq)] - #[allow(clippy::module_name_repetitions, clippy::option_option)] - pub struct Sample { - pub field1: u32, - pub field2: Vec, - pub field3: (bool, [i16; 4]), - } - #[automatically_derived] - impl ::stef::Encode for Sample { - #[allow( - clippy::borrow_deref_ref, - clippy::explicit_auto_deref, - clippy::needless_borrow, - clippy::too_many_lines, - )] - fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field( - w, - 1, - |w| { - ::stef::buf::encode_u32(w, self.field1); - }, - ); - ::stef::buf::encode_field( - w, - 2, - |w| { - ::stef::buf::encode_bytes(w, &self.field2); - }, - ); - ::stef::buf::encode_field( - w, - 3, - |w| { - ::stef::buf::encode_bool(w, self.field3.0); - ::stef::buf::encode_array( - w, - &&(self.field3.1), - |w, v| { - ::stef::buf::encode_i16(w, *v); - }, - ); - }, - ); - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } - } - #[automatically_derived] - impl ::stef::Decode for Sample { - #[allow(clippy::type_complexity, clippy::too_many_lines)] - fn decode(r: &mut impl ::stef::Buf) -> ::stef::buf::Result { - let mut field1: Option = None; - let mut field2: Option> = None; - let mut field3: Option<(bool, [i16; 4])> = None; - loop { - match ::stef::buf::decode_id(r)? { - ::stef::buf::END_MARKER => break, - 1 => field1 = Some(::stef::buf::decode_u32(r)?), - 2 => field2 = Some(::stef::buf::decode_bytes(r)?), - 3 => { - field3 = Some( - { - Ok::< - _, - ::stef::buf::Error, - >(( - ::stef::buf::decode_bool(r)?, - ::stef::buf::decode_array( - r, - |r| { ::stef::buf::decode_i16(r) }, - )?, - )) - }?, - ); - } - _ => continue, - } - } - Ok(Self { - field1: field1 - .ok_or(::stef::buf::Error::MissingField { - id: 1, - name: Some("field1"), - })?, - field2: field2 - .ok_or(::stef::buf::Error::MissingField { - id: 2, - name: Some("field2"), - })?, - field3: field3 - .ok_or(::stef::buf::Error::MissingField { - id: 3, - name: Some("field3"), - })?, - }) - } - } - "#}; - - parse(input, expect); - } - - #[test] - fn basic_enum() { - let input = indoc! {r#" - /// Hello world! - enum Sample { - Variant1 @1, - Variant2(u32 @1, u8 @2) @2, - Variant3 { - field1: string @1, - field2: vec @2, - } @3, - } - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - /// Hello world! - #[derive(Clone, Debug, PartialEq)] - #[allow(clippy::module_name_repetitions, clippy::option_option)] - pub enum Sample { - Variant1, - Variant2(u32, u8), - Variant3 { field1: String, field2: Vec }, - } - #[automatically_derived] - impl ::stef::Encode for Sample { - #[allow( - clippy::borrow_deref_ref, - clippy::semicolon_if_nothing_returned, - clippy::too_many_lines, - )] - fn encode(&self, w: &mut impl ::stef::BufMut) { - match self { - Self::Variant1 => { - ::stef::buf::encode_id(w, 1); - } - Self::Variant2(n0, n1) => { - ::stef::buf::encode_id(w, 2); - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, *n0) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_u8(w, *n1) }); - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } - Self::Variant3 { field1, field2 } => { - ::stef::buf::encode_id(w, 3); - ::stef::buf::encode_field( - w, - 1, - |w| { ::stef::buf::encode_string(w, &*field1) }, - ); - ::stef::buf::encode_field( - w, - 2, - |w| { - ::stef::buf::encode_vec( - w, - &*field2, - |w, v| { - ::stef::buf::encode_bool(w, *v); - }, - ) - }, - ); - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } - } - } - } - #[automatically_derived] - impl ::stef::Decode for Sample { - #[allow(clippy::too_many_lines)] - fn decode(r: &mut impl ::stef::Buf) -> ::stef::buf::Result { - match ::stef::buf::decode_id(r)? { - 1 => Ok(Self::Variant1), - 2 => { - let mut n0: Option = None; - let mut n1: Option = None; - loop { - match ::stef::buf::decode_id(r)? { - ::stef::buf::END_MARKER => break, - 1 => n0 = Some(::stef::buf::decode_u32(r)?), - 2 => n1 = Some(::stef::buf::decode_u8(r)?), - _ => continue, - } - } - Ok( - Self::Variant2( - n0 - .ok_or(::stef::buf::Error::MissingField { - id: 1, - name: None, - })?, - n1 - .ok_or(::stef::buf::Error::MissingField { - id: 2, - name: None, - })?, - ), - ) - } - 3 => { - let mut field1: Option = None; - let mut field2: Option> = None; - loop { - match ::stef::buf::decode_id(r)? { - ::stef::buf::END_MARKER => break, - 1 => field1 = Some(::stef::buf::decode_string(r)?), - 2 => { - field2 = Some( - ::stef::buf::decode_vec( - r, - |r| { ::stef::buf::decode_bool(r) }, - )?, - ); - } - _ => continue, - } - } - Ok(Self::Variant3 { - field1: field1 - .ok_or(::stef::buf::Error::MissingField { - id: 1, - name: Some("field1"), - })?, - field2: field2 - .ok_or(::stef::buf::Error::MissingField { - id: 2, - name: Some("field2"), - })?, - }) - } - id => Err(::stef::buf::Error::UnknownVariant(id)), - } - } - } - "#}; - - parse(input, expect); - } - - #[test] - fn basic_alias() { - let input = indoc! {r#" - /// Hello world! - type Sample = String; - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - /// Hello world! - #[allow(dead_code, clippy::module_name_repetitions, clippy::option_option)] - pub type Sample = String; - "#}; - - parse(input, expect); - } - - #[test] - fn basic_const() { - let input = indoc! {r#" - /// A bool. - const BOOL: bool = true; - /// An integer. - const INT: u32 = 100; - /// A float. - const FLOAT: f64 = 5.0; - /// A string. - const STRING: string = "hello"; - /// Some bytes. - const BYTES: bytes = [1, 2, 3]; - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - /// A bool. - #[allow(dead_code)] - pub const BOOL: bool = true; - /// An integer. - #[allow(dead_code)] - pub const INT: u32 = 100; - /// A float. - #[allow(dead_code)] - pub const FLOAT: f64 = 5.0; - /// A string. - #[allow(dead_code)] - pub const STRING: &str = "hello"; - /// Some bytes. - #[allow(dead_code)] - pub const BYTES: &[u8] = b"\x01\x02\x03"; - "#}; - - parse(input, expect); - } - - #[test] - fn basic_import() { - let input = indoc! {r#" - use other::module; - use other::module::Type; - "#}; - let expect = indoc! {r#" - #[allow(unused_imports)] - use ::stef::buf::{Decode, Encode}; - use other::module; - use other::module::Type; - "#}; - - parse(input, expect); - } -} diff --git a/crates/stef-build/tests/compiler.rs b/crates/stef-build/tests/compiler.rs index 465eade..9431142 100644 --- a/crates/stef-build/tests/compiler.rs +++ b/crates/stef-build/tests/compiler.rs @@ -14,3 +14,15 @@ fn compile_schema() { assert_snapshot!("compile", format!("{value}"), input.trim()); }); } + +#[test] +fn compile_schema_extra() { + glob!("inputs-extra/*.stef", |path| { + let input = fs::read_to_string(path).unwrap(); + let value = Schema::parse(input.as_str()).unwrap(); + let value = stef_build::compile_schema(&value); + let value = prettyplease::unparse(&syn::parse2(value.clone()).unwrap()); + + assert_snapshot!("compile-extra", format!("{value}"), input.trim()); + }); +} diff --git a/crates/stef-build/tests/inputs-extra/alias.stef b/crates/stef-build/tests/inputs-extra/alias.stef new file mode 100644 index 0000000..e62e55b --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/alias.stef @@ -0,0 +1,2 @@ +/// Hello world! +type Sample = String; diff --git a/crates/stef-build/tests/inputs-extra/const.stef b/crates/stef-build/tests/inputs-extra/const.stef new file mode 100644 index 0000000..e1eba2b --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/const.stef @@ -0,0 +1,10 @@ +/// A bool. +const BOOL: bool = true; +/// An integer. +const INT: u32 = 100; +/// A float. +const FLOAT: f64 = 5.0; +/// A string. +const STRING: string = "hello"; +/// Some bytes. +const BYTES: bytes = [1, 2, 3]; diff --git a/crates/stef-build/tests/inputs-extra/enum.stef b/crates/stef-build/tests/inputs-extra/enum.stef new file mode 100644 index 0000000..e80d1af --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/enum.stef @@ -0,0 +1,9 @@ +/// Hello world! +enum Sample { + Variant1 @1, + Variant2(u32 @1, u8 @2) @2, + Variant3 { + field1: string @1, + field2: vec @2, + } @3, +} diff --git a/crates/stef-build/tests/inputs-extra/import.stef b/crates/stef-build/tests/inputs-extra/import.stef new file mode 100644 index 0000000..9c7f585 --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/import.stef @@ -0,0 +1,2 @@ +use other::module; +use other::module::Type; diff --git a/crates/stef-build/tests/inputs-extra/module.stef b/crates/stef-build/tests/inputs-extra/module.stef new file mode 100644 index 0000000..3e27684 --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/module.stef @@ -0,0 +1,2 @@ +/// Hello world! +mod sample {} diff --git a/crates/stef-build/tests/inputs-extra/struct.stef b/crates/stef-build/tests/inputs-extra/struct.stef new file mode 100644 index 0000000..61c0ef3 --- /dev/null +++ b/crates/stef-build/tests/inputs-extra/struct.stef @@ -0,0 +1,6 @@ +/// Hello world! +struct Sample { + field1: u32 @1, + field2: bytes @2, + field3: (bool, [i16; 4]) @3, +} diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@alias.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@alias.stef.snap new file mode 100644 index 0000000..846f04e --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@alias.stef.snap @@ -0,0 +1,11 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "/// Hello world!\ntype Sample = String;" +input_file: crates/stef-build/tests/inputs-extra/alias.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +/// Hello world! +#[allow(dead_code, clippy::module_name_repetitions, clippy::option_option)] +pub type Sample = String; + diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@const.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@const.stef.snap new file mode 100644 index 0000000..45c2e53 --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@const.stef.snap @@ -0,0 +1,23 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "/// A bool.\nconst BOOL: bool = true;\n/// An integer.\nconst INT: u32 = 100;\n/// A float.\nconst FLOAT: f64 = 5.0;\n/// A string.\nconst STRING: string = \"hello\";\n/// Some bytes.\nconst BYTES: bytes = [1, 2, 3];" +input_file: crates/stef-build/tests/inputs-extra/const.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +/// A bool. +#[allow(dead_code)] +pub const BOOL: bool = true; +/// An integer. +#[allow(dead_code)] +pub const INT: u32 = 100; +/// A float. +#[allow(dead_code)] +pub const FLOAT: f64 = 5.0; +/// A string. +#[allow(dead_code)] +pub const STRING: &str = "hello"; +/// Some bytes. +#[allow(dead_code)] +pub const BYTES: &[u8] = b"\x01\x02\x03"; + diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@enum.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@enum.stef.snap new file mode 100644 index 0000000..a2f4618 --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@enum.stef.snap @@ -0,0 +1,126 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "/// Hello world!\nenum Sample {\n Variant1 @1,\n Variant2(u32 @1, u8 @2) @2,\n Variant3 {\n field1: string @1,\n field2: vec @2,\n } @3,\n}" +input_file: crates/stef-build/tests/inputs-extra/enum.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +/// Hello world! +#[derive(Clone, Debug, PartialEq)] +#[allow(clippy::module_name_repetitions, clippy::option_option)] +pub enum Sample { + Variant1, + Variant2(u32, u8), + Variant3 { field1: String, field2: Vec }, +} +#[automatically_derived] +impl ::stef::Encode for Sample { + #[allow( + clippy::borrow_deref_ref, + clippy::semicolon_if_nothing_returned, + clippy::too_many_lines, + )] + fn encode(&self, w: &mut impl ::stef::BufMut) { + match self { + Self::Variant1 => { + ::stef::buf::encode_id(w, 1); + } + Self::Variant2(n0, n1) => { + ::stef::buf::encode_id(w, 2); + ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, *n0) }); + ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_u8(w, *n1) }); + ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); + } + Self::Variant3 { field1, field2 } => { + ::stef::buf::encode_id(w, 3); + ::stef::buf::encode_field( + w, + 1, + |w| { ::stef::buf::encode_string(w, &*field1) }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_vec( + w, + &*field2, + |w, v| { + ::stef::buf::encode_bool(w, *v); + }, + ) + }, + ); + ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); + } + } + } +} +#[automatically_derived] +impl ::stef::Decode for Sample { + #[allow(clippy::too_many_lines)] + fn decode(r: &mut impl ::stef::Buf) -> ::stef::buf::Result { + match ::stef::buf::decode_id(r)? { + 1 => Ok(Self::Variant1), + 2 => { + let mut n0: Option = None; + let mut n1: Option = None; + loop { + match ::stef::buf::decode_id(r)? { + ::stef::buf::END_MARKER => break, + 1 => n0 = Some(::stef::buf::decode_u32(r)?), + 2 => n1 = Some(::stef::buf::decode_u8(r)?), + _ => continue, + } + } + Ok( + Self::Variant2( + n0 + .ok_or(::stef::buf::Error::MissingField { + id: 1, + name: None, + })?, + n1 + .ok_or(::stef::buf::Error::MissingField { + id: 2, + name: None, + })?, + ), + ) + } + 3 => { + let mut field1: Option = None; + let mut field2: Option> = None; + loop { + match ::stef::buf::decode_id(r)? { + ::stef::buf::END_MARKER => break, + 1 => field1 = Some(::stef::buf::decode_string(r)?), + 2 => { + field2 = Some( + ::stef::buf::decode_vec( + r, + |r| { ::stef::buf::decode_bool(r) }, + )?, + ); + } + _ => continue, + } + } + Ok(Self::Variant3 { + field1: field1 + .ok_or(::stef::buf::Error::MissingField { + id: 1, + name: Some("field1"), + })?, + field2: field2 + .ok_or(::stef::buf::Error::MissingField { + id: 2, + name: Some("field2"), + })?, + }) + } + id => Err(::stef::buf::Error::UnknownVariant(id)), + } + } +} + diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@import.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@import.stef.snap new file mode 100644 index 0000000..7878630 --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@import.stef.snap @@ -0,0 +1,10 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "use other::module;\nuse other::module::Type;" +input_file: crates/stef-build/tests/inputs-extra/import.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +use other::module; +use other::module::Type; + diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@module.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@module.stef.snap new file mode 100644 index 0000000..634ca79 --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@module.stef.snap @@ -0,0 +1,13 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "/// Hello world!\nmod sample {}" +input_file: crates/stef-build/tests/inputs-extra/module.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +/// Hello world! +pub mod sample { + #[allow(unused_imports)] + use ::stef::buf::{Decode, Encode}; +} + diff --git a/crates/stef-build/tests/snapshots/compiler__compile-extra@struct.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile-extra@struct.stef.snap new file mode 100644 index 0000000..0638943 --- /dev/null +++ b/crates/stef-build/tests/snapshots/compiler__compile-extra@struct.stef.snap @@ -0,0 +1,106 @@ +--- +source: crates/stef-build/tests/compiler.rs +expression: "/// Hello world!\nstruct Sample {\n field1: u32 @1,\n field2: bytes @2,\n field3: (bool, [i16; 4]) @3,\n}" +input_file: crates/stef-build/tests/inputs-extra/struct.stef +--- +#[allow(unused_imports)] +use ::stef::buf::{Decode, Encode}; +/// Hello world! +#[derive(Clone, Debug, PartialEq)] +#[allow(clippy::module_name_repetitions, clippy::option_option)] +pub struct Sample { + pub field1: u32, + pub field2: Vec, + pub field3: (bool, [i16; 4]), +} +#[automatically_derived] +impl ::stef::Encode for Sample { + #[allow( + clippy::borrow_deref_ref, + clippy::explicit_auto_deref, + clippy::needless_borrow, + clippy::too_many_lines, + )] + fn encode(&self, w: &mut impl ::stef::BufMut) { + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.field1); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_bytes(w, &self.field2); + }, + ); + ::stef::buf::encode_field( + w, + 3, + |w| { + ::stef::buf::encode_bool(w, self.field3.0); + ::stef::buf::encode_array( + w, + &&(self.field3.1), + |w, v| { + ::stef::buf::encode_i16(w, *v); + }, + ); + }, + ); + ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); + } +} +#[automatically_derived] +impl ::stef::Decode for Sample { + #[allow(clippy::type_complexity, clippy::too_many_lines)] + fn decode(r: &mut impl ::stef::Buf) -> ::stef::buf::Result { + let mut field1: Option = None; + let mut field2: Option> = None; + let mut field3: Option<(bool, [i16; 4])> = None; + loop { + match ::stef::buf::decode_id(r)? { + ::stef::buf::END_MARKER => break, + 1 => field1 = Some(::stef::buf::decode_u32(r)?), + 2 => field2 = Some(::stef::buf::decode_bytes(r)?), + 3 => { + field3 = Some( + { + Ok::< + _, + ::stef::buf::Error, + >(( + ::stef::buf::decode_bool(r)?, + ::stef::buf::decode_array( + r, + |r| { ::stef::buf::decode_i16(r) }, + )?, + )) + }?, + ); + } + _ => continue, + } + } + Ok(Self { + field1: field1 + .ok_or(::stef::buf::Error::MissingField { + id: 1, + name: Some("field1"), + })?, + field2: field2 + .ok_or(::stef::buf::Error::MissingField { + id: 2, + name: Some("field2"), + })?, + field3: field3 + .ok_or(::stef::buf::Error::MissingField { + id: 3, + name: Some("field3"), + })?, + }) + } +} +