Skip to content

Commit

Permalink
Simplify TlRead trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed Nov 28, 2024
1 parent ec80c34 commit 7a87b57
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 150 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tl-proto"
description = "A collection of traits for working with TL serialization/deserialization"
authors = ["Ivan Kalinin <i.kalinin@dexpa.io>"]
repository = "https://github.com/broxus/tl-proto"
version = "0.4.10"
version = "0.5.0"
edition = "2021"
include = ["src/**/*.rs", "README.md"]
license = "MIT"
Expand All @@ -18,7 +18,7 @@ sha2 = { version = "0.10", optional = true }
smallvec = { version = "1.7", features = ["union", "const_generics"] }
thiserror = "1.0.64"

tl-proto-proc = { version = "=0.4.7", path = "proc", optional = true }
tl-proto-proc = { version = "=0.5.0", path = "proc", optional = true }

[features]
default = ["derive", "bytes", "hash"]
Expand Down
2 changes: 1 addition & 1 deletion proc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tl-proto-proc"
description = "A collection of traits for working with TL serialization/deserialization"
authors = ["Ivan Kalinin <i.kalinin@dexpa.io>"]
repository = "https://github.com/broxus/tl-proto"
version = "0.4.7"
version = "0.5.0"
edition = "2021"
include = ["src/**/*.rs", "../README.md"]
license = "MIT"
Expand Down
22 changes: 11 additions & 11 deletions proc/src/tl_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ fn build_enum(variants: &[ast::Variant]) -> TokenStream {
});

quote! {
fn read_from(__packet: &'tl [u8], __offset: &mut usize) -> _tl_proto::TlResult<Self> {
match u32::read_from(__packet, __offset) {
fn read_from(__packet: &mut &'tl [u8]) -> _tl_proto::TlResult<Self> {
match u32::read_from(__packet) {
Ok(constructor) => match constructor {
#(#variants)*
_ => Err(_tl_proto::TlError::UnknownConstructor)
Expand All @@ -145,7 +145,7 @@ fn build_struct(
.map(|id| {
let id = id.unwrap_explicit();
quote! {
match u32::read_from(__packet, __offset) {
match u32::read_from(__packet) {
Ok(constructor) => {
if constructor != #id {
return Err(_tl_proto::TlError::UnknownConstructor)
Expand All @@ -160,7 +160,7 @@ fn build_struct(
let read_from = build_read_from(quote! { Self }, style, fields);

quote! {
fn read_from(__packet: &'tl [u8], __offset: &mut usize) -> _tl_proto::TlResult<Self> {
fn read_from(__packet: &mut &'tl [u8]) -> _tl_proto::TlResult<Self> {
#(#prefix)*
#read_from
}
Expand Down Expand Up @@ -194,7 +194,7 @@ fn build_read_from(ident: TokenStream, style: &ast::Style, fields: &[ast::Field]

if field.attrs.flags {
quote! {
let #ident = match <u32 as _tl_proto::TlRead<'tl>>::read_from(__packet, __offset) {
let #ident = match <u32 as _tl_proto::TlRead<'tl>>::read_from(__packet) {
Ok(flags) => flags,
Err(e) => return Err(e),
};
Expand All @@ -210,22 +210,22 @@ fn build_read_from(ident: TokenStream, style: &ast::Style, fields: &[ast::Field]

let read = if let Some(with) = &field.attrs.with {
quote! {
match #with::read(__packet, __offset) {
match #with::read(__packet) {
Ok(value) => value,
Err(e) => return Err(e),
}
}
} else if let Some(read_with) = &field.attrs.read_with {
quote! {
match #read_with(__packet, __offset) {
match #read_with(__packet) {
Ok(value) => value,
Err(e) => return Err(e),
}
}
} else {
quote! {
match <<#ty as IntoIterator>::Item as _tl_proto::TlRead<'tl>>::read_from(
__packet, __offset,
__packet,
) {
Ok(value) => value,
Err(e) => return Err(e),
Expand All @@ -242,21 +242,21 @@ fn build_read_from(ident: TokenStream, style: &ast::Style, fields: &[ast::Field]
}
} else if let Some(with) = &field.attrs.with {
quote! {
let #ident = match #with::read(__packet, __offset) {
let #ident = match #with::read(__packet) {
Ok(value) => value,
Err(e) => return Err(e),
};
}
} else if let Some(read_with) = &field.attrs.read_with {
quote! {
let #ident = match #read_with(__packet, __offset) {
let #ident = match #read_with(__packet) {
Ok(value) => value,
Err(e) => return Err(e),
};
}
} else {
quote! {
let #ident = match <#ty as _tl_proto::TlRead<'tl>>::read_from(__packet, __offset) {
let #ident = match <#ty as _tl_proto::TlRead<'tl>>::read_from(__packet) {
Ok(value) => value,
Err(e) => return Err(e),
};
Expand Down
6 changes: 3 additions & 3 deletions src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ where
{
type Repr = Boxed;

fn read_from(packet: &'a [u8], offset: &mut usize) -> TlResult<Self> {
match u32::read_from(packet, offset) {
Ok(id) if id == T::TL_ID => match T::read_from(packet, offset) {
fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
match u32::read_from(packet) {
Ok(id) if id == T::TL_ID => match T::read_from(packet) {
Ok(data) => Ok(BoxedWrapper(data)),
Err(e) => Err(e),
},
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ mod tuple;
mod util;

/// Tries to deserialize `T` from the TL representation.
pub fn deserialize<'a, T>(packet: &'a [u8]) -> TlResult<T>
pub fn deserialize<'a, T>(mut packet: &'a [u8]) -> TlResult<T>
where
T: TlRead<'a>,
{
T::read_from(packet, &mut 0)
T::read_from(&mut packet)
}

/// Tries to deserialize `T` as boxed from the TL representation.
Expand Down
72 changes: 33 additions & 39 deletions src/primitive.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::traits::*;
use crate::util::*;

impl TlRead<'_> for () {
type Repr = Bare;

fn read_from(_packet: &'_ [u8], _offset: &mut usize) -> TlResult<Self> {
fn read_from(_packet: &mut &'_ [u8]) -> TlResult<Self> {
Ok(())
}
}
Expand All @@ -28,8 +27,8 @@ impl TlWrite for () {
impl TlRead<'_> for bool {
type Repr = Boxed;

fn read_from(packet: &[u8], offset: &mut usize) -> TlResult<Self> {
match u32::read_from(packet, offset) {
fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
match u32::read_from(packet) {
Ok(BOOL_TRUE) => Ok(true),
Ok(BOOL_FALSE) => Ok(false),
Ok(_) => Err(TlError::UnknownConstructor),
Expand Down Expand Up @@ -61,15 +60,14 @@ macro_rules! impl_read_from_packet(
type Repr = Bare;

#[inline(always)]
fn read_from(packet: &[u8], offset: &mut usize) -> TlResult<Self> {
if unlikely(packet.len() < *offset + std::mem::size_of::<$ty>()) {
Err(TlError::UnexpectedEof)
} else {
let value = <$ty>::from_le_bytes(unsafe {
*(packet.as_ptr().add(*offset) as *const [u8; std::mem::size_of::<$ty>()])
});
*offset += std::mem::size_of::<$ty>();
Ok(value)
fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
match packet.split_first_chunk() {
Some((first, tail)) => {
let value = <$ty>::from_le_bytes(*first);
*packet = tail;
Ok(value)
}
None => Err(TlError::UnexpectedEof),
}
}
}
Expand Down Expand Up @@ -233,8 +231,8 @@ macro_rules! impl_non_zero {
type Repr = Bare;

#[inline(always)]
fn read_from(packet: &[u8], offset: &mut usize) -> TlResult<Self> {
match <$ty>::new(<$read_ty>::read_from(packet, offset)?) {
fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
match <$ty>::new(<$read_ty>::read_from(packet)?) {
Some(value) => Ok(value),
None => Err(TlError::InvalidData),
}
Expand Down Expand Up @@ -276,71 +274,67 @@ mod test {
fn read_non_zero() {
// u32
assert!(matches!(
std::num::NonZeroU32::read_from(&[0, 0], &mut 0).unwrap_err(),
std::num::NonZeroU32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
TlError::UnexpectedEof
));
assert!(matches!(
std::num::NonZeroU32::read_from(&[0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroU32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::InvalidData
));
let mut offset = 0;
let mut packet: &[u8] = &[123, 0, 0, 0];
assert_eq!(
std::num::NonZeroU32::read_from(&[123, 0, 0, 0], &mut offset).unwrap(),
std::num::NonZeroU32::read_from(&mut packet).unwrap(),
std::num::NonZeroU32::new(123).unwrap(),
);
assert_eq!(offset, 4);
assert!(packet.is_empty());

// i32
assert!(matches!(
std::num::NonZeroI32::read_from(&[0, 0], &mut 0).unwrap_err(),
std::num::NonZeroI32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
TlError::UnexpectedEof
));
assert!(matches!(
std::num::NonZeroI32::read_from(&[0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroI32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::InvalidData
));
let mut offset = 0;
let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff];
assert_eq!(
std::num::NonZeroI32::read_from(&[0xfe, 0xff, 0xff, 0xff], &mut offset).unwrap(),
std::num::NonZeroI32::read_from(&mut packet).unwrap(),
std::num::NonZeroI32::new(-2).unwrap(),
);
assert_eq!(offset, 4);
assert!(packet.is_empty());

// u64
assert!(matches!(
std::num::NonZeroU64::read_from(&[0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::UnexpectedEof
));
assert!(matches!(
std::num::NonZeroU64::read_from(&[0, 0, 0, 0, 0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::InvalidData
));
let mut offset = 0;
let mut packet: &[u8] = &[123, 0, 0, 0, 0, 0, 0, 0];
assert_eq!(
std::num::NonZeroU64::read_from(&[123, 0, 0, 0, 0, 0, 0, 0], &mut offset).unwrap(),
std::num::NonZeroU64::read_from(&mut packet).unwrap(),
std::num::NonZeroU64::new(123).unwrap(),
);
assert_eq!(offset, 8);
assert!(packet.is_empty());

// i64
assert!(matches!(
std::num::NonZeroI64::read_from(&[0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::UnexpectedEof
));

assert!(matches!(
std::num::NonZeroI64::read_from(&[0, 0, 0, 0, 0, 0, 0, 0], &mut 0).unwrap_err(),
std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
TlError::InvalidData
));
let mut offset = 0;
let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
assert_eq!(
std::num::NonZeroI64::read_from(
&[0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
&mut offset
)
.unwrap(),
std::num::NonZeroI64::read_from(&mut packet,).unwrap(),
std::num::NonZeroI64::new(-2).unwrap(),
);
assert_eq!(offset, 8);
assert!(packet.is_empty());
}
}
Loading

0 comments on commit 7a87b57

Please sign in to comment.