1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
pub mod error;
pub mod types;
use std::fmt::Debug;
use std::num::{IntErrorKind, ParseIntError};
use std::path::PathBuf;
use crate::osu_file::types::Decimal;
use crate::parsers::comma;
use nom::bytes::complete::take_till;
use nom::combinator::map_res;
use nom::multi::separated_list0;
use nom::Finish;
use rust_decimal_macros::dec;
use crate::helper;
use crate::helper::macros::*;
use crate::osu_file::Integer;
pub use error::*;
pub use types::*;
versioned_field!(AudioFilename, PathBuf, no_versions, |s| { Ok(PathBuf::from(s)) } -> (), |v| { v.display().to_string() }, PathBuf::from(""));
versioned_field!(AudioLeadIn, Integer, no_versions, |s| { s.parse() } -> ParseIntError,, 0);
versioned_field!(AudioHash, String, no_versions, |s| { Ok(s.to_string()) } -> (),
|v, version| { if version > 13 { None } else { Some(v.to_string()) } },
|version| { if version > 13 { None } else { Some(String::new())}
});
versioned_field!(PreviewTime, Integer, no_versions, |s| { s.parse() } -> ParseIntError,, -1);
versioned_field!(StackLeniency, Decimal, no_versions, |s| { s.parse() } -> (),, Decimal::from(dec!(0.7)));
versioned_field!(LetterboxInBreaks, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(StoryFireInFront, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, true);
versioned_field!(UseSkinSprites, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(AlwaysShowPlayfield, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(SkinPreference, String, no_versions, |s| { Ok(s.to_string()) } -> (),, String::new());
versioned_field!(EpilepsyWarning, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(CountdownOffset, Integer, no_versions, |s| { s.parse() } -> ParseIntError,, 0);
versioned_field!(SpecialStyle, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(WidescreenStoryboard, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(SamplesMatchPlaybackRate, bool, no_versions, |s| { helper::parse_zero_one_bool(s) } -> helper::ParseZeroOneBoolError, boolean, false);
versioned_field!(EditorBookmarks, Vec<Integer>, no_versions, |s| {
let bookmark = map_res(take_till(|c| c == ','), |s: &str| s.parse::<Integer>());
let mut bookmarks = separated_list0(comma::<nom::error::Error<_>>(), bookmark);
let input_len = s.len();
let (s, bookmarks) = bookmarks(s).finish().unwrap();
if s.is_empty() {
Ok(bookmarks)
} else {
let (_, s) = {
let s = if s.len() < input_len {
match s.strip_prefix(',') {
Some(s) => s,
None => s,
}
} else {
s
};
take_till::<_, _, nom::error::Error<_>>(|c| c == ',')(s).unwrap()
};
let err = s.parse::<Integer>().unwrap_err();
let err = if let IntErrorKind::Empty = err.kind() {
ParseError::InvalidCommaList
} else {
ParseError::ParseIntError(err)
};
Err(err)
}
} -> ParseError,
|v, version| {
if version > 5 {
return None;
}
Some(v.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(","))
},
);
versioned_field!(EditorDistanceSpacing, Decimal, no_versions, |s| { s.parse() } -> (),
|v, version| {
if version > 5 {
return None;
}
Some(v.to_string())
}
,);
general_section!(
pub struct General {
pub audio_filename: AudioFilename,
pub audio_lead_in: AudioLeadIn,
pub audio_hash: AudioHash,
pub preview_time: PreviewTime,
pub countdown: Countdown,
pub sample_set: SampleSet,
pub stack_leniency: StackLeniency,
pub mode: Mode,
pub letterbox_in_breaks: LetterboxInBreaks,
pub story_fire_in_front: StoryFireInFront,
pub use_skin_sprites: UseSkinSprites,
pub always_show_playfield: AlwaysShowPlayfield,
pub overlay_position: OverlayPosition,
pub skin_preference: SkinPreference,
pub epilepsy_warning: EpilepsyWarning,
pub countdown_offset: CountdownOffset,
pub special_style: SpecialStyle,
pub widescreen_storyboard: WidescreenStoryboard,
pub samples_match_playback_rate: SamplesMatchPlaybackRate,
pub editor_bookmarks: EditorBookmarks,
pub editor_distance_spacing: EditorDistanceSpacing,
},
ParseError,
" ",
);