From 2775a26a3eca5a2ad1e1de631961507d17be5cda Mon Sep 17 00:00:00 2001 From: wcampbell Date: Wed, 3 Nov 2021 07:55:12 -0400 Subject: [PATCH 1/7] Use deku library This library makes encode and decode libraries easy to write, and removes the custom decode/encode code and replaces with deku derive-macros. `PrimaryHeader::from_bytes` is the new external API for decoding. and `to_bytes` for encoding. Signed-off-by: wcampbell --- Cargo.toml | 3 +- src/lib.rs | 4 -- src/primaryheader.rs | 76 ++++----------------- src/types.rs | 159 ++++++++----------------------------------- 4 files changed, 43 insertions(+), 199 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0826f4f..de43de6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,5 +17,4 @@ exclude = [ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -byteorder = "1.2.7" -failure = "0.1.3" +deku = "0.12" diff --git a/src/lib.rs b/src/lib.rs index b013dbb..ccb8377 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,3 @@ mod primaryheader; pub use primaryheader::PrimaryHeader; pub mod types; - -use failure::Error; - -pub type ParseResult = Result; diff --git a/src/primaryheader.rs b/src/primaryheader.rs index af81ab5..72dfa81 100644 --- a/src/primaryheader.rs +++ b/src/primaryheader.rs @@ -18,86 +18,40 @@ // use crate::packet::{LinkPacket, PayloadType}; // use crate::CommsResult; -use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use std::io::Cursor; -use crate::ParseResult; use crate::types; +use deku::prelude::*; -#[derive(Eq, Debug, PartialEq, Clone)] +#[derive(Eq, Debug, PartialEq, Clone, DekuRead, DekuWrite)] pub struct PrimaryHeader { /// Packet Version Number - 3 bits + #[deku(bits = "3")] pub version: u8, + /// Packet Type - 1 bit pub packet_type: types::PacketType, + /// Secondary Header Flag - 1 bit pub sec_header_flag: types::SecondaryHeaderFlag, + /// Application Process ID - 11 bits + #[deku(bits = "11", endian = "big")] pub app_proc_id: u16, + /// Sequence Flags - 2 bits pub sequence_flags: types::SeqFlag, + /// Packet Sequence Count or Packet Name - 14 bits + #[deku(bits = "14", endian = "big")] pub sequence_count: u16, + /// Packet Data Length - 2 bytes + #[deku(endian = "big")] pub data_length: u16, } - -impl PrimaryHeader { - - pub fn parse(raw: &[u8]) -> ParseResult<(PrimaryHeader, Vec)> { - let mut reader = Cursor::new(raw.to_vec()); - - let header_0 = reader.read_u16::()?; - let version = ((header_0 & 0xE000) >> 13) as u8; - let packet_type = types::PacketType::from(((header_0 & 0x1000) >> 12) as u8); - let sec_header_flag = types::SecondaryHeaderFlag::from(((header_0 & 0x800) >> 11) as u8); - let app_proc_id = (header_0 & 0x7FF) as u16; - - let header_1 = reader.read_u16::()?; - let sequence_flags = types::SeqFlag::from(((header_1 & 0xC000) >> 14) as u8); - let sequence_count = (header_1 & 0x3FFF) as u16; - - let data_length = reader.read_u16::()?; - - let pos = reader.position() as usize; - let remaining = raw[pos..].to_vec(); - - Ok((PrimaryHeader { - version, - packet_type, - sec_header_flag, - app_proc_id, - sequence_flags, - sequence_count, - data_length, - }, remaining)) - } - - pub fn to_bytes(&self) -> ParseResult> { - let mut bytes = vec![]; - //TODO: look into this two-stage casting from enum to u16 - let header_0: u16 = (self.app_proc_id) as u16 - | u16::from(self.sec_header_flag as u8) << 11 - | u16::from(self.packet_type as u8) << 12 - | u16::from(self.version) << 13; - - let header_1 = (self.sequence_count as u16) - | u16::from(self.sequence_flags) << 14; - - let header_2 = self.data_length; - - bytes.write_u16::(header_0)?; - bytes.write_u16::(header_1)?; - bytes.write_u16::(header_2)?; - - Ok(bytes) - } -} - #[cfg(test)] mod tests { - use crate::*; - use crate::primaryheader::PrimaryHeader; + use super::*; #[test] fn parse_python_spacepacket_primary_header() { @@ -112,9 +66,9 @@ mod tests { sequence_count: 0, data_length: 64, }; - let (parsed, remaining) = PrimaryHeader::parse(raw).expect("failed to parse header"); + let (rest, parsed) = PrimaryHeader::from_bytes((raw, 0)).expect("failed to parse header"); assert_eq!(parsed, expected); - assert_eq!(remaining, [255,255]) + assert_eq!(rest.0, [255, 255]) } } diff --git a/src/types.rs b/src/types.rs index 74da16f..b90e0d4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,19 +1,18 @@ // This file contains type definitions for various fields used within the PrimaryHeader and other parts of the space packet // It is derived from Apache 2.0-licensed work done by Noah Ryan in https://github.com/nsmryan/ccsds_primary_header/blob/master/src/primary_header.rs +use deku::prelude::*; -/// The PacketType indicates whether the packet is a command (Command) or a +/// The PacketType indicates whether the packet is a command (Command) or a /// telemetry (Data) packet. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, DekuRead, DekuWrite)] +#[deku(type = "u8", bits = "1")] pub enum PacketType { - /// The packet contains telemetry data. - Data, - /// The packet contains a command. - Command, - /// The packet type is unknown. This should not occur, but it is included - /// for encoding an integer into a packet type. - Unknown -} + /// The packet contains telemetry data. + Data = 0, + /// The packet contains a command. + Command = 1, +} impl Default for PacketType { fn default() -> PacketType { @@ -21,89 +20,17 @@ impl Default for PacketType { } } -impl From for PacketType { - fn from(byte: u8) -> PacketType { - match byte { - 0 => PacketType::Data, - 1 => PacketType::Command, - _ => PacketType::Unknown - } - } -} - -impl From for PacketType { - fn from(byte: u16) -> PacketType { - PacketType::from(byte as u8) - } -} - -impl From for u8 { - fn from(packet_type: PacketType) -> u8 { - match packet_type { - PacketType::Data => 0, - PacketType::Command => 1, - PacketType::Unknown => 0, - } - } -} - -impl From for u16 { - fn from(packet_type: PacketType) -> u16 { - u8::from(packet_type) as u16 - } -} - /// The secondary header flag indicates whether there is another header /// following the primary header (Present) or not (NotPresent). -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, DekuRead, DekuWrite)] +#[deku(type = "u8", bits = "1")] pub enum SecondaryHeaderFlag { - /// The secondary header is not present. The bytes following the primary header - /// is the packet's data section. - NotPresent, - /// A secondary header is present in the packet. The secondary header follows the - /// primary header. - Present, - /// The secondary header flag in not valid. This should not occur, but it is included - /// for turning an integer into a SecondaryHeaderFlag. - Unknown -} - -impl Default for SecondaryHeaderFlag { - fn default() -> SecondaryHeaderFlag { - SecondaryHeaderFlag::NotPresent - } -} - -impl From for SecondaryHeaderFlag { - fn from(byte: u8) -> SecondaryHeaderFlag { - match byte { - 0 => SecondaryHeaderFlag::NotPresent, - 1 => SecondaryHeaderFlag::Present, - _ => SecondaryHeaderFlag::Unknown - } - } -} - -impl From for SecondaryHeaderFlag { - fn from(byte: u16) -> SecondaryHeaderFlag { - SecondaryHeaderFlag::from(byte as u8) - } -} - -impl From for u8 { - fn from(flag: SecondaryHeaderFlag) -> u8 { - match flag { - SecondaryHeaderFlag::NotPresent => 0, - SecondaryHeaderFlag::Present => 1, - SecondaryHeaderFlag::Unknown => 0 - } - } -} - -impl From for u16 { - fn from(flag: SecondaryHeaderFlag) -> u16 { - u8::from(flag) as u16 - } + /// The secondary header is not present. The bytes following the primary header + /// is the packet's data section. + NotPresent = 0, + /// A secondary header is present in the packet. The secondary header follows the + /// primary header. + Present = 1, } /// The sequence flag indicates the interpretation of the sequence count. @@ -113,19 +40,17 @@ impl From for u16 { /// LastSegement- the packet is the last in a series of segemented packets. /// Unsegmented- the sequence count is an incrementing counter used to distinguish /// packets. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, DekuRead, DekuWrite)] +#[deku(type = "u8", bits = "2")] pub enum SeqFlag { - /// The packets is a continuation in a series of packets. - Continuation, - /// The packets is the first is a series of packets. - FirstSegment, - /// The packets is the last is a series of packets. - LastSegment, - /// The packets is a standalone packet. Most packets are unsegmented. - Unsegmented, - /// The sequence flag is unknown. This should not occur, but it is included - /// for encoding integers into this type. - Unknown + /// The packets is a continuation in a series of packets. + Continuation = 0, + /// The packets is the first is a series of packets. + FirstSegment = 1, + /// The packets is the last is a series of packets. + LastSegment = 2, + /// The packets is a standalone packet. Most packets are unsegmented. + Unsegmented = 3, } impl Default for SeqFlag { @@ -133,33 +58,3 @@ impl Default for SeqFlag { SeqFlag::Unsegmented } } - -impl From for SeqFlag { - fn from(byte: u8) -> SeqFlag { - match byte { - 0 => SeqFlag::Continuation, - 1 => SeqFlag::FirstSegment, - 2 => SeqFlag::LastSegment, - 3 => SeqFlag::Unsegmented, - _ => SeqFlag::Unknown - } - } -} - -impl From for SeqFlag { - fn from(byte: u16) -> SeqFlag { - SeqFlag::from(byte as u8) - } -} - -impl From for u16 { - fn from(byte: SeqFlag) -> u16 { - match byte { - SeqFlag::Continuation => 0, - SeqFlag::FirstSegment => 1, - SeqFlag::LastSegment => 2, - SeqFlag::Unsegmented => 3, - SeqFlag::Unknown => 0 - } - } -} \ No newline at end of file From 16ec74ec5f0e6f3e9fac5e4b540a5da03c277f80 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:11:39 -0400 Subject: [PATCH 2/7] update cargo.lock --- Cargo.lock | 185 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0959b8..214bd47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,116 +3,109 @@ version = 3 [[package]] -name = "addr2line" -version = "0.15.2" +name = "bitvec" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" +checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" dependencies = [ - "gimli", + "funty", + "radium", + "tap", + "wyz", ] [[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" +name = "ccsds_spacepacket" +version = "0.1.0" dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "deku", ] [[package]] -name = "byteorder" -version = "1.4.3" +name = "darling" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12" +dependencies = [ + "darling_core", + "darling_macro", +] [[package]] -name = "cc" -version = "1.0.70" +name = "darling_core" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" - -[[package]] -name = "ccsds_spacepacket" -version = "0.1.0" +checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" dependencies = [ - "byteorder", - "failure", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "darling_macro" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" +dependencies = [ + "darling_core", + "quote", + "syn", +] [[package]] -name = "failure" -version = "0.1.8" +name = "deku" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +checksum = "54c431132565a4ba57d02759711a71d0d943e5937202c3b3aa46a58b3704f241" dependencies = [ - "backtrace", - "failure_derive", + "bitvec", + "deku_derive", ] [[package]] -name = "failure_derive" -version = "0.1.8" +name = "deku_derive" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +checksum = "48c9dcf8067fe6e8dcef6b1c785db36d271efe30ec4299c765e482d2a6043797" dependencies = [ + "darling", + "proc-macro-crate", "proc-macro2", "quote", "syn", - "synstructure", ] [[package]] -name = "gimli" -version = "0.24.0" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "libc" -version = "0.2.101" +name = "funty" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" [[package]] -name = "miniz_oxide" -version = "0.4.4" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "object" -version = "0.24.0" +name = "proc-macro-crate" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +dependencies = [ + "thiserror", + "toml", +] [[package]] name = "proc-macro2" @@ -133,10 +126,22 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.21" +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" + +[[package]] +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -150,15 +155,38 @@ dependencies = [ ] [[package]] -name = "synstructure" -version = "0.12.5" +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", "syn", - "unicode-xid", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", ] [[package]] @@ -166,3 +194,12 @@ name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "wyz" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +dependencies = [ + "tap", +] From c4612b6a0508611f32667219937b3a228bc494e8 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:13:06 -0400 Subject: [PATCH 3/7] add TODO regarding the automatic counting of vector lengths --- src/primaryheader.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/primaryheader.rs b/src/primaryheader.rs index 72dfa81..764b84a 100644 --- a/src/primaryheader.rs +++ b/src/primaryheader.rs @@ -47,6 +47,8 @@ pub struct PrimaryHeader { /// Packet Data Length - 2 bytes #[deku(endian = "big")] pub data_length: u16, + // TODO: maybe figure out if https://docs.rs/deku/0.12.4/deku/#vec is appropriate here + } #[cfg(test)] From 013105312cfeaa3498d28ae47d60b32e02799a31 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:13:23 -0400 Subject: [PATCH 4/7] add test case for incompleteness --- src/primaryheader.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/primaryheader.rs b/src/primaryheader.rs index 764b84a..bd6f4b6 100644 --- a/src/primaryheader.rs +++ b/src/primaryheader.rs @@ -68,9 +68,35 @@ mod tests { sequence_count: 0, data_length: 64, }; + + let (rest, parsed) = PrimaryHeader::from_bytes((raw, 0)).expect("failed to parse header"); + + assert_eq!(parsed, expected); + assert_eq!(rest.0, [255,255]) + } + + #[test] + fn parse_incomplete_primary_header() { + //this is the equivalent of an all-zero primary header except for a data length of 64 followed by two bytes set to all 1 as a "payload" + let raw_short = b"\x00\x00\xc0\x00\x00"; + let expected = PrimaryHeader { + version: 0, + packet_type: types::PacketType::Data, + sec_header_flag: types::SecondaryHeaderFlag::NotPresent, + app_proc_id: 0, + sequence_flags: types::SeqFlag::Unsegmented, + sequence_count: 0, + data_length: 64, + }; + let inc = PrimaryHeader::from_bytes((raw_short, 0)); + + assert_eq!(inc.is_err(), true); + + let raw = b"\x00\x00\xc0\x00\x00\x40"; + + let (rest, parsed) = PrimaryHeader::from_bytes((raw, 0)).expect("failed to parse header"); assert_eq!(parsed, expected); - assert_eq!(rest.0, [255, 255]) } } From b65be0998ea1f3ac68ed0671935543f9944ad65d Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:16:14 -0400 Subject: [PATCH 5/7] bump version number --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index de43de6..8b4b3ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ccsds_spacepacket" -version = "0.1.0" +version = "0.2.0" authors = ["Adrian Edwards <17362949+MoralCode@users.noreply.github.com>"] edition = "2018" license = "Apache-2.0" From b9b5d32dbd9d594da882bb39ae6ff08fdaeceaa0 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:20:44 -0400 Subject: [PATCH 6/7] add note about current status --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bb817a..e6e4441 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,8 @@ The Secondary Header and Payload make up the "User Data Field" and at least one ## What this library does This library attempts to implement a general-purpose parser for Space Packets that can interperet both the generic aspects of the space packet protocol (i.e. the Primary Header) in addition to any custom fields supplied within the Secondary Headers. -This Secondary Header parsing is accomplished by allowing users of the library to pass in a parser that can interperet the Secondary Header as specified by their project or organisation. \ No newline at end of file +This Secondary Header parsing is accomplished by allowing users of the library to pass in a parser that can interperet the Secondary Header as specified by their project or organisation. + + +## Current status +Currently this library just implements Primary Header parsing, but expanding it to be able to deal with a complete, generic spacepacket (think of generics in programming) with user defined custom secondary headers is one of the projects main goals. From 90ceffc41352cf98eb118c86ad08a4a538bff7c8 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:21:05 -0400 Subject: [PATCH 7/7] turn one of the unit tests into an example in the README --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index e6e4441..55930d2 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,27 @@ This Secondary Header parsing is accomplished by allowing users of the library t ## Current status Currently this library just implements Primary Header parsing, but expanding it to be able to deal with a complete, generic spacepacket (think of generics in programming) with user defined custom secondary headers is one of the projects main goals. + + +## Usage + +```rust + // say you have some bytes you want to turn into a PrimaryHeader + let raw = b"\x00\x00\xc0\x00\x00\x40\xff\xff"; + + let expected = PrimaryHeader { + version: 0, + packet_type: types::PacketType::Data, + sec_header_flag: types::SecondaryHeaderFlag::NotPresent, + app_proc_id: 0, + sequence_flags: types::SeqFlag::Unsegmented, + sequence_count: 0, + data_length: 64, + }; + + // do the parsing and save the parsed header and any remaining bytes + let (rest, parsed) = PrimaryHeader::from_bytes((raw, 0)).expect("failed to parse header"); + + assert_eq!(parsed, expected); + assert_eq!(rest.0, [255,255]) +``` \ No newline at end of file