rhythm_open_exchange/codec/formats/
yrox.rs1use crate::codec::{Decoder, Encoder, Format};
6use crate::error::{RoxError, RoxResult};
7use crate::model::RoxChart;
8
9pub struct YroxDecoder;
11
12pub struct YroxEncoder;
14
15impl Decoder for YroxDecoder {
16 fn decode(data: &[u8]) -> RoxResult<RoxChart> {
17 const MAX_FILE_SIZE: usize = 100 * 1024 * 1024;
19 if data.len() > MAX_FILE_SIZE {
20 return Err(RoxError::InvalidFormat(format!(
21 "File too large: {} bytes (max {}MB)",
22 data.len(),
23 MAX_FILE_SIZE / 1024 / 1024
24 )));
25 }
26
27 let chart: RoxChart = serde_yaml::from_slice(data)
28 .map_err(|e| RoxError::InvalidFormat(format!("YROX parse error: {e}")))?;
29
30 Ok(chart)
31 }
32}
33
34impl Encoder for YroxEncoder {
35 fn encode(chart: &RoxChart) -> RoxResult<Vec<u8>> {
36 let s = serde_yaml::to_string(chart).map_err(|e| RoxError::Serialize(e.to_string()))?;
37 Ok(s.into_bytes())
38 }
39}
40
41impl Format for YroxDecoder {
42 const EXTENSIONS: &'static [&'static str] = &["yrox"];
43}
44
45impl Format for YroxEncoder {
46 const EXTENSIONS: &'static [&'static str] = &["yrox"];
47}
48
49#[cfg(test)]
50mod tests {
51 use compact_str::ToCompactString;
52
53 use super::*;
54 use crate::codec::{Decoder, Encoder};
55 use crate::model::RoxChart;
56
57 #[test]
58 fn test_yrox_roundtrip() {
59 let mut chart = RoxChart::new(4);
60 chart.metadata.title = "Yrox Test".to_compact_string();
61
62 let encoded = YroxEncoder::encode(&chart).unwrap();
63 let decoded = YroxDecoder::decode(&encoded).unwrap();
64
65 assert_eq!(chart.key_count(), decoded.key_count());
66 assert_eq!(chart.metadata.title, decoded.metadata.title);
67 }
68
69 #[test]
70 fn test_file_too_large() {
71 let max_file_size: usize = 100 * 1024 * 1024;
73 let big_data = vec![0; max_file_size + 1];
74 let result = YroxDecoder::decode(&big_data);
75 assert!(
76 matches!(result, Err(RoxError::InvalidFormat(msg)) if msg.contains("File too large"))
77 );
78 }
79}