Improve wire module

* Set `Size` correctly to `u16`
* Remove `usize` support, since it's OS-dependent

Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
Alexis Sellier 2022-10-18 13:01:17 +02:00
parent 874386540a
commit c306392d13
No known key found for this signature in database
2 changed files with 17 additions and 46 deletions

View File

@ -26,10 +26,13 @@ use crate::storage::refs::Refs;
use crate::storage::refs::SignedRefs; use crate::storage::refs::SignedRefs;
use crate::storage::WriteStorage; use crate::storage::WriteStorage;
/// The default type we use to represent sizes. /// The default type we use to represent sizes on the wire.
/// Four bytes is more than enough for anything sent over the wire. ///
/// Note that in certain cases, we may use only one or two byte types. /// Since wire messages are limited to 64KB by the transport layer,
pub type Size = u32; /// two bytes is enough to represent any message.
///
/// Note that in certain cases, we may use a smaller type.
pub type Size = u16;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Error { pub enum Error {
@ -123,21 +126,6 @@ impl Encode for u64 {
} }
} }
impl Encode for usize {
/// We encode this type to a [`u32`], since there's no need to send larger messages
/// over the network.
fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
assert!(
*self <= u32::MAX as usize,
"Cannot encode sizes larger than {}",
u32::MAX
);
writer.write_u32::<NetworkEndian>(*self as u32)?;
Ok(mem::size_of::<u32>())
}
}
impl Encode for PublicKey { impl Encode for PublicKey {
fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> { fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
self.deref().encode(writer) self.deref().encode(writer)
@ -215,7 +203,11 @@ impl Encode for Id {
impl Encode for Refs { impl Encode for Refs {
fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> { fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
let mut n = self.len().encode(writer)?; let len: Size = self
.len()
.try_into()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
let mut n = len.encode(writer)?;
for (name, oid) in self.iter() { for (name, oid) in self.iter() {
n += name.as_str().encode(writer)?; n += name.as_str().encode(writer)?;
@ -251,7 +243,7 @@ impl Decode for PublicKey {
impl Decode for Refs { impl Decode for Refs {
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> { fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
let len = usize::decode(reader)?; let len = Size::decode(reader)?;
let mut refs = BTreeMap::new(); let mut refs = BTreeMap::new();
for _ in 0..len { for _ in 0..len {
@ -267,7 +259,7 @@ impl Decode for Refs {
impl Decode for git::Oid { impl Decode for git::Oid {
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> { fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
let len = usize::decode(reader)?; let len = Size::decode(reader)? as usize;
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
const expected: usize = mem::size_of::<git::raw::Oid>(); const expected: usize = mem::size_of::<git::raw::Oid>();
@ -318,16 +310,6 @@ impl Decode for u64 {
} }
} }
impl Decode for usize {
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
let size: usize = u32::decode(reader)?
.try_into()
.map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
Ok(size)
}
}
impl<const N: usize> Decode for [u8; N] { impl<const N: usize> Decode for [u8; N] {
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> { fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
let mut ary = [0; N]; let mut ary = [0; N];
@ -587,16 +569,6 @@ mod tests {
assert_eq!(deserialize::<u64>(&serialize(&input)).unwrap(), input); assert_eq!(deserialize::<u64>(&serialize(&input)).unwrap(), input);
} }
#[quickcheck]
fn prop_usize(input: usize) -> quickcheck::TestResult {
if input > u32::MAX as usize {
return quickcheck::TestResult::discard();
}
assert_eq!(deserialize::<usize>(&serialize(&input)).unwrap(), input);
quickcheck::TestResult::passed()
}
#[quickcheck] #[quickcheck]
fn prop_string(input: String) -> quickcheck::TestResult { fn prop_string(input: String) -> quickcheck::TestResult {
if input.len() > u8::MAX as usize { if input.len() > u8::MAX as usize {

View File

@ -1,4 +1,4 @@
use std::{io, net}; use std::{io, mem, net};
use byteorder::{NetworkEndian, ReadBytesExt}; use byteorder::{NetworkEndian, ReadBytesExt};
@ -7,10 +7,9 @@ use crate::prelude::*;
use crate::service::message::*; use crate::service::message::*;
use crate::wire; use crate::wire;
use std::mem::size_of;
/// The maximum supported message size in bytes. /// The maximum supported message size in bytes.
pub const MAX_PAYLOAD_SIZE_BYTES: u16 = u16::MAX - (size_of::<MessageType>() as u16); pub const MAX_PAYLOAD_SIZE_BYTES: wire::Size =
wire::Size::MAX - (mem::size_of::<MessageType>() as wire::Size);
/// Message type. /// Message type.
#[repr(u16)] #[repr(u16)]