Skip to main content

Key

Struct Key 

Source
pub struct Key(pub u32);
Expand description

Represents keys that can be pressed during osu!standard gameplay. Includes mouse buttons (M1, M2), keyboard keys (K1, K2), and smoke.

Tuple Fields§

§0: u32

Implementations§

Source§

impl Key

Source

pub const M1: Self

Source

pub const M2: Self

Source

pub const K1: Self

Source

pub const K2: Self

Source

pub const SMOKE: Self

Source

pub fn value(&self) -> u32

Examples found in repository?
examples/example_1.rs (line 81)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let osr_path = Path::new("assets/test.osr");
6
7    // Check if the file exists
8    if !osr_path.exists() {
9        eprintln!("Error: File 'assets/test.osr' not found!");
10        eprintln!("Please place a valid .osr file at 'assets/test.osr' to run this example.");
11        return Ok(());
12    }
13
14    println!("Reading replay from: {}", osr_path.display());
15
16    // Parse the replay file
17    match Replay::from_path(osr_path) {
18        Ok(replay) => {
19            println!("\n=== Replay Information ===");
20            println!("Username: {}", replay.username);
21            println!("Game Mode: {:?}", replay.mode);
22            println!("Game Version: {}", replay.game_version);
23            println!("Beatmap Hash: {}", replay.beatmap_hash);
24            println!("Score: {}", replay.score);
25            println!("Max Combo: {}", replay.max_combo);
26            println!("Perfect: {}", replay.perfect);
27            println!("Mods: {:?} (value: {})", replay.mods, replay.mods.value());
28            println!("Timestamp: {}", replay.timestamp);
29            println!("Replay ID: {}", replay.replay_id);
30
31            // Hit counts
32            println!("\n=== Hit Counts ===");
33            println!("300s: {}", replay.count_300);
34            println!("100s: {}", replay.count_100);
35            println!("50s: {}", replay.count_50);
36            println!("Gekis: {}", replay.count_geki);
37            println!("Katus: {}", replay.count_katu);
38            println!("Misses: {}", replay.count_miss);
39
40            // RNG seed
41            if let Some(seed) = replay.rng_seed {
42                println!("\n=== RNG Seed ===");
43                println!("Seed: {}", seed);
44            }
45
46            // Life bar information
47            if let Some(ref life_bar) = replay.life_bar_graph {
48                println!("\n=== Life Bar ===");
49                println!("Life bar states: {}", life_bar.len());
50                if !life_bar.is_empty() {
51                    println!(
52                        "First state: time={}ms, life={}",
53                        life_bar[0].time, life_bar[0].life
54                    );
55                    println!(
56                        "Last state: time={}ms, life={}",
57                        life_bar[life_bar.len() - 1].time,
58                        life_bar[life_bar.len() - 1].life
59                    );
60                }
61            } else {
62                println!("\n=== Life Bar ===");
63                println!("No life bar data available");
64            }
65
66            // Replay data information
67            println!("\n=== Replay Data ===");
68            println!("Total events: {}", replay.replay_data.len());
69
70            if !replay.replay_data.is_empty() {
71                println!("\nFirst 5 events:");
72                for (i, event) in replay.replay_data.iter().take(5).enumerate() {
73                    match event {
74                        ReplayEvent::Osu(e) => {
75                            println!(
76                                "  {}: Osu - time_delta={}ms, x={}, y={}, keys={}",
77                                i + 1,
78                                e.time_delta,
79                                e.x,
80                                e.y,
81                                e.keys.value()
82                            );
83                        }
84                        ReplayEvent::Taiko(e) => {
85                            println!(
86                                "  {}: Taiko - time_delta={}ms, x={}, keys={}",
87                                i + 1,
88                                e.time_delta,
89                                e.x,
90                                e.keys.value()
91                            );
92                        }
93                        ReplayEvent::Catch(e) => {
94                            println!(
95                                "  {}: Catch - time_delta={}ms, x={}, dashing={}",
96                                i + 1,
97                                e.time_delta,
98                                e.x,
99                                e.dashing
100                            );
101                        }
102                        ReplayEvent::Mania(e) => {
103                            println!(
104                                "  {}: Mania - time_delta={}ms, keys={}",
105                                i + 1,
106                                e.time_delta,
107                                e.keys.value()
108                            );
109                        }
110                    }
111                }
112
113                if replay.replay_data.len() > 5 {
114                    println!("  ... and {} more events", replay.replay_data.len() - 5);
115                }
116            }
117
118            // Calculate total replay duration
119            let total_time: i32 = replay
120                .replay_data
121                .iter()
122                .map(|event| event.time_delta())
123                .sum();
124
125            if total_time > 0 {
126                let minutes = total_time / 60000;
127                let seconds = (total_time % 60000) / 1000;
128                let milliseconds = total_time % 1000;
129                println!(
130                    "\nTotal replay duration: {}:{:02}.{:03}",
131                    minutes, seconds, milliseconds
132                );
133            }
134
135            // Try to write the replay back to verify our packer works
136            println!("\n=== Testing Write Functionality ===");
137            let output_path = "assets/test_output.osr";
138            match replay.write_path(output_path) {
139                Ok(()) => {
140                    println!("Successfully wrote replay to: {}", output_path);
141
142                    // Verify by reading it back
143                    match Replay::from_path(output_path) {
144                        Ok(replay_copy) => {
145                            println!("Successfully verified written replay!");
146                            println!("Original username: {}", replay.username);
147                            println!("Copy username: {}", replay_copy.username);
148                            println!("Scores match: {}", replay.score == replay_copy.score);
149                        }
150                        Err(e) => {
151                            eprintln!("Error reading back written replay: {}", e);
152                        }
153                    }
154                }
155                Err(e) => {
156                    eprintln!("Error writing replay: {}", e);
157                }
158            }
159
160            // Test uncompressed packing
161            println!("\n=== Testing Uncompressed Packing ===");
162            let uncompressed_path = "assets/test_uncompressed.osr";
163            match replay.pack_uncompressed() {
164                Ok(uncompressed_data) => {
165                    std::fs::write(uncompressed_path, &uncompressed_data)?;
166                    println!(
167                        "Successfully wrote uncompressed replay to: {}",
168                        uncompressed_path
169                    );
170
171                    // Compare file sizes
172                    let compressed_size = std::fs::metadata(output_path)?.len();
173                    let uncompressed_size = std::fs::metadata(uncompressed_path)?.len();
174
175                    println!("Compressed file size: {} bytes", compressed_size);
176                    println!("Uncompressed file size: {} bytes", uncompressed_size);
177                    println!(
178                        "Size difference: {} bytes ({}%)",
179                        uncompressed_size as i64 - compressed_size as i64,
180                        ((uncompressed_size as f64 - compressed_size as f64)
181                            / compressed_size as f64
182                            * 100.0) as i32
183                    );
184
185                    // Verify uncompressed replay can be read back
186                    match Replay::from_path(uncompressed_path) {
187                        Ok(replay_uncompressed) => {
188                            println!("Successfully verified uncompressed replay!");
189                            println!(
190                                "Scores match: {}",
191                                replay.score == replay_uncompressed.score
192                            );
193                            println!(
194                                "Event counts match: {}",
195                                replay.replay_data.len() == replay_uncompressed.replay_data.len()
196                            );
197                        }
198                        Err(e) => {
199                            eprintln!("Error reading back uncompressed replay: {}", e);
200                        }
201                    }
202                }
203                Err(e) => {
204                    eprintln!("Error packing uncompressed replay: {}", e);
205                }
206            }
207        }
208        Err(e) => {
209            eprintln!("Error reading replay: {}", e);
210            eprintln!("Make sure the file is a valid .osr replay file.");
211        }
212    }
213
214    Ok(())
215}

Trait Implementations§

Source§

impl Clone for Key

Source§

fn clone(&self) -> Key

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Key

Source§

impl Debug for Key

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Key

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for Key

Source§

impl From<u32> for Key

Source§

fn from(value: u32) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for Key

Source§

fn eq(&self, other: &Key) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Key

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Key

Auto Trait Implementations§

§

impl Freeze for Key

§

impl RefUnwindSafe for Key

§

impl Send for Key

§

impl Sync for Key

§

impl Unpin for Key

§

impl UnsafeUnpin for Key

§

impl UnwindSafe for Key

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.