arrowvortex_clipboard/
lib.rs

1#![warn(missing_docs)]
2
3/*!
4Small library for encoding and decoding [ArrowVortex](https://arrowvortex.ddrnl.com/) clipboard
5data. Ported from [av-clipboard-lib](https://github.com/DeltaEpsilon7787/av-clipboard-lib), a Python
6libary by DeltaEpsilon.
7
8Main credit goes to DeltaEpsilon for reverse-engineering ArrowVortex' clipboard functions and
9implementing the first ArrowVortex clipboard library.
10
11```rust
12// EtternaOnline noteskin template pattern (https://etternaonline.com/noteskins)
13let data = r#"ArrowVortex:notes:!"8i-K)chjJHuM^!#P_Z![IjrJi#:bJ2UO3!BC3L"%E"#;
14
15// Decode string into Vec<Note>
16let notes = match arrowvortex_clipboard::decode(data.as_bytes())? {
17    arrowvortex_clipboard::DecodeResult::RowBasedNotes(notes) => notes,
18    _ => panic!("Unexpected data type"),
19};
20println!("{:?}", notes);
21
22// Encode &[Note] into string
23let buffer = arrowvortex_clipboard::encode_row_based_notes(&notes)?;
24println!("{}", buffer);
25
26// Verify that string stayed identical after roundtrip
27assert_eq!(data, buffer);
28# Ok::<(), Box<dyn std::error::Error>>(())
29```
30*/
31
32mod decode;
33pub use decode::*;
34
35mod encode;
36pub use encode::*;
37
38/// Note-type specific data
39#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub enum NoteKind<P> {
41    /// Normal tap
42    Tap,
43    /// Hold note, spanning from this note's row up to end_row
44    Hold {
45        /// Where this hold note ends
46        end_pos: P,
47    },
48    /// Mine note
49    Mine,
50    /// Roll note, spanning from this note's row up to end_row
51    Roll {
52        /// Where this roll note ends
53        end_pos: P,
54    },
55    /// Lift note
56    Lift,
57    /// Fake note
58    Fake,
59}
60
61impl<P> Default for NoteKind<P> {
62    fn default() -> Self {
63        Self::Tap
64    }
65}
66
67/// Singular note
68#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
69pub struct Note<P> {
70    /// Position of this note
71    pub pos: P,
72    /// Column of this note. Left-most column is 0
73    pub column: u8,
74    /// Type and type-specific data for this note
75    pub kind: NoteKind<P>,
76}
77
78/// Tempo event type specific data
79#[derive(Debug, Clone, PartialEq)]
80pub enum TempoEventKind {
81    /// Changes BPM (beats per minute)
82    Bpm {
83        /// BPM value
84        bpm: f64,
85    },
86    /// Stops for a number of seconds
87    Stop {
88        /// Duration in seconds
89        time: f64,
90    },
91    /// Delays for a number of seconds
92    Delay {
93        /// Duration in seconds
94        time: f64,
95    },
96    /// Warps over a number of rows
97    Warp {
98        /// Length in rows
99        num_skipped_rows: u32,
100    },
101    /// Changes time signature
102    TimeSignature {
103        /// Numerator of the time signature fraction
104        numerator: u32,
105        /// Denominator of the time signature fraction
106        denominator: u32,
107    },
108    /// Changes number of ticks per beat
109    Ticks {
110        /// Number of ticks per beat
111        num_ticks: u32,
112    },
113    /// Changes combo multiplier settings
114    Combo {
115        /// Combo multiplier
116        combo_multiplier: u32,
117        /// Miss multiplier
118        miss_multiplier: u32,
119    },
120    /// Unknown
121    Speed {
122        /// Unknown
123        ratio: f64,
124        /// Unknown
125        delay: f64,
126        /// Unknown
127        delay_is_time: bool,
128    },
129    /// Changes scroll speed
130    Scroll {
131        /// Scroll speed multiplier
132        ratio: f64,
133    },
134    /// Converts all notes in the following rows into fakes
135    FakeSegment {
136        /// Length in rows
137        num_fake_rows: u32,
138    },
139    /// Label with arbitrary content
140    Label {
141        /// Message content
142        message: Vec<u8>,
143    },
144}
145
146/// Singular tempo event
147#[derive(Debug, Clone, PartialEq)]
148pub struct TempoEvent {
149    /// Row position of this tempo event
150    pub row: u32,
151    /// Type and type-specific for this tempo event
152    pub kind: TempoEventKind,
153}