diff --git a/Cargo.lock b/Cargo.lock index aa4dd10..0384d5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ dependencies = [ [[package]] name = "bits-io" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334d5023bf30d7edb7798b4dbbef2e2d3c121ecd885445cb1f6b0dbe879ab5e8" +checksum = "db8ee456cc74052abbbfc9e94cff1484c5b23b200aec976a47854078bc16a272" dependencies = [ "bitvec", "bytes", diff --git a/Notes.md b/Notes.md index 3eca824..dd53fd2 100644 --- a/Notes.md +++ b/Notes.md @@ -486,3 +486,23 @@ after doing the code I realized I had no good way to test it because the built-in buf doesn't provide anything that could be used with it, which makes me think putting it in parsely might not make sense. This use case _could_ have used the custom reader attribute, maybe? + +### Using ParselyRead/ParselyWrite with types other than BitBuf/BitBufMut + +For things like RTP parsing, we don't want to use the BitBuf/BitBufMut +abstractions because they limit the efficiency we can get when we use +Bits/BitsMut directly. It would be nice to be able to leverage +ParselyRead/ParselyWrite for other types as well: i.e. manually implementing it +for the RTP packet types. The problem is that the trait bound +(BitBuf/BitBufMut) is built into the trait, so we can't really do that. I +looked at changing the "buffer" type to be an associated type, but that has a +couple problems: + +* We can't do `type Buf = impl BitBuf` or `type Buf = dyn BitBUf` so we lose +the ability to say "some BitBuf type". We _could_ add another layer of +indirection here, but that's a bit of a bummer. +* Supporting multiple buffer types also makes me think that it'd be nice to be +able to provide different/optimized read/write impls for different types (e.g. +one for BitBuf and another when we know it's a Bits specifically or something) + +--> look into a refactoring of the read/write traits to accomplish this diff --git a/impl/Cargo.toml b/impl/Cargo.toml index f97d4c1..e024d42 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -7,7 +7,7 @@ description = "Macro-based struct serialization/deserialization" [dependencies] anyhow = "1" -bits-io = { version = "0.5.4" } +bits-io = { version = "0.5.5" } darling = "0.20.10" paste = "1" proc-macro2 = "1" diff --git a/impl/src/code_gen/gen_read.rs b/impl/src/code_gen/gen_read.rs index 2f4a62d..3cc2b73 100644 --- a/impl/src/code_gen/gen_read.rs +++ b/impl/src/code_gen/gen_read.rs @@ -24,7 +24,7 @@ pub fn generate_parsely_read_impl(data: ParselyReadData) -> TokenStream { fn generate_plain_read(ty: &syn::Type, context_values: &[syn::Expr]) -> TokenStream { quote! { - #ty::read::<_, T>(buf, (#(#context_values,)*)) + #ty::read::(buf, (#(#context_values,)*)) } } @@ -182,11 +182,8 @@ fn generate_parsely_read_impl_struct( #(#field_reads)* - let __bytes_remaining_end = buf.remaining_bytes(); - let mut __amount_read = __bytes_remaining_start - __bytes_remaining_end; - while __amount_read % #alignment != 0 { + while (__bytes_remaining_start - buf.remaining_bytes()) % #alignment != 0 { buf.get_u8().context("padding")?; - __amount_read += 1; } } } else { @@ -202,9 +199,9 @@ fn generate_parsely_read_impl_struct( }; quote! { - impl ::#crate_name::ParselyRead for #struct_name { + impl ::#crate_name::ParselyRead for #struct_name { type Ctx = (#(#context_types,)*); - fn read(buf: &mut B, #ctx_var: (#(#context_types,)*)) -> ::#crate_name::ParselyResult { + fn read(buf: &mut B, #ctx_var: (#(#context_types,)*)) -> ::#crate_name::ParselyResult { #(#context_assignments)* #body diff --git a/impl/src/code_gen/gen_write.rs b/impl/src/code_gen/gen_write.rs index 296c402..eff0cc2 100644 --- a/impl/src/code_gen/gen_write.rs +++ b/impl/src/code_gen/gen_write.rs @@ -60,18 +60,18 @@ fn generate_parsely_write_impl_struct( } else if f.ty.is_option() { field_write_output.extend(quote! { if let Some(ref v) = self.#field_name { - #write_type::write::<_, T>(v, buf, (#(#context_values,)*)).with_context(|| format!("Writing field '{}'", #field_name_string))?; + #write_type::write::(v, buf, (#(#context_values,)*)).with_context(|| format!("Writing field '{}'", #field_name_string))?; } }); } else if f.ty.is_collection() { field_write_output.extend(quote! { self.#field_name.iter().enumerate().map(|(idx, v)| { - #write_type::write::<_, T>(v, buf, (#(#context_values,)*)).with_context(|| format!("Index {idx}")) + #write_type::write::(v, buf, (#(#context_values,)*)).with_context(|| format!("Index {idx}")) }).collect::>>().with_context(|| format!("Writing field '{}'", #field_name_string))?; }); } else { field_write_output.extend(quote! { - #write_type::write::<_, T>(&self.#field_name, buf, (#(#context_values,)*)).with_context(|| format!("Writing field '{}'", #field_name_string))?; + #write_type::write::(&self.#field_name, buf, (#(#context_values,)*)).with_context(|| format!("Writing field '{}'", #field_name_string))?; }); } @@ -127,11 +127,8 @@ fn generate_parsely_write_impl_struct( #(#field_writes)* - let __bytes_remaining_end = buf.remaining_mut_bytes(); - let mut __amount_written = __bytes_remaining_start - __bytes_remaining_end; - while __amount_written % #alignment != 0 { + while (__bytes_remaining_start - buf.remaining_mut_bytes()) % #alignment != 0 { let _ = buf.put_u8(0).context("padding")?; - __amount_written += 1; } } @@ -142,9 +139,9 @@ fn generate_parsely_write_impl_struct( }; quote! { - impl ::#crate_name::ParselyWrite for #struct_name { + impl ::#crate_name::ParselyWrite for #struct_name { type Ctx = (#(#context_types,)*); - fn write( + fn write( &self, buf: &mut B, ctx: Self::Ctx, diff --git a/impl/src/error.rs b/impl/src/error.rs index 97ac835..b48b39e 100644 --- a/impl/src/error.rs +++ b/impl/src/error.rs @@ -5,25 +5,24 @@ pub type ParselyResult = anyhow::Result; /// Helper trait to coerce values of both `T: ParselyWrite` and `Result: E: /// Into` into `ParselyResult`. We need a trait specifically for writing because /// if we don't bound the impl for `T` in some way there's ambiguity: the compiler doesn't know if -/// we want `ParselyResult` or `ParselyResult>`. -pub trait IntoWritableParselyResult { - fn into_parsely_result(self) -> ParselyResult; +pub trait IntoWritableParselyResult { + fn into_writable_parsely_result(self) -> ParselyResult; } -impl IntoWritableParselyResult for T +impl IntoWritableParselyResult for T where - T: ParselyWrite, + T: ParselyWrite, { - fn into_parsely_result(self) -> ParselyResult { + fn into_writable_parsely_result(self) -> ParselyResult { Ok(self) } } -impl IntoWritableParselyResult for Result +impl IntoWritableParselyResult for Result where E: Into, { - fn into_parsely_result(self) -> ParselyResult { + fn into_writable_parsely_result(self) -> ParselyResult { self.map_err(Into::into) } } @@ -33,12 +32,15 @@ where /// concrete type and we can rely on type inference in order to figure out what that should be. /// Because of that we don't want/need the `ParselyWrite` trait bounds on the impl like we have /// above for the writable side, so we need a different trait here. +// TODO: remove the 'read' from these method calls, as they get used in places like context +// expression evaluation where the writable limitations also don't exist, but aren't exactly on the +// 'read path' (for example when syncing state) pub trait IntoParselyResult { - fn into_parsely_result_read(self) -> ParselyResult; + fn into_parsely_result(self) -> ParselyResult; } impl IntoParselyResult for T { - fn into_parsely_result_read(self) -> ParselyResult { + fn into_parsely_result(self) -> ParselyResult { Ok(self) } } @@ -47,7 +49,7 @@ impl IntoParselyResult for Result where E: Into, { - fn into_parsely_result_read(self) -> ParselyResult { + fn into_parsely_result(self) -> ParselyResult { self.map_err(Into::into) } } diff --git a/impl/src/lib.rs b/impl/src/lib.rs index ed702ee..9670f45 100644 --- a/impl/src/lib.rs +++ b/impl/src/lib.rs @@ -17,6 +17,7 @@ pub use bits_io::{ }; pub mod nsw_types { + pub use bits_io::nsw_types::from_bitslice::BitSliceUxExts; pub use bits_io::nsw_types::*; } diff --git a/impl/src/model_types.rs b/impl/src/model_types.rs index 403e841..952b6d8 100644 --- a/impl/src/model_types.rs +++ b/impl/src/model_types.rs @@ -261,9 +261,9 @@ impl MapExpr { // value? tokens.extend(quote! { { - let original_value = ::#crate_name::ParselyRead::read::<_, T>(buf, ()) + let original_value = ::#crate_name::ParselyRead::read::(buf, ()) .with_context(|| format!("Reading raw value for field '{}'", #field_name_string))?; - (#map_expr)(original_value).into_parsely_result_read() + (#map_expr)(original_value).into_parsely_result() .with_context(|| format!("Mapping raw value for field '{}'", #field_name_string)) } }) @@ -275,9 +275,13 @@ impl MapExpr { let map_expr = &self.0; tokens.extend(quote! { { - let mapped_value = (#map_expr)(&self.#field_name).into_parsely_result() + let mapped_value = (#map_expr)(&self.#field_name); + // Coerce the result of the mapping function into a ParselyResult where we know + // T is writable to the buffer. We need to use this syntax because otherwise the + // compiler gets caught up on trying to infer the buffer type. + let result = <_ as IntoWritableParselyResult<_, B>>::into_writable_parsely_result(mapped_value) .with_context(|| format!("Mapping raw value for field '{}'", #field_name_string))?; - ::#crate_name::ParselyWrite::write::(&mapped_value, buf, ()) + ::#crate_name::ParselyWrite::write::(&result, buf, ()) .with_context(|| format!("Writing mapped value for field '{}'", #field_name_string))?; } }) diff --git a/impl/src/parsely_read.rs b/impl/src/parsely_read.rs index 1c06bc5..b2182ba 100644 --- a/impl/src/parsely_read.rs +++ b/impl/src/parsely_read.rs @@ -2,16 +2,16 @@ use bits_io::prelude::*; use crate::error::ParselyResult; -pub trait ParselyRead: Sized { +pub trait ParselyRead: Sized { type Ctx; - fn read(buf: &mut B, ctx: Self::Ctx) -> ParselyResult; + fn read(buf: &mut B, ctx: Self::Ctx) -> ParselyResult; } macro_rules! impl_parsely_read_builtin { ($type:ty) => { - impl ParselyRead for $type { + impl ParselyRead for $type { type Ctx = (); - fn read(buf: &mut B, _: Self::Ctx) -> ParselyResult { + fn read(buf: &mut B, _: Self::Ctx) -> ParselyResult { ::paste::paste! { Ok(buf.[]()?) } @@ -22,9 +22,9 @@ macro_rules! impl_parsely_read_builtin { macro_rules! impl_parsely_read_builtin_bo { ($type:ty) => { - impl ParselyRead for $type { + impl ParselyRead for $type { type Ctx = (); - fn read(buf: &mut B, _: Self::Ctx) -> ParselyResult { + fn read(buf: &mut B, _: Self::Ctx) -> ParselyResult { ::paste::paste! { Ok(buf.[]::()?) } @@ -33,9 +33,9 @@ macro_rules! impl_parsely_read_builtin_bo { }; } -impl ParselyRead for bool { +impl ParselyRead for bool { type Ctx = (); - fn read(buf: &mut B, _ctx: Self::Ctx) -> ParselyResult { + fn read(buf: &mut B, _ctx: Self::Ctx) -> ParselyResult { Ok(buf.get_bool()?) } } diff --git a/impl/src/parsely_write.rs b/impl/src/parsely_write.rs index b45ec11..3393337 100644 --- a/impl/src/parsely_write.rs +++ b/impl/src/parsely_write.rs @@ -22,21 +22,17 @@ macro_rules! impl_stateless_sync { }; } -pub trait ParselyWrite: StateSync + Sized { +pub trait ParselyWrite: StateSync + Sized { type Ctx; - fn write(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()>; + fn write(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()>; } macro_rules! impl_parsely_write_builtin { ($type:ty) => { - impl ParselyWrite for $type { + impl ParselyWrite for $type { type Ctx = (); - fn write( - &self, - buf: &mut B, - _: Self::Ctx, - ) -> ParselyResult<()> { + fn write(&self, buf: &mut B, _: Self::Ctx) -> ParselyResult<()> { ::paste::paste! { Ok(buf.[](*self)?) } @@ -47,13 +43,9 @@ macro_rules! impl_parsely_write_builtin { macro_rules! impl_parsely_write_builtin_bo { ($type:ty) => { - impl ParselyWrite for $type { + impl ParselyWrite for $type { type Ctx = (); - fn write( - &self, - buf: &mut B, - _: Self::Ctx, - ) -> ParselyResult<()> { + fn write(&self, buf: &mut B, _: Self::Ctx) -> ParselyResult<()> { ::paste::paste! { Ok(buf.[]::(*self)?) } diff --git a/tests/expand/alignment.expanded.rs b/tests/expand/alignment.expanded.rs index 3efff43..948c66b 100644 --- a/tests/expand/alignment.expanded.rs +++ b/tests/expand/alignment.expanded.rs @@ -3,43 +3,33 @@ use parsely_rs::*; struct Foo { one: u8, } -impl ::parsely_rs::ParselyRead for Foo { +impl ::parsely_rs::ParselyRead for Foo { type Ctx = (); - fn read( + fn read( buf: &mut B, _ctx: (), ) -> ::parsely_rs::ParselyResult { let __bytes_remaining_start = buf.remaining_bytes(); - let one = u8::read::<_, T>(buf, ()).with_context(|| "Reading field 'one'")?; - let __bytes_remaining_end = buf.remaining_bytes(); - let mut __amount_read = __bytes_remaining_start - __bytes_remaining_end; - while __amount_read % 4usize != 0 { + let one = u8::read::(buf, ()).with_context(|| "Reading field 'one'")?; + while (__bytes_remaining_start - buf.remaining_bytes()) % 4usize != 0 { buf.get_u8().context("padding")?; - __amount_read += 1; } Ok(Self { one }) } } -impl ::parsely_rs::ParselyWrite for Foo { +impl ::parsely_rs::ParselyWrite for Foo { type Ctx = (); - fn write( - &self, - buf: &mut B, - ctx: Self::Ctx, - ) -> ParselyResult<()> { + fn write(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()> { let __bytes_remaining_start = buf.remaining_mut_bytes(); - u8::write::<_, T>(&self.one, buf, ()) + u8::write::(&self.one, buf, ()) .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Writing field \'{0}\'", "one"), ); res }))?; - let __bytes_remaining_end = buf.remaining_mut_bytes(); - let mut __amount_written = __bytes_remaining_start - __bytes_remaining_end; - while __amount_written % 4usize != 0 { + while (__bytes_remaining_start - buf.remaining_mut_bytes()) % 4usize != 0 { let _ = buf.put_u8(0).context("padding")?; - __amount_written += 1; } Ok(()) } diff --git a/tests/expand/assertion.expanded.rs b/tests/expand/assertion.expanded.rs index d0dcc10..de4eb2c 100644 --- a/tests/expand/assertion.expanded.rs +++ b/tests/expand/assertion.expanded.rs @@ -3,13 +3,13 @@ struct Foo { #[parsely(assertion = "|v: &u8| *v % 2 == 0")] value: u8, } -impl ::parsely_rs::ParselyRead for Foo { +impl ::parsely_rs::ParselyRead for Foo { type Ctx = (); - fn read( + fn read( buf: &mut B, _ctx: (), ) -> ::parsely_rs::ParselyResult { - let value = u8::read::<_, T>(buf, ()) + let value = u8::read::(buf, ()) .and_then(|read_value| { let assertion_func = |v: &u8| *v % 2 == 0; if !assertion_func(&read_value) { @@ -33,13 +33,9 @@ impl ::parsely_rs::ParselyRead for Foo { Ok(Self { value }) } } -impl ::parsely_rs::ParselyWrite for Foo { +impl ::parsely_rs::ParselyWrite for Foo { type Ctx = (); - fn write( - &self, - buf: &mut B, - ctx: Self::Ctx, - ) -> ParselyResult<()> { + fn write(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()> { let __value_assertion_func = |v: &u8| *v % 2 == 0; if !__value_assertion_func(&self.value) { return ::anyhow::__private::Err( @@ -56,7 +52,7 @@ impl ::parsely_rs::ParselyWrite for Foo { ), ); } - u8::write::<_, T>(&self.value, buf, ()) + u8::write::(&self.value, buf, ()) .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Writing field \'{0}\'", "value"), diff --git a/tests/expand/map.expanded.rs b/tests/expand/map.expanded.rs index 17eacca..d672265 100644 --- a/tests/expand/map.expanded.rs +++ b/tests/expand/map.expanded.rs @@ -4,14 +4,14 @@ struct Foo { #[parsely_write(map = "|v: &str| { v.parse::() }")] value: String, } -impl ::parsely_rs::ParselyRead for Foo { +impl ::parsely_rs::ParselyRead for Foo { type Ctx = (); - fn read( + fn read( buf: &mut B, _ctx: (), ) -> ::parsely_rs::ParselyResult { let value = { - let original_value = ::parsely_rs::ParselyRead::read::<_, T>(buf, ()) + let original_value = ::parsely_rs::ParselyRead::read::(buf, ()) .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Reading raw value for field \'{0}\'", "value"), @@ -19,7 +19,7 @@ impl ::parsely_rs::ParselyRead for Foo { res }))?; (|v: u8| { v.to_string() })(original_value) - .into_parsely_result_read() + .into_parsely_result() .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Mapping raw value for field \'{0}\'", "value"), @@ -31,23 +31,22 @@ impl ::parsely_rs::ParselyRead for Foo { Ok(Self { value }) } } -impl ::parsely_rs::ParselyWrite for Foo { +impl ::parsely_rs::ParselyWrite for Foo { type Ctx = (); - fn write( - &self, - buf: &mut B, - ctx: Self::Ctx, - ) -> ParselyResult<()> { + fn write(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()> { { - let mapped_value = (|v: &str| { v.parse::() })(&self.value) - .into_parsely_result() + let mapped_value = (|v: &str| { v.parse::() })(&self.value); + let result = <_ as IntoWritableParselyResult< + _, + B, + >>::into_writable_parsely_result(mapped_value) .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Mapping raw value for field \'{0}\'", "value"), ); res }))?; - ::parsely_rs::ParselyWrite::write::(&mapped_value, buf, ()) + ::parsely_rs::ParselyWrite::write::(&result, buf, ()) .with_context(|| ::alloc::__export::must_use({ let res = ::alloc::fmt::format( format_args!("Writing mapped value for field \'{0}\'", "value"), diff --git a/tests/ui/pass/alignment.rs b/tests/ui/pass/alignment.rs index 8888a1c..ddecd9a 100644 --- a/tests/ui/pass/alignment.rs +++ b/tests/ui/pass/alignment.rs @@ -9,12 +9,12 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[42, 0, 0, 0]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, ()).unwrap(); + let foo = Foo::read::(&mut bits, ()).unwrap(); assert_eq!(foo.one, 42); assert_eq!(bits.remaining_bytes(), 0); let mut bits_mut = BitsMut::new(); - Foo::write::<_, NetworkOrder>(&foo, &mut bits_mut, ()).unwrap(); + Foo::write::(&foo, &mut bits_mut, ()).unwrap(); assert_eq!(bits_mut.len_bytes(), 4); } diff --git a/tests/ui/pass/basic_read.rs b/tests/ui/pass/basic_read.rs index 9cf6ca0..cdc9e0c 100644 --- a/tests/ui/pass/basic_read.rs +++ b/tests/ui/pass/basic_read.rs @@ -8,6 +8,6 @@ struct Foo { fn main() { let mut cursor = Bits::from_static_bytes(&[0b10101010]); - let foo = Foo::read::<_, NetworkOrder>(&mut cursor, ()).expect("successful parse"); + let foo = Foo::read::(&mut cursor, ()).expect("successful parse"); assert!(foo.one); } diff --git a/tests/ui/pass/basic_write.rs b/tests/ui/pass/basic_write.rs index 25aeeeb..5c22057 100644 --- a/tests/ui/pass/basic_write.rs +++ b/tests/ui/pass/basic_write.rs @@ -13,5 +13,5 @@ fn main() { two: u3::new(4), }; - Foo::write::<_, NetworkOrder>(&foo, &mut bits_mut, ()).unwrap(); + Foo::write::(&foo, &mut bits_mut, ()).unwrap(); } diff --git a/tests/ui/pass/context.rs b/tests/ui/pass/context.rs index 416e081..67b35c8 100644 --- a/tests/ui/pass/context.rs +++ b/tests/ui/pass/context.rs @@ -20,7 +20,7 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[1, 2, 3, 4]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, (2,)).expect("successful parse"); + let foo = Foo::read::(&mut bits, (2,)).expect("successful parse"); // Should have only read 2 values assert_eq!(foo.data.len(), 2); diff --git a/tests/ui/pass/count.rs b/tests/ui/pass/count.rs index 83278fb..e56956e 100644 --- a/tests/ui/pass/count.rs +++ b/tests/ui/pass/count.rs @@ -10,6 +10,6 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[2, 1, 2, 3]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, ()).expect("successful parse"); + let foo = Foo::read::(&mut bits, ()).expect("successful parse"); assert_eq!(foo.data.len(), 2); } diff --git a/tests/ui/pass/map.rs b/tests/ui/pass/map.rs index 58922e1..21162e9 100644 --- a/tests/ui/pass/map.rs +++ b/tests/ui/pass/map.rs @@ -12,7 +12,7 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[42]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, ()).expect("successful parse"); + let foo = Foo::read::(&mut bits, ()).expect("successful parse"); assert_eq!(foo.value, "42"); let mut bits_mut = BitsMut::new(); @@ -21,7 +21,7 @@ fn main() { value: String::from("42"), }; - foo.write::<_, NetworkOrder>(&mut bits_mut, ()) + foo.write::(&mut bits_mut, ()) .expect("successful write"); let mut bits = bits_mut.freeze(); assert_eq!(bits.get_u8().unwrap(), 42); diff --git a/tests/ui/pass/when.rs b/tests/ui/pass/when.rs index 81e4aec..41b3623 100644 --- a/tests/ui/pass/when.rs +++ b/tests/ui/pass/when.rs @@ -9,7 +9,7 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[0b1_0000001, 2]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, ()).expect("successful parse"); + let foo = Foo::read::(&mut bits, ()).expect("successful parse"); assert_eq!(foo.value, Some(u7::new(1))); } diff --git a/tests/ui/pass/while.rs b/tests/ui/pass/while.rs index 98e7c00..0473e68 100644 --- a/tests/ui/pass/while.rs +++ b/tests/ui/pass/while.rs @@ -9,6 +9,6 @@ struct Foo { fn main() { let mut bits = Bits::from_static_bytes(&[2, 1, 2, 3]); - let foo = Foo::read::<_, NetworkOrder>(&mut bits, ()).expect("successful parse"); + let foo = Foo::read::(&mut bits, ()).expect("successful parse"); assert_eq!(foo.data.len(), 4); }