added method Beatmap::from_path

This commit is contained in:
MaxOhn
2021-11-17 16:53:51 +01:00
parent 7b3294eda1
commit 82b124fa75
6 changed files with 86 additions and 67 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
## Upcoming
- Nothing as of now
- Added method `Beatmap::from_path` so the file does not have to be created manually for `Beatmap::parse`
# v0.3.0
@@ -9,8 +9,8 @@
- [BREAKING] Instead of returning `PpResult`, performance calculations now return `{Mode}PerformanceAttributes` and `PpResult` has been renamed to `PerformanceAttributes`.
- [BREAKING] Instead of returning `StarResult`, difficulty calculations now return `{Mode}DifficultyAttributes` and `StarResult` has been renamed to `DifficultyAttributes`.
- [BREAKING] Various fields and methods now include `f64` instead of `f32` to stay true to osu!'s original code
- added internal binary crate `pp-gen` to calculate difficulty & pp values via `PerformanceCalculator.dll`
- added internal binary crate `pp-plot` to plot out differences between `pp-gen`'s output and `rosu-pp` values
- Added internal binary crate `pp-gen` to calculate difficulty & pp values via `PerformanceCalculator.dll`
- Added internal binary crate `pp-plot` to plot out differences between `pp-gen`'s output and `rosu-pp` values
- osu: Updated up to commit [9fb2402781ad91c197d51aeec716b0000f52c4d1](https://github.com/ppy/osu/commit/9fb2402781ad91c197d51aeec716b0000f52c4d1) (2021-11-12)
## v0.2.3
+2 -17
View File
@@ -11,16 +11,10 @@ Async is supported through features, see below.
### Usage
```rust
use std::fs::File;
use rosu_pp::{Beatmap, BeatmapExt};
let file = match File::open("/path/to/file.osu") {
Ok(file) => file,
Err(why) => panic!("Could not open file: {}", why),
};
// Parse the map yourself
let map = match Beatmap::parse(file) {
let map = match Beatmap::from_path("/path/to/file.osu") {
Ok(map) => map,
Err(why) => panic!("Error while parsing map: {}", why),
};
@@ -45,7 +39,6 @@ let next_result = map.pp()
.combo(543)
.misses(5)
.n50(3)
.passed_objects(600)
.accuracy(96.5)
.calculate();
@@ -61,16 +54,8 @@ println!("Stars: {} | Max PP: {}", stars, max_pp);
If either the `async_tokio` or `async_std` feature is enabled, beatmap parsing will be async.
```rust
use async_std::fs::File;
// use tokio::fs::File;
let file = match File::open("/path/to/file.osu").await {
Ok(file) => file,
Err(why) => panic!("Could not open file: {}", why),
};
// Parse the map asynchronously
let map = match Beatmap::parse(file).await {
let map = match Beatmap::from_path("/path/to/file.osu").await {
Ok(map) => map,
Err(why) => panic!("Error while parsing map: {}", why),
};
+2 -3
View File
@@ -670,13 +670,12 @@ impl From<FruitsPerformanceAttributes> for FruitsDifficultyAttributes {
#[test]
// #[ignore]
fn custom_fruits() {
use std::{fs::File, time::Instant};
use std::time::Instant;
use crate::{Beatmap, FruitsPP};
let path = "E:Games/osu!/beatmaps/2919116_.osu";
let file = File::open(path).unwrap();
let map = Beatmap::parse(file).unwrap();
let map = Beatmap::from_path(path).unwrap();
let start = Instant::now();
let result = FruitsPP::new(&map).mods(256).calculate();
+2 -18
View File
@@ -7,17 +7,11 @@
//! ## Usage
//!
//! ```no_run
//! use std::fs::File;
//! use rosu_pp::{Beatmap, BeatmapExt};
//!
//! # /*
//! let file = match File::open("/path/to/file.osu") {
//! Ok(file) => file,
//! Err(why) => panic!("Could not open file: {}", why),
//! };
//!
//! // Parse the map yourself
//! let map = match Beatmap::parse(file) {
//! let map = match Beatmap::from_path("/path/to/file.osu") {
//! Ok(map) => map,
//! Err(why) => panic!("Error while parsing map: {}", why),
//! };
@@ -43,7 +37,6 @@
//! .combo(543)
//! .misses(5)
//! .n50(3)
//! .passed_objects(600)
//! .accuracy(96.5)
//! .calculate();
//!
@@ -60,19 +53,10 @@
//!
//! ```no_run
//! use rosu_pp::{Beatmap, BeatmapExt};
//! # /*
//! use async_std::fs::File;
//! # */
//! // use tokio::fs::File;
//!
//! # /*
//! let file = match File::open("/path/to/file.osu").await {
//! Ok(file) => file,
//! Err(why) => panic!("Could not open file: {}", why),
//! };
//!
//! // Parse the map asynchronously
//! let map = match Beatmap::parse(file).await {
//! let map = match Beatmap::from_path("/path/to/file.osu").await {
//! Ok(map) => map,
//! Err(why) => panic!("Error while parsing map: {}", why),
//! };
+2 -3
View File
@@ -601,15 +601,14 @@ fn difficulty_range_od(od: f64) -> f64 {
#[test]
// #[ignore]
fn custom_osu() {
use std::{fs::File, time::Instant};
use std::time::Instant;
use crate::{Beatmap, OsuPP};
let path = "E:Games/osu!/beatmaps/116169_.osu";
let file = File::open(path).unwrap();
let start = Instant::now();
let map = Beatmap::parse(file).unwrap();
let map = Beatmap::from_path(path).unwrap();
let iters = 100;
let accum = start.elapsed();
+75 -23
View File
@@ -17,13 +17,26 @@ use sort::legacy_sort;
use std::cmp::Ordering;
#[cfg(not(any(feature = "async_std", feature = "async_tokio")))]
use std::io::{BufRead, BufReader, Read};
use std::{
fs::File,
io::{BufRead, BufReader, Read},
};
#[cfg(feature = "async_tokio")]
use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader};
use tokio::{
fs::File,
io::{AsyncBufReadExt, AsyncRead, BufReader},
};
#[cfg(not(feature = "async_std"))]
use std::path::Path;
#[cfg(feature = "async_std")]
use async_std::io::{prelude::BufReadExt, BufReader as AsyncBufReader, Read as AsyncRead};
use async_std::{
fs::File,
io::{prelude::BufReadExt, BufReader as AsyncBufReader, Read as AsyncRead},
path::Path,
};
#[cfg(feature = "sliders")]
pub use osu_fruits::*;
@@ -173,10 +186,10 @@ macro_rules! parse_general_body {
}
macro_rules! parse_general {
($reader:ident<$inner:ident>) => {
fn parse_general<R: $inner>(
() => {
fn parse_general<R: Read>(
&mut self,
reader: &mut $reader<R>,
reader: &mut BufReader<R>,
buf: &mut String,
section: &mut Section,
) -> ParseResult<bool> {
@@ -244,10 +257,10 @@ macro_rules! parse_difficulty_body {
}
macro_rules! parse_difficulty {
($reader:ident<$inner:ident>) => {
fn parse_difficulty<R: $inner>(
() => {
fn parse_difficulty<R: Read>(
&mut self,
reader: &mut $reader<R>,
reader: &mut BufReader<R>,
buf: &mut String,
section: &mut Section,
) -> ParseResult<bool> {
@@ -356,10 +369,10 @@ macro_rules! parse_timingpoints_body {
}
macro_rules! parse_timingpoints {
($reader:ident<$inner:ident>) => {
fn parse_timingpoints<R: $inner>(
() => {
fn parse_timingpoints<R: Read>(
&mut self,
reader: &mut $reader<R>,
reader: &mut BufReader<R>,
buf: &mut String,
section: &mut Section,
) -> ParseResult<bool> {
@@ -606,10 +619,10 @@ macro_rules! parse_hitobjects_body {
}
macro_rules! parse_hitobjects {
($reader:ident<$inner:ident>) => {
fn parse_hitobjects<R: $inner>(
() => {
fn parse_hitobjects<R: Read>(
&mut self,
reader: &mut $reader<R>,
reader: &mut BufReader<R>,
buf: &mut String,
section: &mut Section,
) -> ParseResult<bool> {
@@ -688,19 +701,52 @@ macro_rules! parse_body {
}
macro_rules! parse {
($reader:ident<$inner:ident>) => {
pub fn parse<R: $inner>(input: R) -> ParseResult<Self> {
parse_body!($reader<$inner>: input)
() => {
/// Parse a beatmap from a `.osu` file.
///
/// As argument you can give anything that implements [`std::io::Read`].
/// You'll likely want to pass (a reference of) a [`File`](std::fs::File)
/// or the file's content as a slice of bytes (`&[u8]`).
pub fn parse<R: Read>(input: R) -> ParseResult<Self> {
parse_body!(BufReader<Read>: input)
}
};
(async $reader:ident<$inner:ident>) => {
/// Parse a beatmap from a `.osu` file.
///
/// As argument you can give anything that implements `tokio::io::AsyncRead`
/// or `async_std::io::Read`, depending which feature you chose.
/// You'll likely want to pass a `File`
/// or the file's content as a slice of bytes (`&[u8]`).
pub async fn parse<R: $inner + Unpin>(input: R) -> ParseResult<Self> {
parse_body!($reader<$inner>: input)
}
};
}
macro_rules! from_path {
() => {
/// Pass the path to a `.osu` file.
///
/// Useful when you don't want to create the [`File`](std::fs::File) manually.
/// If you have the file lying around already though (and plan on re-using it),
/// passing `&file` to [`parse`](Beatmap::parse) should be preferred.
pub fn from_path<P: AsRef<Path>>(path: P) -> ParseResult<Self> {
Self::parse(File::open(path)?)
}
};
(async $path:ident) => {
/// Pass the path to a `.osu` file.
///
/// Useful when you don't want to create the file manually.
pub async fn from_path<P: AsRef<$path>>(path: P) -> ParseResult<Self> {
Self::parse(File::open(path).await?).await
}
};
}
/// The mode of a beatmap.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[allow(clippy::upper_case_acronyms)]
@@ -911,11 +957,13 @@ mod osu_fruits {
#[cfg(not(any(feature = "async_std", feature = "async_tokio")))]
impl Beatmap {
parse!(BufReader<Read>);
parse_general!(BufReader<Read>);
parse_difficulty!(BufReader<Read>);
parse_timingpoints!(BufReader<Read>);
parse_hitobjects!(BufReader<Read>);
parse!();
parse_general!();
parse_difficulty!();
parse_timingpoints!();
parse_hitobjects!();
from_path!();
}
#[cfg(feature = "async_tokio")]
@@ -925,6 +973,8 @@ impl Beatmap {
parse_difficulty!(async BufReader<AsyncRead>);
parse_timingpoints!(async BufReader<AsyncRead>);
parse_hitobjects!(async BufReader<AsyncRead>);
from_path!(async Path);
}
#[cfg(feature = "async_std")]
@@ -934,6 +984,8 @@ impl Beatmap {
parse_difficulty!(async AsyncBufReader<AsyncRead>);
parse_timingpoints!(async AsyncBufReader<AsyncRead>);
parse_hitobjects!(async AsyncBufReader<AsyncRead>);
from_path!(async Path);
}
#[inline]