Avoid truncation
Error where truncation can occurr and prevent truncation in the future by using `type::from()` (which checks for truncation) instead of `as type` (which doesn’t).
This commit is contained in:
parent
e64ae362ef
commit
56d36f2732
|
@ -345,7 +345,7 @@ impl ConvertedChart {
|
|||
},
|
||||
difficulty: beatmap::Difficulty {
|
||||
hp_drain_rate: config.hp_drain.map_from(self.difficulty.clone().into()),
|
||||
circle_size: self.difficulty.players as f32 * 4.0,
|
||||
circle_size: f32::from(self.difficulty.players) * 4.0,
|
||||
overall_difficulty: config.accuracy.map_from(self.difficulty.clone().into()),
|
||||
approach_rate: 8.0,
|
||||
slider_multiplier: 0.64,
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::fmt;
|
|||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
use std::num;
|
||||
|
||||
use byteorder::{ReadBytesExt, LE};
|
||||
use log::{debug, info, trace, warn};
|
||||
|
@ -12,7 +13,7 @@ use thiserror::Error;
|
|||
use crate::mini_parser::{MiniParser, MiniParserError};
|
||||
use crate::utils;
|
||||
|
||||
const MEASURE_LENGTH: i32 = 4096;
|
||||
const MEASURE_LENGTH: f32 = 4096.0;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
|
@ -21,7 +22,7 @@ pub enum Error {
|
|||
#[error(transparent)]
|
||||
IOError(#[from] io::Error),
|
||||
#[error(transparent)]
|
||||
TryFromIntError(#[from] std::num::TryFromIntError),
|
||||
TryFromIntError(#[from] num::TryFromIntError),
|
||||
#[error(transparent)]
|
||||
MiniParserError(#[from] MiniParserError),
|
||||
}
|
||||
|
@ -29,7 +30,7 @@ pub enum Error {
|
|||
/// Convert time offset to beats
|
||||
/// time offset is the measure times MEASURE_LENGTH
|
||||
fn measure_to_beats(metric: i32) -> f32 {
|
||||
4.0 * metric as f32 / MEASURE_LENGTH as f32
|
||||
4.0 * metric as f32 / MEASURE_LENGTH
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
|
@ -385,7 +386,7 @@ impl SSQ {
|
|||
};
|
||||
|
||||
loop {
|
||||
let length = cursor.read_i32::<LE>()? as usize;
|
||||
let length: usize = cursor.read_i32::<LE>()?.try_into()?;
|
||||
trace!("Found chunk (length {})", length);
|
||||
if length == 0 {
|
||||
break;
|
||||
|
@ -401,7 +402,7 @@ impl SSQ {
|
|||
match chunk_type {
|
||||
1 => {
|
||||
debug!("Parsing tempo changes (ticks/s: {})", parameter);
|
||||
ssq.tempo_changes = TempoChanges::parse(parameter as i32, &data)?;
|
||||
ssq.tempo_changes = TempoChanges::parse(parameter.into(), &data)?;
|
||||
}
|
||||
3 => {
|
||||
debug!("Parsing step chunk ({})", Difficulty::from(parameter));
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![warn(clippy::cast_lossless)]
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use(quickcheck)]
|
||||
extern crate quickcheck_macros;
|
||||
|
|
|
@ -29,7 +29,7 @@ fn assemble_hit_object_type(hit_object_type: u8, new_combo: bool, skip_combo_col
|
|||
}
|
||||
|
||||
pub fn column_to_x(column: u8, columns: u8) -> OsuPixel {
|
||||
((512 * column as OsuPixel + 256) / columns as OsuPixel) as OsuPixel
|
||||
(512 * OsuPixel::from(column) + 256) / OsuPixel::from(columns)
|
||||
}
|
||||
|
||||
#[derive(ToPrimitive, Clone)]
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::convert::TryInto;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use log::{debug, trace};
|
||||
use thiserror::Error;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const COEFFS: &[CoefSet] = &[
|
||||
|
@ -14,6 +16,12 @@ const COEFFS: &[CoefSet] = &[
|
|||
(392, -232),
|
||||
];
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("unable to create file of size {0} (larger than 2^32)")]
|
||||
TooLarge(usize),
|
||||
}
|
||||
|
||||
trait WaveChunk {
|
||||
fn to_chunk(&self) -> Vec<u8>;
|
||||
}
|
||||
|
@ -87,17 +95,22 @@ impl WaveChunk for RIFFHeader {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn build_wav(format: WaveFormat, data: &[u8]) -> Vec<u8> {
|
||||
pub fn build_wav(format: WaveFormat, data: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
debug!("Building file");
|
||||
let length: u32 = data
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|_| Error::TooLarge(data.len()))?;
|
||||
|
||||
let riff_header = RIFFHeader {
|
||||
file_size: 82 + data.len() as u32,
|
||||
file_size: 82 + length,
|
||||
};
|
||||
|
||||
let fact = WaveFact {
|
||||
length_samples: ((data.len() as u32 / format.n_block_align as u32)
|
||||
* ((format.n_block_align - (7 * format.n_channels)) * 8) as u32
|
||||
length_samples: ((length / u32::from(format.n_block_align))
|
||||
* u32::from((format.n_block_align - (7 * format.n_channels)) * 8)
|
||||
/ 4)
|
||||
/ format.n_channels as u32,
|
||||
/ u32::from(format.n_channels),
|
||||
};
|
||||
|
||||
let mut buf = Cursor::new(Vec::new());
|
||||
|
@ -110,8 +123,8 @@ pub fn build_wav(format: WaveFormat, data: &[u8]) -> Vec<u8> {
|
|||
buf.write_all(&fact.to_chunk()).unwrap();
|
||||
|
||||
write!(buf, "data").unwrap();
|
||||
buf.write_u32::<LittleEndian>(data.len() as u32).unwrap();
|
||||
buf.write_u32::<LittleEndian>(length).unwrap();
|
||||
buf.write_all(data).unwrap();
|
||||
|
||||
buf.into_inner()
|
||||
Ok(buf.into_inner())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||
use std::convert::TryInto;
|
||||
use std::io;
|
||||
use std::io::Cursor;
|
||||
use std::num;
|
||||
|
||||
use byteorder::{ReadBytesExt, LE};
|
||||
use log::{debug, info, trace, warn};
|
||||
|
@ -23,6 +24,10 @@ pub enum Error {
|
|||
IOError(#[from] io::Error),
|
||||
#[error(transparent)]
|
||||
MiniParserError(#[from] MiniParserError),
|
||||
#[error(transparent)]
|
||||
ADPCMError(#[from] adpcm::Error),
|
||||
#[error(transparent)]
|
||||
TryFromIntError(#[from] num::TryFromIntError),
|
||||
}
|
||||
|
||||
#[derive(Clone, FromPrimitive, Debug, PartialEq)]
|
||||
|
@ -60,11 +65,11 @@ impl TryInto<adpcm::WaveFormat> for Format {
|
|||
return Err(Error::UnsupportedFormat(self.tag));
|
||||
}
|
||||
|
||||
let n_block_align = (self.alignment as u16 + 22) * self.channels;
|
||||
let n_block_align = (u16::from(self.alignment) + 22) * self.channels;
|
||||
let n_samples_per_block =
|
||||
(((n_block_align - (7 * self.channels)) * 8) / (4 * self.channels)) + 2;
|
||||
let n_avg_bytes_per_sec =
|
||||
(self.sample_rate / n_samples_per_block as u32) * n_block_align as u32;
|
||||
(self.sample_rate / u32::from(n_samples_per_block)) * u32::from(n_block_align);
|
||||
|
||||
Ok(adpcm::WaveFormat {
|
||||
n_channels: self.channels,
|
||||
|
@ -113,8 +118,8 @@ impl Header {
|
|||
let offset = cursor.read_u32::<LE>()?;
|
||||
let length = cursor.read_u32::<LE>()?;
|
||||
segment_positions.push(SegmentPosition {
|
||||
offset: offset as usize,
|
||||
length: length as usize,
|
||||
offset: offset.try_into()?,
|
||||
length: length.try_into()?,
|
||||
})
|
||||
}
|
||||
Ok(Header { segment_positions })
|
||||
|
@ -145,9 +150,9 @@ impl Info {
|
|||
let _build_time = cursor.read_u32::<LE>()?;
|
||||
|
||||
Ok(Self {
|
||||
entry_count: entry_count as usize,
|
||||
entry_count: entry_count.try_into()?,
|
||||
name,
|
||||
entry_name_element_size: entry_name_element_size as usize,
|
||||
entry_name_element_size: entry_name_element_size.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -181,8 +186,8 @@ impl Entry {
|
|||
Ok(Self {
|
||||
name: "".to_string(),
|
||||
format: format.into(),
|
||||
data_offset: data_offset as usize,
|
||||
data_length: data_length as usize,
|
||||
data_offset: data_offset.try_into()?,
|
||||
data_length: data_length.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +269,10 @@ pub struct Sound<'a> {
|
|||
impl Sound<'_> {
|
||||
pub fn to_wav(&self) -> Result<Vec<u8>, Error> {
|
||||
match &self.format.tag {
|
||||
FormatTag::ADPCM => Ok(adpcm::build_wav(self.format.clone().try_into()?, self.data)),
|
||||
FormatTag::ADPCM => Ok(adpcm::build_wav(
|
||||
self.format.clone().try_into()?,
|
||||
self.data,
|
||||
)?),
|
||||
_ => Err(Error::UnsupportedFormat(self.format.tag.clone())),
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue