chainlink_data_streams_report/report/
compress.rs

1use super::Report;
2
3use snap::raw::Encoder;
4
5#[derive(Debug)]
6pub enum CompressionError {
7    SerializationError(serde_json::Error),
8    CompressionError(snap::Error),
9}
10
11impl From<snap::Error> for CompressionError {
12    fn from(err: snap::Error) -> Self {
13        CompressionError::CompressionError(err)
14    }
15}
16
17/// Compresses a raw report payload using the [Snappy compression algorithm](https://google.github.io/snappy/).
18///
19/// # Arguments
20///
21/// * `payload` - The raw report payload to compress.
22///
23/// # Returns
24///
25/// A `Result` containing the compressed payload as a `Vec<u8>` if successful, or a `CompressionError` error if compression fails.
26///
27/// # Examples
28/// ```rust
29/// use chainlink_data_streams_report::report::compress::{compress_report_raw, CompressionError};
30///
31/// fn main() -> Result<(), CompressionError> {
32///    let raw_report = "7b22666565644944223a22307830303033366234616137653537636137623638616531626634353635336635366236353666643361613333356566376661653639366236363366316238343732222c2276616c696446726f6d54696d657374616d70223a313731383838353737322c226f62736572766174696f6e7354696d657374616d70223a313731383838353737322c2266756c6c5265706f7274223a2230303036626438373833306435663333366532303563663563363333323961316461623866356435363831326561656237633639333030653636616238653232303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030636637656431333030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030306530303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303232303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303033303030313031303030313031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303132303030303330616237643032666262613963363330346639383832343532343430376231663439343734313137343332306366643137613263323265656331646530303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303636613866356336303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036366138663563363030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303035373831303635336464393030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303534313331356461373664363130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036366161343734363030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303039613639376565343233303335303430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030396136353036643134323664303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303961373764303361653335356665303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303637326261633939316635323333646638396635383164633032613839646438643438343139653335353862323437643365363566343036396661343563333636353861356134383230646339346663343761383861323164383334373463323965653338333832633436623666396135373562396365386265346536383963303363373666616331396662656334613239646261373034633732636330303361366265316639366166313135653332323332316630363838653234373230613564396264373133366131643936383432656338393133333035386238383862326536353732623564343131346465323432363139356530333866316339613563653530303136623666356135646530376530383532396238343565316336323264636265666130636661326666643132386539393332656365653865666438363962633536643039613530636562333630613864333636636661386565666533663634323739633838626462633838373536306566613939343432333865623030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036306532613830306631363966323631363435333363376661666636633930373363643664623234306438393434346433343837313133323332663963333134323261303939336262343764353638303764306463323637323865346338343234626239646237373531313030313930343335336631303232313638373233303130633436363237633839306265366537303165373636363739363030363936383636633838386563383065376462643432386635313632613234663264383236326638343662646230366439653436643239356464386538393666623233326265383035333462303034313636306665343435306137656465396263336232333037323233383137373361346165383132343135363838363761373539663533633262646430356433326232303965373838343566633538323033393439653530613630383934326232373063343536303031653537383232376164303038363163663566343762323762303931333761306334623766386234373436636566227d";
33///    let report = hex::decode(raw_report).unwrap();
34///
35///    let compressed_report = compress_report_raw(&report).unwrap();
36///
37///     Ok(())
38/// }
39/// ```
40pub fn compress_report_raw(payload: &[u8]) -> Result<Vec<u8>, CompressionError> {
41    let mut encoder = Encoder::new();
42    let compressed = encoder.compress_vec(payload)?;
43    Ok(compressed)
44}
45
46/// Compresses a report using the [Snappy compression algorithm](https://google.github.io/snappy/).
47///
48/// # Arguments
49///
50/// * `report` - The report to compress.
51///
52/// # Returns
53///
54/// A `Result` containing the compressed payload as a `Vec<u8>` if successful, or a `CompressionError` error if serialization or compression fails.
55///
56/// # Examples
57/// ```rust
58/// use chainlink_data_streams_report::report::{Report, compress::{compress_report, CompressionError}};
59/// use chainlink_data_streams_report::feed_id::ID;
60///
61/// fn main() -> Result<(), CompressionError> {
62///    let feed_id = ID::from_hex_str("0x00036b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472").unwrap();
63///    let full_report = "0006bd87830d5f336e205cf5c63329a1dab8f5d56812eaeb7c69300e66ab8e22000000000000000000000000000000000000000000000000000000000cf7ed13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000101000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000030ab7d02fbba9c6304f98824524407b1f494741174320cfd17a2c22eec1de0000000000000000000000000000000000000000000000000000000066a8f5c60000000000000000000000000000000000000000000000000000000066a8f5c6000000000000000000000000000000000000000000000000000057810653dd9000000000000000000000000000000000000000000000000000541315da76d6100000000000000000000000000000000000000000000000000000000066aa474600000000000000000000000000000000000000000000000009a697ee4230350400000000000000000000000000000000000000000000000009a6506d1426d00000000000000000000000000000000000000000000000000009a77d03ae355fe0000000000000000000000000000000000000000000000000000000000000000672bac991f5233df89f581dc02a89dd8d48419e3558b247d3e65f4069fa45c36658a5a4820dc94fc47a88a21d83474c29ee38382c46b6f9a575b9ce8be4e689c03c76fac19fbec4a29dba704c72cc003a6be1f96af115e322321f0688e24720a5d9bd7136a1d96842ec89133058b888b2e6572b5d4114de2426195e038f1c9a5ce50016b6f5a5de07e08529b845e1c622dcbefa0cfa2ffd128e9932ecee8efd869bc56d09a50ceb360a8d366cfa8eefe3f64279c88bdbc887560efa9944238eb000000000000000000000000000000000000000000000000000000000000000060e2a800f169f26164533c7faff6c9073cd6db240d89444d3487113232f9c31422a0993bb47d56807d0dc26728e4c8424bb9db77511001904353f1022168723010c46627c890be6e701e766679600696866c888ec80e7dbd428f5162a24f2d8262f846bdb06d9e46d295dd8e896fb232be80534b0041660fe4450a7ede9bc3b230722381773a4ae81241568867a759f53c2bdd05d32b209e78845fc58203949e50a608942b270c456001e578227ad00861cf5f47b27b09137a0c4b7f8b4746cef";
64///
65///    let report = Report {
66///         feed_id,
67///         valid_from_timestamp: 1718885772,
68///         observations_timestamp: 1718885772,
69///         full_report: full_report.to_string(),
70///    };
71///
72///    let compressed_report = compress_report(report).unwrap();
73///
74///     Ok(())
75/// }
76/// ```
77pub fn compress_report(report: Report) -> Result<Vec<u8>, CompressionError> {
78    let payload = serde_json::to_vec(&report).map_err(CompressionError::SerializationError)?;
79
80    compress_report_raw(&payload)
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use crate::feed_id::ID;
87
88    const COMPRESSED_MOCK_REPORT: &str = "e210f0817b22666565644944223a22307830303033366234616137653537636137623638616531626634353635336635366236353666643361613333356566376661653639366236363366316238343732222c2276616c696446726f6d54696d657374616d70223a313731383838353737322c226f62736572766174696f6e7354696d6573744223002466756c6c5265706f72740195f0403030366264383738333064356633333665323035636635633633333239613164616238663564353638313265616562376336393330306536366162386532323030da02001863663765643133da3e00fe01000d010065f64800eaff00050101fe1031303130300d06fe0100be01000431320172f03c333061623764303266626261396336333034663938383234353234343037623166343934373431313734333230636664313761326332326565633164650141ce01000c363661384166ce3c000101ee4000283537383130363533646439014bba01002c35343133313564613736643621bbd601001836366161343734c6000138396136393765653432333033353034c27e002c396136353036643134323664c23d003c30303039613737643033616533353566fa4003f48101303036373262616339393166353233336466383966353831646330326138396464386434383431396533353538623234376433653635663430363966613435633336363538613561343832306463393466633437613838613231643833343734633239656533383338326334366236663961353735623963653862653465363839633033633736666163313966626563346132396462613730346337326363303033613662653166393661663131356533323233323166303638386532343732306135643962643731333661316439363834326563383931333330353862383838623265363537326235643431313464653234323631393565303338663163396135636535303031366236663561356465303765303835323962383435653163363232646362656661306366613266666431323865393933326563656538656664383639626335366430396135306365623336306138643336366366613865656665336636343237396338386264626338383735363065666139393434323338656221d2ee0100f4820136306532613830306631363966323631363435333363376661666636633930373363643664623234306438393434346433343837313133323332663963333134323261303939336262343764353638303764306463323637323865346338343234626239646237373531313030313930343335336631303232313638373233303130633436363237633839306265366537303165373636363739363030363936383636633838386563383065376462643432386635313632613234663264383236326638343662646230366439653436643239356464386538393666623233326265383035333462303034313636306665343435306137656465396263336232333037323233383137373361346165383132343135363838363761373539663533633262646430356433326232303965373838343566633538323033393439653530613630383934326232373063343536303031653537383232376164303038363163663566343762323762303931333761306334623766386234373436636566227d";
89
90    #[test]
91    fn compress_report_raw_test() {
92        let mock_report_raw = "7b22666565644944223a22307830303033366234616137653537636137623638616531626634353635336635366236353666643361613333356566376661653639366236363366316238343732222c2276616c696446726f6d54696d657374616d70223a313731383838353737322c226f62736572766174696f6e7354696d657374616d70223a313731383838353737322c2266756c6c5265706f7274223a2230303036626438373833306435663333366532303563663563363333323961316461623866356435363831326561656237633639333030653636616238653232303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030636637656431333030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030306530303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303232303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303033303030313031303030313031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303132303030303330616237643032666262613963363330346639383832343532343430376231663439343734313137343332306366643137613263323265656331646530303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303636613866356336303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036366138663563363030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303035373831303635336464393030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303534313331356461373664363130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036366161343734363030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303039613639376565343233303335303430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030396136353036643134323664303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303961373764303361653335356665303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303637326261633939316635323333646638396635383164633032613839646438643438343139653335353862323437643365363566343036396661343563333636353861356134383230646339346663343761383861323164383334373463323965653338333832633436623666396135373562396365386265346536383963303363373666616331396662656334613239646261373034633732636330303361366265316639366166313135653332323332316630363838653234373230613564396264373133366131643936383432656338393133333035386238383862326536353732623564343131346465323432363139356530333866316339613563653530303136623666356135646530376530383532396238343565316336323264636265666130636661326666643132386539393332656365653865666438363962633536643039613530636562333630613864333636636661386565666533663634323739633838626462633838373536306566613939343432333865623030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036306532613830306631363966323631363435333363376661666636633930373363643664623234306438393434346433343837313133323332663963333134323261303939336262343764353638303764306463323637323865346338343234626239646237373531313030313930343335336631303232313638373233303130633436363237633839306265366537303165373636363739363030363936383636633838386563383065376462643432386635313632613234663264383236326638343662646230366439653436643239356464386538393666623233326265383035333462303034313636306665343435306137656465396263336232333037323233383137373361346165383132343135363838363761373539663533633262646430356433326232303965373838343566633538323033393439653530613630383934326232373063343536303031653537383232376164303038363163663566343762323762303931333761306334623766386234373436636566227d";
93        let payload = hex::decode(mock_report_raw).unwrap();
94
95        let got = compress_report_raw(&payload).unwrap();
96
97        let want = COMPRESSED_MOCK_REPORT;
98
99        assert_eq!(hex::encode(&got), want);
100    }
101
102    #[test]
103    fn compress_report_test() {
104        let mock_feed_id =
105            ID::from_hex_str("0x00036b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472")
106                .unwrap();
107        let mock_timestamp = 1718885772;
108        let mock_report_data = "0006bd87830d5f336e205cf5c63329a1dab8f5d56812eaeb7c69300e66ab8e22000000000000000000000000000000000000000000000000000000000cf7ed13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000101000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000030ab7d02fbba9c6304f98824524407b1f494741174320cfd17a2c22eec1de0000000000000000000000000000000000000000000000000000000066a8f5c60000000000000000000000000000000000000000000000000000000066a8f5c6000000000000000000000000000000000000000000000000000057810653dd9000000000000000000000000000000000000000000000000000541315da76d6100000000000000000000000000000000000000000000000000000000066aa474600000000000000000000000000000000000000000000000009a697ee4230350400000000000000000000000000000000000000000000000009a6506d1426d00000000000000000000000000000000000000000000000000009a77d03ae355fe0000000000000000000000000000000000000000000000000000000000000000672bac991f5233df89f581dc02a89dd8d48419e3558b247d3e65f4069fa45c36658a5a4820dc94fc47a88a21d83474c29ee38382c46b6f9a575b9ce8be4e689c03c76fac19fbec4a29dba704c72cc003a6be1f96af115e322321f0688e24720a5d9bd7136a1d96842ec89133058b888b2e6572b5d4114de2426195e038f1c9a5ce50016b6f5a5de07e08529b845e1c622dcbefa0cfa2ffd128e9932ecee8efd869bc56d09a50ceb360a8d366cfa8eefe3f64279c88bdbc887560efa9944238eb000000000000000000000000000000000000000000000000000000000000000060e2a800f169f26164533c7faff6c9073cd6db240d89444d3487113232f9c31422a0993bb47d56807d0dc26728e4c8424bb9db77511001904353f1022168723010c46627c890be6e701e766679600696866c888ec80e7dbd428f5162a24f2d8262f846bdb06d9e46d295dd8e896fb232be80534b0041660fe4450a7ede9bc3b230722381773a4ae81241568867a759f53c2bdd05d32b209e78845fc58203949e50a608942b270c456001e578227ad00861cf5f47b27b09137a0c4b7f8b4746cef";
109
110        let mock_report = Report {
111            feed_id: mock_feed_id,
112            valid_from_timestamp: mock_timestamp,
113            observations_timestamp: mock_timestamp,
114            full_report: mock_report_data.to_string(),
115        };
116
117        let got = compress_report(mock_report).unwrap();
118
119        let want = COMPRESSED_MOCK_REPORT;
120
121        assert_eq!(hex::encode(&got), want);
122    }
123}