parse cleanup

This commit is contained in:
MaxOhn
2021-04-17 13:41:08 +02:00
parent 041032ee14
commit ed33eda909
2 changed files with 43 additions and 45 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
## Upcoming ## Upcoming
- No changes so far - parse:
- Cleanup
# v0.2.0 # v0.2.0
+33 -36
View File
@@ -37,8 +37,8 @@ macro_rules! sort {
} }
macro_rules! next_field { macro_rules! next_field {
($opt:expr, $($val:tt)*) => { ($opt:expr, $err:literal) => {
$opt.ok_or_else(|| ParseError::MissingField(stringify!($($val)*)))? $opt.ok_or_else(|| ParseError::MissingField($err))?
}; };
} }
@@ -172,24 +172,24 @@ macro_rules! parse_general_body {
macro_rules! parse_general { macro_rules! parse_general {
($reader:ident<$inner:ident>) => { ($reader:ident<$inner:ident>) => {
fn parse_difficulty<R: $inner>( fn parse_general<R: $inner>(
&mut self, &mut self,
reader: &mut $reader<R>, reader: &mut $reader<R>,
buf: &mut String, buf: &mut String,
section: &mut Section, section: &mut Section,
) -> ParseResult<bool> { ) -> ParseResult<bool> {
parse_difficulty_body!(self, reader, buf, section) parse_general_body!(self, reader, buf, section)
} }
}; };
(async $reader:ident<$inner:ident>) => { (async $reader:ident<$inner:ident>) => {
async fn parse_difficulty<R: $inner + Unpin>( async fn parse_general<R: $inner + Unpin>(
&mut self, &mut self,
reader: &mut $reader<R>, reader: &mut $reader<R>,
buf: &mut String, buf: &mut String,
section: &mut Section, section: &mut Section,
) -> ParseResult<bool> { ) -> ParseResult<bool> {
parse_difficulty_body!(self, reader, buf, section) parse_general_body!(self, reader, buf, section)
} }
}; };
} }
@@ -230,12 +230,12 @@ macro_rules! parse_difficulty_body {
$buf.clear(); $buf.clear();
} }
$self.od = next_field!(od, od); $self.od = next_field!(od, "od");
$self.cs = next_field!(cs, cs); $self.cs = next_field!(cs, "cs");
$self.hp = next_field!(hp, hp); $self.hp = next_field!(hp, "hp");
$self.ar = ar.unwrap_or($self.od); $self.ar = ar.unwrap_or($self.od);
$self.sv = next_field!(sv, sv); $self.sv = next_field!(sv, "sv");
$self.tick_rate = next_field!(tick_rate, sv); $self.tick_rate = next_field!(tick_rate, "sv");
Ok(empty) Ok(empty)
}}; }};
@@ -243,24 +243,24 @@ macro_rules! parse_difficulty_body {
macro_rules! parse_difficulty { macro_rules! parse_difficulty {
($reader:ident<$inner:ident>) => { ($reader:ident<$inner:ident>) => {
fn parse_general<R: $inner>( fn parse_difficulty<R: $inner>(
&mut self, &mut self,
reader: &mut $reader<R>, reader: &mut $reader<R>,
buf: &mut String, buf: &mut String,
section: &mut Section, section: &mut Section,
) -> ParseResult<bool> { ) -> ParseResult<bool> {
parse_general_body!(self, reader, buf, section) parse_difficulty_body!(self, reader, buf, section)
} }
}; };
(async $reader:ident<$inner:ident>) => { (async $reader:ident<$inner:ident>) => {
async fn parse_general<R: $inner + Unpin>( async fn parse_difficulty<R: $inner + Unpin>(
&mut self, &mut self,
reader: &mut $reader<R>, reader: &mut $reader<R>,
buf: &mut String, buf: &mut String,
section: &mut Section, section: &mut Section,
) -> ParseResult<bool> { ) -> ParseResult<bool> {
parse_general_body!(self, reader, buf, section) parse_difficulty_body!(self, reader, buf, section)
} }
}; };
} }
@@ -306,12 +306,14 @@ macro_rules! parse_timingpoints_body {
let mut split = line.split(','); let mut split = line.split(',');
let time = next_field!(split.next(), timing point time) let time = next_field!(split.next(), "timing point time")
.trim() .trim()
.parse::<f32>()?; .parse::<f32>()?;
validate_float!(time); validate_float!(time);
let beat_len = next_field!(split.next(), beat len).trim().parse::<f32>()?; let beat_len = next_field!(split.next(), "beat len")
.trim()
.parse::<f32>()?;
if beat_len < 0.0 { if beat_len < 0.0 {
let point = DifficultyPoint { let point = DifficultyPoint {
@@ -383,7 +385,6 @@ macro_rules! parse_timingpoints {
#[cfg(any(feature = "osu", feature = "fruits"))] #[cfg(any(feature = "osu", feature = "fruits"))]
parse_timingpoints_body!(self, reader, buf, section) parse_timingpoints_body!(self, reader, buf, section)
} }
}; };
} }
@@ -408,11 +409,11 @@ macro_rules! parse_hitobjects_body {
let mut split = line.split(','); let mut split = line.split(',');
let pos = Pos2 { let pos = Pos2 {
x: next_field!(split.next(), x position).parse()?, x: next_field!(split.next(), "x position").parse()?,
y: next_field!(split.next(), y position).parse()?, y: next_field!(split.next(), "y position").parse()?,
}; };
let time = next_field!(split.next(), hitobject time) let time = next_field!(split.next(), "hitobject time")
.trim() .trim()
.parse::<f32>()?; .parse::<f32>()?;
@@ -422,7 +423,7 @@ macro_rules! parse_hitobjects_body {
unsorted = true; unsorted = true;
} }
let kind: u8 = next_field!(split.next(), hitobject kind).parse()?; let kind: u8 = next_field!(split.next(), "hitobject kind").parse()?;
let sound = split.next().map(str::parse).transpose()?.unwrap_or(0); let sound = split.next().map(str::parse).transpose()?.unwrap_or(0);
let kind = if kind & Self::CIRCLE_FLAG > 0 { let kind = if kind & Self::CIRCLE_FLAG > 0 {
@@ -437,13 +438,13 @@ macro_rules! parse_hitobjects_body {
all(feature = "osu", not(feature = "no_sliders_no_leniency")) all(feature = "osu", not(feature = "no_sliders_no_leniency"))
))] ))]
{ {
let mut curve_points = Vec::with_capacity(8); let mut curve_points = Vec::with_capacity(4);
curve_points.push(pos); curve_points.push(pos);
let mut curve_point_iter = next_field!(split.next(), curve points).split('|'); let mut curve_point_iter = next_field!(split.next(), "curve points").split('|');
let mut path_type: PathType = let mut path_type: PathType =
next_field!(curve_point_iter.next(), path kind).parse()?; next_field!(curve_point_iter.next(), "path kind").parse()?;
for pos in curve_point_iter { for pos in curve_point_iter {
let mut v = pos.split(':').map(str::parse); let mut v = pos.split(':').map(str::parse);
@@ -457,9 +458,7 @@ macro_rules! parse_hitobjects_body {
if $self.version <= 6 && curve_points.len() >= 2 { if $self.version <= 6 && curve_points.len() >= 2 {
if path_type == PathType::Linear { if path_type == PathType::Linear {
path_type = PathType::Bezier; path_type = PathType::Bezier;
} } else if curve_points.len() == 2
if curve_points.len() == 2
&& (pos == curve_points[0] || pos == curve_points[1]) && (pos == curve_points[0] || pos == curve_points[1])
{ {
path_type = PathType::Linear; path_type = PathType::Linear;
@@ -467,9 +466,8 @@ macro_rules! parse_hitobjects_body {
} }
// Reduce amount of curvepoints but keep the elements evenly spaced. // Reduce amount of curvepoints but keep the elements evenly spaced.
// Necessary to handle maps like XNOR (2573164) that have // Necessary to handle maps like XNOR (2573164) which have
// tens of thousands of curvepoints more efficiently. // tens of thousands of curvepoints more efficiently.
if curve_points.len() > CURVE_POINT_THRESHOLD {
while curve_points.len() > CURVE_POINT_THRESHOLD { while curve_points.len() > CURVE_POINT_THRESHOLD {
let last = curve_points[curve_points.len() - 1]; let last = curve_points[curve_points.len() - 1];
let last_idx = (curve_points.len() - 1) / 2; let last_idx = (curve_points.len() - 1) / 2;
@@ -481,23 +479,22 @@ macro_rules! parse_hitobjects_body {
curve_points[last_idx] = last; curve_points[last_idx] = last;
curve_points.truncate(last_idx + 1); curve_points.truncate(last_idx + 1);
} }
}
if curve_points.is_empty() { if curve_points.is_empty() {
HitObjectKind::Circle HitObjectKind::Circle
} else { } else {
let repeats = next_field!(split.next(), repeats) let repeats = next_field!(split.next(), "repeats")
.parse::<usize>()? .parse::<usize>()?
.min(9000); .min(9000);
let len = next_field!(split.next(), pixel len) let pixel_len = next_field!(split.next(), "pixel len")
.parse::<f32>()? .parse::<f32>()?
.max(0.0) .max(0.0)
.min(MAX_COORDINATE_VALUE); .min(MAX_COORDINATE_VALUE);
HitObjectKind::Slider { HitObjectKind::Slider {
repeats, repeats,
pixel_len: len, pixel_len,
curve_points, curve_points,
path_type, path_type,
} }
@@ -519,7 +516,7 @@ macro_rules! parse_hitobjects_body {
} }
} else if kind & Self::SPINNER_FLAG > 0 { } else if kind & Self::SPINNER_FLAG > 0 {
$self.n_spinners += 1; $self.n_spinners += 1;
let end_time = next_field!(split.next(), spinner endtime).parse()?; let end_time = next_field!(split.next(), "spinner endtime").parse()?;
HitObjectKind::Spinner { end_time } HitObjectKind::Spinner { end_time }
} else if kind & Self::HOLD_FLAG > 0 { } else if kind & Self::HOLD_FLAG > 0 {
@@ -527,7 +524,7 @@ macro_rules! parse_hitobjects_body {
let mut end = time; let mut end = time;
if let Some(next) = split.next() { if let Some(next) = split.next() {
end = end.max(next_field!(next.split(':').next(), hold endtime).parse()?); end = end.max(next_field!(next.split(':').next(), "hold endtime").parse()?);
} }
HitObjectKind::Hold { end_time: end } HitObjectKind::Hold { end_time: end }