Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| // Memento - A Whisper implementation in Rust | |
| // | |
| // Copyright 2017-2018 TSH Labs | |
| // | |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
| // option. This file may not be copied, modified, or distributed | |
| // except according to those terms. | |
| //! Functions to encode Whisper files to a stream of bytes | |
| use std::io; | |
| use byteorder::{NetworkEndian, WriteBytesExt}; | |
| use errors::MementoResult; | |
| use types::{Archive, ArchiveInfo, Data, Header, MementoDatabase, Metadata, Point}; | |
| pub fn memento_encode_metadata<W>(writer: &mut W, meta: &Metadata) -> io::Result<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| writer.write_u32::<NetworkEndian>(meta.aggregation() as u32)?; | |
| writer.write_u32::<NetworkEndian>(meta.max_retention())?; | |
| writer.write_f32::<NetworkEndian>(meta.x_files_factor())?; | |
| writer.write_u32::<NetworkEndian>(meta.archive_count()) | |
| } | |
| pub fn memento_encode_archive_infos<W>(writer: &mut W, infos: &[ArchiveInfo]) -> io::Result<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| for info in infos { | |
| writer.write_u32::<NetworkEndian>(info.offset())?; | |
| writer.write_u32::<NetworkEndian>(info.seconds_per_point())?; | |
| writer.write_u32::<NetworkEndian>(info.num_points())?; | |
| } | |
| Ok(()) | |
| } | |
| pub fn memento_encode_point<W>(writer: &mut W, point: &Point) -> io::Result<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| writer.write_u32::<NetworkEndian>(point.timestamp())?; | |
| writer.write_f64::<NetworkEndian>(point.value()) | |
| } | |
| pub fn memento_encode_data<W>(writer: &mut W, data: &Data) -> io::Result<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| for archive in data.archives() { | |
| memento_encode_archive(writer, archive)?; | |
| } | |
| Ok(()) | |
| } | |
| pub fn memento_encode_archive<W>(writer: &mut W, archive: &Archive) -> io::Result<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| for point in archive.points() { | |
| memento_encode_point(writer, point)?; | |
| } | |
| Ok(()) | |
| } | |
| pub fn memento_encode_header<W>(writer: &mut W, header: &Header) -> MementoResult<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| memento_encode_metadata(writer, header.metadata())?; | |
| Ok(memento_encode_archive_infos(writer, header.archive_info())?) | |
| } | |
| pub fn memento_encode_database<W>(writer: &mut W, file: &MementoDatabase) -> MementoResult<()> | |
| where | |
| W: WriteBytesExt, | |
| { | |
| memento_encode_header(writer, file.header())?; | |
| Ok(memento_encode_data(writer, file.data())?) | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use types::{ | |
| AggregationType, Archive, ArchiveInfo, Data, Header, MementoDatabase, Metadata, Point, | |
| }; | |
| use super::{ | |
| memento_encode_archive, memento_encode_archive_infos, memento_encode_data, | |
| memento_encode_database, memento_encode_header, memento_encode_metadata, | |
| memento_encode_point, | |
| }; | |
| #[test] | |
| fn test_memento_encode_metadata() { | |
| let metadata = Metadata::new(AggregationType::Max, 31536000, 0.5, 5); | |
| // Python: struct.pack('>LLfL', 4, 31536000, 0.5, 5).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x00, 0x00, 0x00, 0x04, | |
| 0x01, 0xe1, 0x33, 0x80, | |
| 0x3f, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x05 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_metadata(&mut buf, &metadata).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_archive_infos() { | |
| let info = ArchiveInfo::new(76, 10, 8640); | |
| // Python: struct.pack('>LLL', 76, 10, 8640).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x00, 0x00, 0x00, 0x4c, | |
| 0x00, 0x00, 0x00, 0x0a, | |
| 0x00, 0x00, 0x21, 0xc0 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_archive_infos(&mut buf, &vec![info]).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_point() { | |
| let point = Point::new(1511396041, 42.0); | |
| // Python: struct.pack('>Ld', 1511396041, 42.0).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x5a, 0x16, 0x12, 0xc9, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_point(&mut buf, &point).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_data() { | |
| let point1 = Point::new(1511396041, 42.0); | |
| let point2 = Point::new(1511396051, 42.0); | |
| let archive = Archive::new(vec![point1, point2]); | |
| let data = Data::new(vec![archive]); | |
| // Python: | |
| // struct.pack('>Ld', 1511396041, 42.0).hex() | |
| // struct.pack('>Ld', 1511396051, 42.0).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x5a, 0x16, 0x12, 0xc9, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x5a, 0x16, 0x12, 0xd3, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_data(&mut buf, &data).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_archive() { | |
| let point1 = Point::new(1511396041, 42.0); | |
| let point2 = Point::new(1511396051, 42.0); | |
| let archive = Archive::new(vec![point1, point2]); | |
| // Python: | |
| // struct.pack('>Ld', 1511396041, 42.0).hex() | |
| // struct.pack('>Ld', 1511396051, 42.0).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x5a, 0x16, 0x12, 0xc9, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x5a, 0x16, 0x12, 0xd3, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_archive(&mut buf, &archive).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_header() { | |
| let metadata = Metadata::new(AggregationType::Min, 86400, 0.5, 1); | |
| let info = ArchiveInfo::new(28, 10, 8640); | |
| let header = Header::new(metadata, vec![info]); | |
| // Python: | |
| // struct.pack('>LLfL', 5, 86400, 0.5, 1).hex() | |
| // struct.pack('>LLL', 28, 10, 8640).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x00, 0x00, 0x00, 0x05, | |
| 0x00, 0x01, 0x51, 0x80, | |
| 0x3f, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x01, | |
| 0x00, 0x00, 0x00, 0x1c, | |
| 0x00, 0x00, 0x00, 0x0a, | |
| 0x00, 0x00, 0x21, 0xc0 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_header(&mut buf, &header).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| #[test] | |
| fn test_memento_encode_database() { | |
| let metadata = Metadata::new(AggregationType::Min, 86400, 0.5, 1); | |
| let info = ArchiveInfo::new(28, 10, 8640); | |
| let header = Header::new(metadata, vec![info]); | |
| let point1 = Point::new(1511396041, 42.0); | |
| let point2 = Point::new(1511396051, 42.0); | |
| let archive = Archive::new(vec![point1, point2]); | |
| let data = Data::new(vec![archive]); | |
| let file = MementoDatabase::new(header, data); | |
| // Python: | |
| // struct.pack('>LLfL', 5, 86400, 0.5, 1).hex() | |
| // struct.pack('>LLL', 28, 10, 8640).hex() | |
| // struct.pack('>Ld', 1511396041, 42.0).hex() | |
| // struct.pack('>Ld', 1511396051, 42.0).hex() | |
| #[cfg_attr(rustfmt, rustfmt_skip)] | |
| let expected = vec![ | |
| 0x00, 0x00, 0x00, 0x05, | |
| 0x00, 0x01, 0x51, 0x80, | |
| 0x3f, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x01, | |
| 0x00, 0x00, 0x00, 0x1c, | |
| 0x00, 0x00, 0x00, 0x0a, | |
| 0x00, 0x00, 0x21, 0xc0, | |
| 0x5a, 0x16, 0x12, 0xc9, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x5a, 0x16, 0x12, 0xd3, | |
| 0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| ]; | |
| let mut buf = vec![]; | |
| memento_encode_database(&mut buf, &file).unwrap(); | |
| assert_eq!(&expected, &buf); | |
| } | |
| } |