diff --git a/Cargo.lock b/Cargo.lock index 0e51f1f..9314533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,9 +81,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bus" @@ -102,6 +102,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" @@ -126,6 +132,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -183,12 +199,55 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if", +] + +[[package]] +name = "cxx" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +dependencies = [ + "cc", + "codespan-reporting", "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -238,6 +297,7 @@ dependencies = [ "delegate 0.8.0", "downcast-rs", "hashbrown", + "heapless", "num-traits", "once_cell", "postcard", @@ -254,13 +314,14 @@ dependencies = [ "delegate 0.8.0", "fsrc-core", "spacepackets", + "zerocopy", ] [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -310,23 +371,33 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" dependencies = [ "android_system_properties", "core-foundation-sys", + "iana-time-zone-haiku", "js-sys", - "once_cell", "wasm-bindgen", "winapi", ] [[package]] -name = "js-sys" -version = "0.3.59" +name = "iana-time-zone-haiku" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -339,15 +410,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" + +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -414,15 +494,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if", "libc", @@ -444,9 +524,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -522,7 +602,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.13", + "semver 1.0.14", ] [[package]] @@ -531,6 +611,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "semver" version = "0.9.0" @@ -542,9 +628,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -554,18 +640,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -574,13 +660,13 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "spacepackets" -version = "0.1.0" +version = "0.2.0" dependencies = [ "chrono", "crc", @@ -608,9 +694,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -618,28 +704,25 @@ dependencies = [ ] [[package]] -name = "synstructure" -version = "0.12.6" +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", + "winapi-util", ] [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] -name = "unicode-xid" -version = "0.2.3" +name = "unicode-width" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "vcell" @@ -676,9 +759,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -686,9 +769,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -701,9 +784,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -711,9 +794,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -724,9 +807,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "winapi" @@ -744,6 +827,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -752,46 +844,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +name = "windows_aarch64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "zerocopy" @@ -805,11 +911,11 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0fbc82b82efe24da867ee52e015e58178684bd9dd64c34e66bdf21da2582a9f" +checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3" dependencies = [ "proc-macro2", + "quote", "syn", - "synstructure", ] diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index 8188273..69df909 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -6,19 +6,20 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -delegate = "0.8.0" -hashbrown = "0.12.3" +delegate = "0.8" +hashbrown = "0.12" +heapless = "0.7" [dependencies.num-traits] version = "0.2" default-features = false [dependencies.downcast-rs] -version = "1.2.0" +version = "1.2" default-features = false [dependencies.bus] -version = "2.2.3" +version = "2.2" optional = true [dependencies.crossbeam-channel] @@ -29,15 +30,15 @@ default-features = false path = "../spacepackets" [dev-dependencies] -serde = "1.0.143" -zerocopy = "0.6.1" -once_cell = "1.13.1" +serde = "1.0" +zerocopy = "0.6" +once_cell = "1.13" [dev-dependencies.postcard] -version = "1.0.1" +version = "1.0" [features] default = ["std"] std = ["downcast-rs/std", "alloc", "bus", "postcard/use-std", "crossbeam-channel/std"] alloc = [] - +heapless = [] diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index be351b9..02bf7f6 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -1,10 +1,13 @@ //! Event support module +use spacepackets::ecss::EcssEnumeration; +use spacepackets::{ByteConversionError, SizeMissmatch}; + pub type GroupId = u16; pub type UniqueId = u16; pub type EventRaw = u32; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum Severity { INFO = 1, LOW = 2, @@ -26,7 +29,7 @@ impl TryFrom for Severity { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct Event { severity: Severity, group_id: GroupId, @@ -91,6 +94,23 @@ impl TryFrom for Event { } } +impl EcssEnumeration for Event { + fn pfc(&self) -> u8 { + 32 + } + + fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { + if buf.len() < self.byte_width() { + return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: buf.len(), + expected: self.byte_width(), + })); + } + buf.copy_from_slice(self.raw().to_be_bytes().as_slice()); + Ok(()) + } +} + #[cfg(test)] mod tests { use super::Event; diff --git a/fsrc-core/src/hal/host/udp_server.rs b/fsrc-core/src/hal/host/udp_server.rs index 2c7cd37..dd7ca67 100644 --- a/fsrc-core/src/hal/host/udp_server.rs +++ b/fsrc-core/src/hal/host/udp_server.rs @@ -41,7 +41,7 @@ use std::vec::Vec; /// let mut sph = SpHeader::tc(0x02, 0, 0).unwrap(); /// let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); /// let len = pus_tc -/// .write_to(&mut buf) +/// .write_to_bytes(&mut buf) /// .expect("Error writing PUS TC packet"); /// assert_eq!(len, 13); /// let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed"); @@ -166,7 +166,7 @@ mod tests { let mut sph = SpHeader::tc(0x02, 0, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let len = pus_tc - .write_to(&mut buf) + .write_to_bytes(&mut buf) .expect("Error writing PUS TC packet"); let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed"); client diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs new file mode 100644 index 0000000..bea74a4 --- /dev/null +++ b/fsrc-core/src/pus/event.rs @@ -0,0 +1,446 @@ +use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmSender}; +use spacepackets::ecss::EcssEnumeration; +use spacepackets::tm::PusTm; +use spacepackets::tm::PusTmSecondaryHeader; +use spacepackets::{SpHeader, MAX_APID}; + +#[cfg(feature = "alloc")] +pub use allocvec::EventReporter; + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub enum Subservices { + TmInfoReport = 1, + TmLowSeverityReport = 2, + TmMediumSeverityReport = 3, + TmHighSeverityReport = 4, + TcEnableEventGeneration = 5, + TcDisableEventGeneration = 6, + TcReportDisabledList = 7, + TmDisabledEventsReport = 8, +} + +impl From for u8 { + fn from(enumeration: Subservices) -> Self { + enumeration as u8 + } +} + +pub struct EventReporterBase { + msg_count: u16, + apid: u16, + pub dest_id: u16, +} + +impl EventReporterBase { + pub fn new(apid: u16) -> Option { + if apid > MAX_APID { + return None; + } + Some(Self { + msg_count: 0, + dest_id: 0, + apid, + }) + } + + pub fn event_info( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmInfoReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_low_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmLowSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_medium_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmMediumSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_high_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmHighSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + fn generate_and_send_generic_tm( + &mut self, + buf: &mut [u8], + subservice: Subservices, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?; + sender.send_tm(tm)?; + self.msg_count += 1; + Ok(()) + } + + fn generate_generic_event_tm<'a, E>( + &'a self, + buf: &'a mut [u8], + subservice: Subservices, + time_stamp: &'a [u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result> { + let mut src_data_len = event_id.byte_width(); + if let Some(aux_data) = aux_data { + src_data_len += aux_data.len(); + } + source_buffer_large_enough(buf.len(), src_data_len)?; + let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let sec_header = PusTmSecondaryHeader::new( + 5, + subservice.into(), + self.msg_count, + self.dest_id, + time_stamp, + ); + let mut current_idx = 0; + event_id.write_to_bytes(&mut buf[0..event_id.byte_width()])?; + current_idx += event_id.byte_width(); + if let Some(aux_data) = aux_data { + buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); + current_idx += aux_data.len(); + } + Ok(PusTm::new( + &mut sp_header, + sec_header, + Some(&buf[0..current_idx]), + true, + )) + } +} + +#[cfg(feature = "alloc")] +mod allocvec { + use super::*; + use alloc::vec; + use alloc::vec::Vec; + + pub struct EventReporter { + source_data_buf: Vec, + pub reporter: EventReporterBase, + } + + impl EventReporter { + pub fn new(apid: u16, max_event_id_and_aux_data_size: usize) -> Option { + let reporter = EventReporterBase::new(apid)?; + Some(Self { + source_data_buf: vec![0; max_event_id_and_aux_data_size], + reporter, + }) + } + pub fn event_info( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_info( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_low_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_low_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_medium_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_medium_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_high_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_high_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::events::{Event, Severity}; + use crate::pus::tests::CommonTmInfo; + use spacepackets::ByteConversionError; + use std::collections::VecDeque; + use std::vec::Vec; + + const EXAMPLE_APID: u16 = 0xee; + const EXAMPLE_GROUP_ID: u16 = 2; + const EXAMPLE_EVENT_ID_0: u16 = 1; + #[allow(dead_code)] + const EXAMPLE_EVENT_ID_1: u16 = 2; + + #[derive(Debug, Eq, PartialEq)] + struct TmInfo { + pub common: CommonTmInfo, + pub event: Event, + pub aux_data: Vec, + } + + #[derive(Default)] + struct TestSender { + pub service_queue: VecDeque, + } + + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { + assert!(tm.source_data().is_some()); + let src_data = tm.source_data().unwrap(); + assert!(src_data.len() >= 4); + let event = Event::try_from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); + assert!(event.is_ok()); + let event = event.unwrap(); + let mut aux_data = Vec::new(); + if src_data.len() > 4 { + aux_data.extend_from_slice(&src_data[4..]); + } + self.service_queue.push_back(TmInfo { + common: CommonTmInfo::new_from_tm(&tm), + event, + aux_data, + }); + Ok(()) + } + } + + fn severity_to_subservice(severity: Severity) -> Subservices { + match severity { + Severity::INFO => Subservices::TmInfoReport, + Severity::LOW => Subservices::TmLowSeverityReport, + Severity::MEDIUM => Subservices::TmMediumSeverityReport, + Severity::HIGH => Subservices::TmHighSeverityReport, + } + } + + fn report_basic_event( + reporter: &mut EventReporter, + sender: &mut TestSender, + time_stamp: &[u8], + event: Event, + severity: Severity, + aux_data: Option<&[u8]>, + ) { + match severity { + Severity::INFO => { + reporter + .event_info(sender, time_stamp, event, aux_data) + .expect("Error reporting info event"); + } + Severity::LOW => { + reporter + .event_low_severity(sender, time_stamp, event, aux_data) + .expect("Error reporting low event"); + } + Severity::MEDIUM => { + reporter + .event_medium_severity(sender, time_stamp, event, aux_data) + .expect("Error reporting medium event"); + } + Severity::HIGH => { + reporter + .event_high_severity(sender, time_stamp, event, aux_data) + .expect("Error reporting high event"); + } + } + } + + fn basic_event_test( + max_event_aux_data_buf: usize, + severity: Severity, + error_data: Option<&[u8]>, + ) { + let mut sender = TestSender::default(); + let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf); + assert!(reporter.is_some()); + let mut reporter = reporter.unwrap(); + let time_stamp_empty: [u8; 7] = [0; 7]; + let mut error_copy = Vec::new(); + if let Some(err_data) = error_data { + error_copy.extend_from_slice(err_data); + } + let event = Event::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) + .expect("Error creating example event"); + report_basic_event( + &mut reporter, + &mut sender, + &time_stamp_empty, + event, + severity, + error_data, + ); + assert_eq!(sender.service_queue.len(), 1); + let tm_info = sender.service_queue.pop_front().unwrap(); + assert_eq!( + tm_info.common.subservice, + severity_to_subservice(severity) as u8 + ); + assert_eq!(tm_info.common.dest_id, 0); + assert_eq!(tm_info.common.time_stamp, time_stamp_empty); + assert_eq!(tm_info.common.msg_counter, 0); + assert_eq!(tm_info.common.apid, EXAMPLE_APID); + assert_eq!(tm_info.event, event); + assert_eq!(tm_info.aux_data, error_copy); + } + + #[test] + fn basic_info_event_generation() { + basic_event_test(4, Severity::INFO, None); + } + + #[test] + fn basic_low_severity_event() { + basic_event_test(4, Severity::LOW, None); + } + + #[test] + fn basic_medium_severity_event() { + basic_event_test(4, Severity::MEDIUM, None); + } + + #[test] + fn basic_high_severity_event() { + basic_event_test(4, Severity::HIGH, None); + } + + #[test] + fn event_with_info_string() { + let info_string = "Test Information"; + basic_event_test(32, Severity::INFO, Some(info_string.as_bytes())); + } + + #[test] + fn low_severity_with_raw_err_data() { + let raw_err_param: i32 = -1; + let raw_err = raw_err_param.to_be_bytes(); + basic_event_test(8, Severity::LOW, Some(&raw_err)) + } + + fn check_buf_too_small( + reporter: &mut EventReporter, + sender: &mut TestSender, + expected_found_len: usize, + ) { + let time_stamp_empty: [u8; 7] = [0; 7]; + let event = Event::new(Severity::INFO, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) + .expect("Error creating example event"); + let err = reporter.event_info(sender, &time_stamp_empty, event, None); + assert!(err.is_err()); + let err = err.unwrap_err(); + if let EcssTmError::ByteConversionError(ByteConversionError::ToSliceTooSmall(missmatch)) = + err + { + assert_eq!(missmatch.expected, 4); + assert_eq!(missmatch.found, expected_found_len); + } else { + panic!("Unexpected error {:?}", err); + } + } + + #[test] + fn insufficient_buffer() { + let mut sender = TestSender::default(); + for i in 0..3 { + let reporter = EventReporter::new(EXAMPLE_APID, i); + assert!(reporter.is_some()); + let mut reporter = reporter.unwrap(); + check_buf_too_small(&mut reporter, &mut sender, i); + } + } +} diff --git a/fsrc-core/src/pus/event_man.rs b/fsrc-core/src/pus/event_man.rs new file mode 100644 index 0000000..0a006e1 --- /dev/null +++ b/fsrc-core/src/pus/event_man.rs @@ -0,0 +1,79 @@ +use crate::events::Event; +use hashbrown::HashSet; + +#[cfg(feature = "heapless")] +pub use heapless_mod::*; + +/// This trait allows the PUS event manager implementation to stay generic over various types +/// of backend containers. These backend containers keep track on whether a particular event +/// is enabled or disabled for reporting and also expose a simple API to enable or disable the event +/// reporting. +/// +/// For example, a straight forward implementation for host systems could use a +/// [hash set](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) +/// structure to track disabled events. A more primitive and embedded friendly +/// solution could track this information in a static or pre-allocated list which contains +/// the disabled events. +pub trait PusEventMgmtBackendProvider { + type Error; + + fn event_enabled(&self, event: &Event) -> bool; + fn enable_event_reporting(&mut self, event: &Event) -> Result; + fn disable_event_reporting(&mut self, event: &Event) -> Result; +} + +/// Default backend provider which uses a hash set as the event reporting status container +/// like mentioned in the example of the [PusEventMgmtBackendProvider] documentation. +/// +/// This provider is a good option for host systems or larger embedded systems where +/// the expected occasional memory allocation performed by the [HashSet] is not an issue. +#[derive(Default)] +pub struct DefaultPusMgmtBackendProvider { + disabled: HashSet, +} + +impl PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider { + type Error = (); + fn event_enabled(&self, event: &Event) -> bool { + !self.disabled.contains(event) + } + + fn enable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.remove(event)) + } + + fn disable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.insert(*event)) + } +} + +#[cfg(feature = "heapless")] +pub mod heapless_mod { + use super::*; + use crate::events::EventRaw; + + // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using + // regular Event type again. + #[derive(Default)] + pub struct HeaplessPusMgmtBckendProvider { + disabled: heapless::FnvIndexSet, + } + + impl PusEventMgmtBackendProvider for HeaplessPusMgmtBckendProvider { + type Error = (); + + fn event_enabled(&self, event: &Event) -> bool { + self.disabled.contains(&event.raw()) + } + + fn enable_event_reporting(&mut self, event: &Event) -> Result { + self.disabled.insert(event.raw()).map_err(|_| ()) + } + + fn disable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.remove(&event.raw())) + } + } +} + +pub struct PusEventManager {} diff --git a/fsrc-core/src/pus/mod.rs b/fsrc-core/src/pus/mod.rs index fb3a317..a09b398 100644 --- a/fsrc-core/src/pus/mod.rs +++ b/fsrc-core/src/pus/mod.rs @@ -3,5 +3,82 @@ //! Currenty includes: //! //! 1. PUS Verification Service 1 module inside [verification]. Requires [alloc] support. -#[cfg(feature = "alloc")] +use downcast_rs::{impl_downcast, Downcast}; +use spacepackets::ecss::PusError; +use spacepackets::time::TimestampError; +use spacepackets::tm::PusTm; +use spacepackets::{ByteConversionError, SizeMissmatch}; + +pub mod event; +pub mod event_man; pub mod verification; + +/// Generic error type which is also able to wrap a user send error with the user supplied type E. +#[derive(Debug, Clone)] +pub enum EcssTmError { + /// Errors related to sending the verification telemetry to a TM recipient + SendError(E), + /// Errors related to the time stamp format of the telemetry + TimestampError(TimestampError), + /// Errors related to byte conversion, for example insufficient buffer size for given data + ByteConversionError(ByteConversionError), + /// Errors related to PUS packet format + PusError(PusError), +} + +impl From for EcssTmError { + fn from(e: ByteConversionError) -> Self { + EcssTmError::ByteConversionError(e) + } +} + +/// Generic trait for a user supplied sender object. This sender object is responsible for sending +/// telemetry to a TM sink. The [Downcast] trait +/// is implemented to allow passing the sender as a boxed trait object and still retrieve the +/// concrete type at a later point. +pub trait EcssTmSender: Downcast + Send { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; +} + +impl_downcast!(EcssTmSender); + +pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmError> { + if len > cap { + return Err(EcssTmError::ByteConversionError( + ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: cap, + expected: len, + }), + )); + } + Ok(()) +} + +#[cfg(test)] +pub(crate) mod tests { + use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT}; + use spacepackets::CcsdsPacket; + + #[derive(Debug, Eq, PartialEq)] + pub(crate) struct CommonTmInfo { + pub subservice: u8, + pub apid: u16, + pub msg_counter: u16, + pub dest_id: u16, + pub time_stamp: [u8; 7], + } + + impl CommonTmInfo { + pub fn new_from_tm(tm: &PusTm) -> Self { + let mut time_stamp = [0; 7]; + time_stamp.clone_from_slice(&tm.time_stamp()[0..7]); + Self { + subservice: tm.subservice(), + apid: tm.apid(), + msg_counter: tm.msg_counter(), + dest_id: tm.dest_id(), + time_stamp, + } + } + } +} diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index 4af6ad6..479dc11 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -29,7 +29,7 @@ //! let shared_tm_pool: SharedPool = Arc::new(RwLock::new(Box::new(LocalPool::new(pool_cfg.clone())))); //! let (verif_tx, verif_rx) = crossbeam_channel::bounded(10); //! let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), verif_tx); -//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); +//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); //! let mut reporter = VerificationReporterWithSender::new(cfg , Box::new(sender)); //! //! let mut sph = SpHeader::tc(TEST_APID, 0, 0).unwrap(); @@ -55,7 +55,7 @@ //! tm_len = slice.len(); //! tm_buf[0..tm_len].copy_from_slice(slice); //! } -//! let (pus_tm, _) = PusTm::new_from_raw_slice(&tm_buf[0..tm_len], 7) +//! let (pus_tm, _) = PusTm::from_bytes(&tm_buf[0..tm_len], 7) //! .expect("Error reading verification TM"); //! if packet_idx == 0 { //! assert_eq!(pus_tm.subservice(), 1); @@ -71,21 +71,20 @@ //! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs) //! for the verification module contains examples how this module could be used in a more complex //! context involving multiple threads -use alloc::boxed::Box; -use alloc::vec; -use alloc::vec::Vec; +use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmSender}; use core::fmt::{Display, Formatter}; use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::size_of; use delegate::delegate; -use downcast_rs::{impl_downcast, Downcast}; -use spacepackets::ecss::{EcssEnumeration, PusError}; +use spacepackets::ecss::EcssEnumeration; use spacepackets::tc::PusTc; -use spacepackets::time::TimestampError; use spacepackets::tm::{PusTm, PusTmSecondaryHeader}; -use spacepackets::{ByteConversionError, SizeMissmatch, SpHeader}; use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl}; +use spacepackets::{SpHeader, MAX_APID}; + +#[cfg(feature = "alloc")] +pub use allocmod::{VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender}; #[cfg(feature = "std")] pub use stdmod::{ @@ -93,6 +92,24 @@ pub use stdmod::{ StdVerifReporterWithSender, StdVerifSenderError, }; +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub enum Subservices { + TmAcceptanceSuccess = 1, + TmAcceptanceFailure = 2, + TmStartSuccess = 3, + TmStartFailure = 4, + TmStepSuccess = 5, + TmStepFailure = 6, + TmCompletionSuccess = 7, + TmCompletionFailure = 8, +} + +impl From for u8 { + fn from(enumeration: Subservices) -> Self { + enumeration as u8 + } +} + /// This is a request identifier as specified in 5.4.11.2 c. of the PUS standard /// This field equivalent to the first two bytes of the CCSDS space packet header. #[derive(Debug, Eq, Copy, Clone)] @@ -160,39 +177,10 @@ impl RequestId { } } -/// Generic error type which is also able to wrap a user send error with the user supplied type E. -#[derive(Debug, Clone)] -pub enum VerificationError { - /// Errors related to sending the verification telemetry to a TM recipient - SendError(E), - /// Errors related to the time stamp format of the telemetry - TimestampError(TimestampError), - /// Errors related to byte conversion, for example unsufficient buffer size for given data - ByteConversionError(ByteConversionError), - /// Errors related to PUS packet format - PusError(PusError), -} - -impl From for VerificationError { - fn from(e: ByteConversionError) -> Self { - VerificationError::ByteConversionError(e) - } -} - /// If a verification operation fails, the passed token will be returned as well. This allows /// re-trying the operation at a later point. #[derive(Debug, Clone)] -pub struct VerificationErrorWithToken(VerificationError, VerificationToken); - -/// Generic trait for a user supplied sender object. This sender object is responsible for sending -/// PUS Service 1 Verification Telemetry to a verification TM recipient. The [Downcast] trait -/// is implemented to allow passing the sender as a boxed trait object and still retrieve the -/// concrete type at a later point. -pub trait VerificationSender: Downcast + Send { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; -} - -impl_downcast!(VerificationSender); +pub struct VerificationErrorWithToken(EcssTmError, VerificationToken); /// Support token to allow type-state programming. This prevents calling the verification /// steps in an invalid order. @@ -209,6 +197,12 @@ pub struct StateAccepted; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct StateStarted; +pub enum StateToken { + None(StateNone), + Accepted(StateAccepted), + Started(StateStarted), +} + impl VerificationToken { fn new(req_id: RequestId) -> VerificationToken { VerificationToken { @@ -222,41 +216,6 @@ impl VerificationToken { } } -pub struct VerificationReporterCfg { - pub apid: u16, - pub dest_id: u16, - pub step_field_width: usize, - pub fail_code_field_width: usize, - pub max_fail_data_len: usize, -} - -impl VerificationReporterCfg { - /// Create a new configuration for the verification reporter. This includes following parameters: - /// - /// 1. Destination ID and APID, which could remain constant after construction. These parameters - /// can be tweaked in the reporter after construction. - /// 2. Maximum expected field sizes. The parameters of this configuration struct will be used - /// to determine required maximum buffer sizes and there will be no addition allocation or - /// configurable buffer parameters after [VerificationReporter] construction. - /// - /// This means the user has supply the maximum expected field sizes of verification messages - /// before constructing the reporter. - pub fn new( - apid: u16, - step_field_width: usize, - fail_code_field_width: usize, - max_fail_data_len: usize, - ) -> Self { - Self { - apid, - dest_id: 0, - step_field_width, - fail_code_field_width, - max_fail_data_len, - } - } -} - /// Composite helper struct to pass failure parameters to the [VerificationReporter] pub struct FailParams<'a> { time_stamp: &'a [u8], @@ -298,33 +257,42 @@ impl<'a> FailParamsWithStep<'a> { } } -/// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets -/// and verify the various steps of telecommand handling as specified in the PUS standard. -pub struct VerificationReporter { - pub apid: u16, +pub struct VerificationReporterBasic { pub dest_id: u16, + apid: u16, msg_count: u16, - source_data_buf: Vec, } -impl VerificationReporter { - pub fn new(cfg: VerificationReporterCfg) -> Self { - Self { - apid: cfg.apid, - dest_id: cfg.dest_id, - msg_count: 0, - source_data_buf: vec![ - 0; - RequestId::SIZE_AS_BYTES - + cfg.step_field_width as usize - + cfg.fail_code_field_width as usize - + cfg.max_fail_data_len - ], +impl VerificationReporterBasic { + pub fn new(apid: u16) -> Option { + if apid > MAX_APID { + return None; } + Some(Self { + apid, + msg_count: 0, + dest_id: 0, + }) } - pub fn allowed_source_data_len(&self) -> usize { - self.source_data_buf.capacity() + pub fn set_apid(&mut self, apid: u16) -> bool { + if apid > MAX_APID { + return false; + } + self.apid = apid; + true + } + + pub fn apid(&self) -> u16 { + self.apid + } + + pub fn dest_id(&self) -> u16 { + self.dest_id + } + + pub fn set_dest_id(&mut self, dest_id: u16) { + self.dest_id = dest_id; } /// Initialize verification handling by passing a TC reference. This returns a token required @@ -342,21 +310,22 @@ impl VerificationReporter { /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard pub fn acceptance_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result, VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( - 1, - 1, + buf, + Subservices::TmAcceptanceSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(VerificationToken { @@ -368,15 +337,22 @@ impl VerificationReporter { /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard pub fn acceptance_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 2, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + Subservices::TmAcceptanceFailure.into(), + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -387,21 +363,22 @@ impl VerificationReporter { /// Requires a token previously acquired by calling [Self::acceptance_success]. pub fn start_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result, VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( - 1, - 3, + buf, + Subservices::TmStartSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(VerificationToken { @@ -416,15 +393,22 @@ impl VerificationReporter { /// the token because verification handling is done. pub fn start_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 4, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + Subservices::TmStartFailure.into(), + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -435,13 +419,20 @@ impl VerificationReporter { /// Requires a token previously acquired by calling [Self::start_success]. pub fn step_success( &mut self, + buf: &mut [u8], token: &VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], step: impl EcssEnumeration, - ) -> Result<(), VerificationError> { - let tm = self.create_pus_verif_success_tm(1, 5, &token.req_id, time_stamp, Some(&step))?; - sender.send_verification_tm(tm)?; + ) -> Result<(), EcssTmError> { + let tm = self.create_pus_verif_success_tm( + buf, + Subservices::TmStepSuccess.into(), + &token.req_id, + time_stamp, + Some(&step), + )?; + sender.send_tm(tm)?; self.msg_count += 1; Ok(()) } @@ -452,15 +443,22 @@ impl VerificationReporter { /// token because verification handling is done. pub fn step_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParamsWithStep, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 6, &token.req_id, Some(params.step), ¶ms.bp) + .create_pus_verif_fail_tm( + buf, + Subservices::TmStepFailure.into(), + &token.req_id, + Some(params.step), + ¶ms.bp, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -472,21 +470,22 @@ impl VerificationReporter { /// token because verification handling is done. pub fn completion_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result<(), VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( - 1, - 7, + buf, + Subservices::TmCompletionSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -498,15 +497,22 @@ impl VerificationReporter { /// token because verification handling is done. pub fn completion_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 8, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + Subservices::TmCompletionFailure.into(), + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -514,28 +520,28 @@ impl VerificationReporter { fn create_pus_verif_success_tm<'a, E>( &'a mut self, - service: u8, + buf: &'a mut [u8], subservice: u8, req_id: &RequestId, time_stamp: &'a [u8], step: Option<&(impl EcssEnumeration + ?Sized)>, - ) -> Result> { + ) -> Result> { let mut source_data_len = size_of::(); if let Some(step) = step { source_data_len += step.byte_width() as usize; } - self.source_buffer_large_enough(source_data_len)?; + source_buffer_large_enough(buf.len(), source_data_len)?; let mut idx = 0; - req_id.to_bytes(&mut self.source_data_buf[0..RequestId::SIZE_AS_BYTES]); + req_id.to_bytes(&mut buf[0..RequestId::SIZE_AS_BYTES]); idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check was done beforehand - step.to_bytes(&mut self.source_data_buf[idx..idx + step.byte_width() as usize]) + step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); } - let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( - service, + buf, subservice, &mut sp_header, time_stamp, @@ -545,12 +551,12 @@ impl VerificationReporter { fn create_pus_verif_fail_tm<'a, E>( &'a mut self, - service: u8, + buf: &'a mut [u8], subservice: u8, req_id: &RequestId, step: Option<&(impl EcssEnumeration + ?Sized)>, params: &'a FailParams, - ) -> Result> { + ) -> Result> { let mut idx = 0; let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.byte_width() as usize; @@ -560,25 +566,25 @@ impl VerificationReporter { if let Some(failure_data) = params.failure_data { source_data_len += failure_data.len(); } - self.source_buffer_large_enough(source_data_len)?; - req_id.to_bytes(&mut self.source_data_buf[0..RequestId::SIZE_AS_BYTES]); + source_buffer_large_enough(buf.len(), source_data_len)?; + req_id.to_bytes(&mut buf[0..RequestId::SIZE_AS_BYTES]); idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check done beforehand - step.to_bytes(&mut self.source_data_buf[idx..idx + step.byte_width() as usize]) + step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); idx += step.byte_width() as usize; } - params.failure_code.to_bytes( - &mut self.source_data_buf[idx..idx + params.failure_code.byte_width() as usize], - )?; + params + .failure_code + .write_to_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?; idx += params.failure_code.byte_width() as usize; if let Some(failure_data) = params.failure_data { - self.source_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); + buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); } - let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( - service, + buf, subservice, &mut sp_header, params.time_stamp, @@ -586,148 +592,341 @@ impl VerificationReporter { )) } - fn source_buffer_large_enough(&self, len: usize) -> Result<(), VerificationError> { - if len > self.source_data_buf.capacity() { - return Err(VerificationError::ByteConversionError( - ByteConversionError::ToSliceTooSmall(SizeMissmatch { - found: self.source_data_buf.capacity(), - expected: len, - }), - )); - } - Ok(()) - } - fn create_pus_verif_tm_base<'a>( &'a mut self, - service: u8, + buf: &'a mut [u8], subservice: u8, sp_header: &mut SpHeader, time_stamp: &'a [u8], source_data_len: usize, ) -> PusTm { - let tm_sec_header = PusTmSecondaryHeader::new( - service, - subservice, - self.msg_count, - self.dest_id, - time_stamp, - ); + let tm_sec_header = + PusTmSecondaryHeader::new(1, subservice, self.msg_count, self.dest_id, time_stamp); PusTm::new( sp_header, tm_sec_header, - Some(&self.source_data_buf[0..source_data_len]), + Some(&buf[0..source_data_len]), true, ) } } -/// Helper object which caches the sender passed as a trait object. Provides the same -/// API as [VerificationReporter] but without the explicit sender arguments. -pub struct VerificationReporterWithSender { - reporter: VerificationReporter, - pub sender: Box>, -} +#[cfg(feature = "alloc")] +mod allocmod { + use super::*; + use alloc::boxed::Box; + use alloc::vec; + use alloc::vec::Vec; -impl VerificationReporterWithSender { - pub fn new(cfg: VerificationReporterCfg, sender: Box>) -> Self { - Self::new_from_reporter(VerificationReporter::new(cfg), sender) + pub struct VerificationReporterCfg { + apid: u16, + pub step_field_width: usize, + pub fail_code_field_width: usize, + pub max_fail_data_len: usize, } - pub fn new_from_reporter( - reporter: VerificationReporter, - sender: Box>, - ) -> Self { - Self { reporter, sender } - } - - delegate! { - to self.reporter { - pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; - pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + impl VerificationReporterCfg { + pub fn new( + apid: u16, + step_field_width: usize, + fail_code_field_width: usize, + max_fail_data_len: usize, + ) -> Option { + if apid > MAX_APID { + return None; + } + Some(Self { + apid, + step_field_width, + fail_code_field_width, + max_fail_data_len, + }) } } - pub fn acceptance_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result, VerificationErrorWithToken> { - self.reporter - .acceptance_success(token, self.sender.as_mut(), time_stamp) + /// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets + /// and verify the various steps of telecommand handling as specified in the PUS standard. + pub struct VerificationReporter { + source_data_buf: Vec, + pub reporter: VerificationReporterBasic, } - pub fn acceptance_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .acceptance_failure(token, self.sender.as_mut(), params) + impl VerificationReporter { + pub fn new(cfg: VerificationReporterCfg) -> Self { + let reporter = VerificationReporterBasic::new(cfg.apid).unwrap(); + Self { + source_data_buf: vec![ + 0; + RequestId::SIZE_AS_BYTES + + cfg.step_field_width as usize + + cfg.fail_code_field_width as usize + + cfg.max_fail_data_len + ], + reporter, + } + } + + delegate!( + to self.reporter { + pub fn set_apid(&mut self, apid: u16) -> bool; + pub fn apid(&self) -> u16; + pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; + pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + pub fn dest_id(&self) -> u16; + pub fn set_dest_id(&mut self, dest_id: u16); + } + ); + + pub fn allowed_source_data_len(&self) -> usize { + self.source_data_buf.capacity() + } + + /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard + pub fn acceptance_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter.acceptance_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard + pub fn acceptance_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.acceptance_failure( + self.source_data_buf.as_mut_slice(), + token, + sender, + params, + ) + } + + /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::acceptance_success]. + pub fn start_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter.start_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes + /// the token because verification handling is done. + pub fn start_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .start_failure(self.source_data_buf.as_mut_slice(), token, sender, params) + } + + /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. + pub fn step_success( + &mut self, + token: &VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + step: impl EcssEnumeration, + ) -> Result<(), EcssTmError> { + self.reporter.step_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + step, + ) + } + + /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn step_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParamsWithStep, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .step_failure(self.source_data_buf.as_mut_slice(), token, sender, params) + } + + /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn completion_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.completion_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 8\] packet, see 8.1.2.8 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn completion_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.completion_failure( + self.source_data_buf.as_mut_slice(), + token, + sender, + params, + ) + } } - pub fn start_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result, VerificationErrorWithToken> { - self.reporter - .start_success(token, self.sender.as_mut(), time_stamp) + /// Helper object which caches the sender passed as a trait object. Provides the same + /// API as [VerificationReporter] but without the explicit sender arguments. + pub struct VerificationReporterWithSender { + pub reporter: VerificationReporter, + pub sender: Box>, } - pub fn start_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .start_failure(token, self.sender.as_mut(), params) - } + impl VerificationReporterWithSender { + pub fn new(cfg: VerificationReporterCfg, sender: Box>) -> Self { + let reporter = VerificationReporter::new(cfg); + Self::new_from_reporter(reporter, sender) + } - pub fn step_success( - &mut self, - token: &VerificationToken, - time_stamp: &[u8], - step: impl EcssEnumeration, - ) -> Result<(), VerificationError> { - self.reporter - .step_success(token, self.sender.as_mut(), time_stamp, step) - } + pub fn new_from_reporter( + reporter: VerificationReporter, + sender: Box>, + ) -> Self { + Self { reporter, sender } + } - pub fn step_failure( - &mut self, - token: VerificationToken, - params: FailParamsWithStep, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .step_failure(token, self.sender.as_mut(), params) - } + delegate! { + to self.reporter { + pub fn set_apid(&mut self, apid: u16) -> bool; + pub fn apid(&self) -> u16; + pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; + pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + pub fn dest_id(&self) -> u16; + pub fn set_dest_id(&mut self, dest_id: u16); + } + } - pub fn completion_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .completion_success(token, self.sender.as_mut(), time_stamp) - } + pub fn acceptance_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter + .acceptance_success(token, self.sender.as_mut(), time_stamp) + } - pub fn completion_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .completion_failure(token, self.sender.as_mut(), params) + pub fn acceptance_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .acceptance_failure(token, self.sender.as_mut(), params) + } + + pub fn start_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter + .start_success(token, self.sender.as_mut(), time_stamp) + } + + pub fn start_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .start_failure(token, self.sender.as_mut(), params) + } + + pub fn step_success( + &mut self, + token: &VerificationToken, + time_stamp: &[u8], + step: impl EcssEnumeration, + ) -> Result<(), EcssTmError> { + self.reporter + .step_success(token, self.sender.as_mut(), time_stamp, step) + } + + pub fn step_failure( + &mut self, + token: VerificationToken, + params: FailParamsWithStep, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .step_failure(token, self.sender.as_mut(), params) + } + + pub fn completion_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .completion_success(token, self.sender.as_mut(), time_stamp) + } + + pub fn completion_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .completion_failure(token, self.sender.as_mut(), params) + } } } #[cfg(feature = "std")] mod stdmod { + use super::allocmod::VerificationReporterWithSender; + use super::*; use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError}; - use crate::pus::verification::{ - VerificationError, VerificationReporterWithSender, VerificationSender, - }; use delegate::delegate; use spacepackets::tm::PusTm; use std::sync::{mpsc, Arc, Mutex, RwLockWriteGuard}; @@ -748,9 +947,9 @@ mod stdmod { } } - impl From for VerificationError { + impl From for EcssTmError { fn from(e: StoreError) -> Self { - VerificationError::SendError(e.into()) + EcssTmError::SendError(e.into()) } } @@ -798,10 +997,10 @@ mod stdmod { } //noinspection RsTraitImplementation - impl VerificationSender for MpscVerifSender { + impl EcssTmSender for MpscVerifSender { delegate!( to self.base { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; } ); } @@ -829,10 +1028,10 @@ mod stdmod { } //noinspection RsTraitImplementation - impl VerificationSender for CrossbeamVerifSender { + impl EcssTmSender for CrossbeamVerifSender { delegate!( to self.base { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; } ); } @@ -840,17 +1039,14 @@ mod stdmod { unsafe impl Sync for CrossbeamVerifSender {} unsafe impl Send for CrossbeamVerifSender {} - impl VerificationSender for StdSenderBase { - fn send_verification_tm( - &mut self, - tm: PusTm, - ) -> Result<(), VerificationError> { + impl EcssTmSender for StdSenderBase { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError> { let operation = |mut mg: RwLockWriteGuard| { let (addr, buf) = mg.free_element(tm.len_packed())?; - tm.write_to(buf).map_err(VerificationError::PusError)?; + tm.write_to_bytes(buf).map_err(EcssTmError::PusError)?; drop(mg); self.tx.send(addr).map_err(|_| { - VerificationError::SendError(StdVerifSenderError::RxDisconnected(addr)) + EcssTmError::SendError(StdVerifSenderError::RxDisconnected(addr)) })?; Ok(()) }; @@ -860,9 +1056,7 @@ mod stdmod { if self.ignore_poison_error { operation(poison_error.into_inner()) } else { - Err(VerificationError::SendError( - StdVerifSenderError::PoisonError, - )) + Err(EcssTmError::SendError(StdVerifSenderError::PoisonError)) } } } @@ -872,30 +1066,27 @@ mod stdmod { #[cfg(test)] mod tests { + use crate::pus::tests::CommonTmInfo; use crate::pus::verification::{ - FailParams, FailParamsWithStep, RequestId, StateNone, VerificationError, + EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, StateNone, VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, - VerificationSender, VerificationToken, + VerificationToken, }; use alloc::boxed::Box; use alloc::format; - use alloc::vec::Vec; use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusPacket}; use spacepackets::tc::{PusTc, PusTcSecondaryHeader}; - use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT}; - use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader}; + use spacepackets::tm::PusTm; + use spacepackets::{ByteConversionError, SpHeader}; use std::collections::VecDeque; + use std::vec::Vec; const TEST_APID: u16 = 0x02; const EMPTY_STAMP: [u8; 7] = [0; 7]; #[derive(Debug, Eq, PartialEq)] struct TmInfo { - pub subservice: u8, - pub apid: u16, - pub msg_counter: u16, - pub dest_id: u16, - pub time_stamp: [u8; 7], + pub common: CommonTmInfo, pub req_id: RequestId, pub additional_data: Option>, } @@ -905,8 +1096,8 @@ mod tests { pub service_queue: VecDeque, } - impl VerificationSender<()> for TestSender { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError<()>> { + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { assert_eq!(PusPacket::service(&tm), 1); assert!(tm.source_data().is_some()); let mut time_stamp = [0; 7]; @@ -921,11 +1112,7 @@ mod tests { vec = Some(new_vec); } self.service_queue.push_back(TmInfo { - subservice: PusPacket::subservice(&tm), - apid: tm.apid(), - msg_counter: tm.msg_counter(), - dest_id: tm.dest_id(), - time_stamp, + common: CommonTmInfo::new_from_tm(&tm), req_id, additional_data: vec, }); @@ -938,9 +1125,9 @@ mod tests { #[derive(Default)] struct FallibleSender {} - impl VerificationSender for FallibleSender { - fn send_verification_tm(&mut self, _: PusTm) -> Result<(), VerificationError> { - Err(VerificationError::SendError(DummyError {})) + impl EcssTmSender for FallibleSender { + fn send_tm(&mut self, _: PusTm) -> Result<(), EcssTmError> { + Err(EcssTmError::SendError(DummyError {})) } } @@ -968,7 +1155,7 @@ mod tests { } fn base_reporter() -> VerificationReporter { - let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); + let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); VerificationReporter::new(cfg) } @@ -1006,11 +1193,13 @@ mod tests { fn acceptance_check(sender: &mut TestSender, req_id: &RequestId) { let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id: req_id.clone(), }; @@ -1019,6 +1208,14 @@ mod tests { assert_eq!(info, cmp_info); } + #[test] + fn test_state() { + let (mut b, _) = base_init(false); + assert_eq!(b.vr.apid(), TEST_APID); + b.vr.set_apid(TEST_APID + 1); + assert_eq!(b.vr.apid(), TEST_APID + 1); + } + #[test] fn test_basic_acceptance_success() { let (mut b, tok) = base_init(false); @@ -1048,7 +1245,7 @@ mod tests { let err = res.unwrap_err(); assert_eq!(err.1, tok); match err.0 { - VerificationError::SendError(e) => { + EcssTmError::SendError(e) => { assert_eq!(e, DummyError {}) } _ => panic!("{}", format!("Unexpected error {:?}", err.0)), @@ -1057,11 +1254,13 @@ mod tests { fn acceptance_fail_check(sender: &mut TestSender, req_id: RequestId, stamp_buf: [u8; 7]) { let cmp_info = TmInfo { - time_stamp: stamp_buf, - subservice: 2, - dest_id: 5, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 2, + apid: TEST_APID, + msg_counter: 0, + dest_id: 5, + time_stamp: stamp_buf, + }, additional_data: Some([0, 2].to_vec()), req_id, }; @@ -1073,7 +1272,7 @@ mod tests { #[test] fn test_basic_acceptance_failure() { let (mut b, tok) = base_init(true); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let mut sender = TestSender::default(); let fail_code = EcssEnumU16::new(2); @@ -1086,7 +1285,7 @@ mod tests { #[test] fn test_basic_acceptance_failure_with_helper() { let (mut b, tok) = base_with_helper_init(); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_params = FailParams::new(stamp_buf.as_slice(), &fail_code, None); @@ -1100,7 +1299,7 @@ mod tests { #[test] fn test_acceptance_fail_data_too_large() { let (mut b, tok) = base_with_helper_init(); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_data: [u8; 16] = [0; 16]; @@ -1113,7 +1312,7 @@ mod tests { let err_with_token = res.unwrap_err(); assert_eq!(err_with_token.1, tok); match err_with_token.0 { - VerificationError::ByteConversionError(e) => match e { + EcssTmError::ByteConversionError(e) => match e { ByteConversionError::ToSliceTooSmall(missmatch) => { assert_eq!( missmatch.expected, @@ -1138,16 +1337,18 @@ mod tests { let fail_code = EcssEnumU8::new(10); let fail_data = EcssEnumU32::new(12); let mut fail_data_raw = [0; 4]; - fail_data.to_bytes(&mut fail_data_raw).unwrap(); + fail_data.write_to_bytes(&mut fail_data_raw).unwrap(); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, Some(fail_data_raw.as_slice())); b.vr.acceptance_failure(tok, &mut sender, fail_params) .expect("Sending acceptance success failed"); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 2, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 2, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([10, 0, 0, 0, 12].to_vec()), req_id: tok.req_id, }; @@ -1159,11 +1360,13 @@ mod tests { fn start_fail_check(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { assert_eq!(sender.service_queue.len(), 2); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1171,11 +1374,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 4, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 4, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()), req_id, }; @@ -1227,44 +1432,52 @@ mod tests { fn step_success_check(sender: &mut TestSender, req_id: RequestId) { let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; let mut info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0].to_vec()), req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 3, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 3, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([1].to_vec()), req_id, }; @@ -1336,11 +1549,13 @@ mod tests { fn check_step_failure(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { assert_eq!(sender.service_queue.len(), 4); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1348,11 +1563,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; @@ -1360,11 +1577,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0].to_vec()), req_id, }; @@ -1372,11 +1591,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 6, - dest_id: 0, - apid: TEST_APID, - msg_counter: 3, + common: CommonTmInfo { + subservice: 6, + apid: TEST_APID, + msg_counter: 3, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some( [ [1].as_slice(), @@ -1473,11 +1694,13 @@ mod tests { assert_eq!(sender.service_queue.len(), 3); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1485,11 +1708,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; @@ -1497,11 +1722,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 8, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 8, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0, 0, 0x10, 0x20].to_vec()), req_id, }; @@ -1557,11 +1784,13 @@ mod tests { fn completion_success_check(sender: &mut TestSender, req_id: RequestId) { assert_eq!(sender.service_queue.len(), 3); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1569,22 +1798,26 @@ mod tests { assert_eq!(info, cmp_info); let cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 7, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 7, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 92d6c39..e09cb6b 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -58,7 +58,7 @@ //! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); //! let mut test_buf: [u8; 32] = [0; 32]; //! let mut size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); @@ -66,7 +66,7 @@ //! // Now pass a packet with an unknown APID to the distributor //! pus_tc.set_apid(0x003); //! size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); @@ -201,7 +201,9 @@ pub(crate) mod tests { pub fn generate_ping_tc(buf: &mut [u8]) -> &[u8] { let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); - let size = pus_tc.write_to(buf).expect("Error writing TC to buffer"); + let size = pus_tc + .write_to_bytes(buf) + .expect("Error writing TC to buffer"); assert_eq!(size, 13); &buf[0..size] } @@ -314,7 +316,7 @@ pub(crate) mod tests { let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; pus_tc - .write_to(test_buf.as_mut_slice()) + .write_to_bytes(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed"); let recvd = unknown_packet_queue.lock().unwrap().pop_front(); diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 9ee8bc6..3171b4b 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -47,7 +47,7 @@ //! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); //! let mut test_buf: [u8; 32] = [0; 32]; //! let mut size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! @@ -99,7 +99,7 @@ impl ReceivesTc for PusDistributor { fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> { // Convert to ccsds and call pass_ccsds let sp_header = SpHeader::from_raw_slice(tm_raw) - .map_err(|e| PusDistribError::PusError(PusError::PacketError(e)))?; + .map_err(|e| PusDistribError::PusError(PusError::ByteConversionError(e)))?; self.pass_ccsds(&sp_header, tm_raw) } } @@ -107,8 +107,7 @@ impl ReceivesTc for PusDistributor { impl ReceivesCcsdsTc for PusDistributor { type Error = PusDistribError; fn pass_ccsds(&mut self, header: &SpHeader, tm_raw: &[u8]) -> Result<(), Self::Error> { - let (tc, _) = - PusTc::new_from_raw_slice(tm_raw).map_err(|e| PusDistribError::PusError(e))?; + let (tc, _) = PusTc::from_bytes(tm_raw).map_err(|e| PusDistribError::PusError(e))?; self.pass_pus_tc(header, &tc) } } diff --git a/fsrc-core/tests/pool_test.rs b/fsrc-core/tests/pools.rs similarity index 100% rename from fsrc-core/tests/pool_test.rs rename to fsrc-core/tests/pools.rs diff --git a/fsrc-core/tests/pus_events.rs b/fsrc-core/tests/pus_events.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/fsrc-core/tests/pus_events.rs @@ -0,0 +1 @@ + diff --git a/fsrc-core/tests/verification_test.rs b/fsrc-core/tests/pus_verification.rs similarity index 94% rename from fsrc-core/tests/verification_test.rs rename to fsrc-core/tests/pus_verification.rs index 22f351e..a158706 100644 --- a/fsrc-core/tests/verification_test.rs +++ b/fsrc-core/tests/pus_verification.rs @@ -25,7 +25,7 @@ const PACKETS_SENT: u8 = 8; /// threads have sent the correct expected verification reports #[test] fn test_shared_reporter() { - let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); + let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); // Shared pool object to store the verification PUS telemetry let pool_cfg = PoolCfg::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]); let shared_tm_pool: SharedPool = @@ -53,14 +53,14 @@ fn test_shared_reporter() { let pus_tc_0 = PusTc::new(&mut sph, tc_header, None, true); req_id_0 = RequestId::new(&pus_tc_0); let (addr, mut buf) = tc_guard.free_element(pus_tc_0.len_packed()).unwrap(); - pus_tc_0.write_to(&mut buf).unwrap(); + pus_tc_0.write_to_bytes(&mut buf).unwrap(); tx_tc_0.send(addr).unwrap(); let mut sph = SpHeader::tc(TEST_APID, 1, 0).unwrap(); let tc_header = PusTcSecondaryHeader::new_simple(5, 1); let pus_tc_1 = PusTc::new(&mut sph, tc_header, None, true); req_id_1 = RequestId::new(&pus_tc_1); let (addr, mut buf) = tc_guard.free_element(pus_tc_0.len_packed()).unwrap(); - pus_tc_1.write_to(&mut buf).unwrap(); + pus_tc_1.write_to_bytes(&mut buf).unwrap(); tx_tc_1.send(addr).unwrap(); } let verif_sender_0 = thread::spawn(move || { @@ -76,7 +76,7 @@ fn test_shared_reporter() { tc_len = buf.len(); tc_buf[0..tc_len].copy_from_slice(buf); } - let (_tc, _) = PusTc::new_from_raw_slice(&tc_buf[0..tc_len]).unwrap(); + let (_tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap(); let accepted_token; { let mut mg = reporter_with_sender_0.lock().expect("Locking mutex failed"); @@ -117,7 +117,7 @@ fn test_shared_reporter() { tc_len = buf.len(); tc_buf[0..tc_len].copy_from_slice(buf); } - let (tc, _) = PusTc::new_from_raw_slice(&tc_buf[0..tc_len]).unwrap(); + let (tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap(); let mut mg = reporter_with_sender_1 .lock() .expect("Locking reporter failed"); @@ -150,8 +150,8 @@ fn test_shared_reporter() { tm_len = slice.len(); tm_buf[0..tm_len].copy_from_slice(slice); } - let (pus_tm, _) = PusTm::new_from_raw_slice(&tm_buf[0..tm_len], 7) - .expect("Error reading verification TM"); + let (pus_tm, _) = + PusTm::from_bytes(&tm_buf[0..tm_len], 7).expect("Error reading verification TM"); let req_id = RequestId::from_bytes( &pus_tm.source_data().expect("Invalid TM source data")[0..RequestId::SIZE_AS_BYTES], ) diff --git a/fsrc-example/Cargo.toml b/fsrc-example/Cargo.toml index 8bccc84..1bc9f48 100644 --- a/fsrc-example/Cargo.toml +++ b/fsrc-example/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Robin Mueller "] [dependencies] crossbeam-channel = "0.5" delegate = "0.8" +zerocopy = "0.6" [dependencies.spacepackets] path = "../spacepackets" diff --git a/fsrc-example/src/bin/client.rs b/fsrc-example/src/bin/client.rs index 1f56418..59ad725 100644 --- a/fsrc-example/src/bin/client.rs +++ b/fsrc-example/src/bin/client.rs @@ -18,7 +18,9 @@ fn main() { "Packing and sending PUS ping command TC[17,1] with request ID {}", tc_req_id ); - let size = pus_tc.write_to(&mut buf).expect("Creating PUS TC failed"); + let size = pus_tc + .write_to_bytes(&mut buf) + .expect("Creating PUS TC failed"); client .send_to(&buf[0..size], &addr) .expect(&*format!("Sending to {:?} failed", addr)); @@ -29,8 +31,7 @@ fn main() { let res = client.recv(&mut buf); match res { Ok(_len) => { - let (pus_tm, size) = - PusTm::new_from_raw_slice(&buf, 7).expect("Parsing PUS TM failed"); + let (pus_tm, size) = PusTm::from_bytes(&buf, 7).expect("Parsing PUS TM failed"); if pus_tm.service() == 17 && pus_tm.subservice() == 2 { println!("Received PUS Ping Reply TM[17,2]") } else if pus_tm.service() == 1 { diff --git a/fsrc-example/src/bin/obsw/main.rs b/fsrc-example/src/bin/obsw/main.rs index 00ad086..a7c5de1 100644 --- a/fsrc-example/src/bin/obsw/main.rs +++ b/fsrc-example/src/bin/obsw/main.rs @@ -39,7 +39,7 @@ fn main() { let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel(); let (tm_server_tx, tm_server_rx) = mpsc::channel(); let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone()); - let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8); + let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap(); let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new( verif_cfg, Box::new(sender), diff --git a/fsrc-example/src/bin/obsw/tmtc.rs b/fsrc-example/src/bin/obsw/tmtc.rs index 5a34d1e..3b3e88e 100644 --- a/fsrc-example/src/bin/obsw/tmtc.rs +++ b/fsrc-example/src/bin/obsw/tmtc.rs @@ -24,7 +24,7 @@ impl TmStore { let mut pg = self.pool.write().expect("Error locking TM store"); let (addr, buf) = pg.free_element(pus_tm.len_packed()).expect("Store error"); pus_tm - .write_to(buf) + .write_to_bytes(buf) .expect("Writing PUS TM to store failed"); addr } diff --git a/fsrc-example/src/bin/test.rs b/fsrc-example/src/bin/test.rs index a979878..d88c902 100644 --- a/fsrc-example/src/bin/test.rs +++ b/fsrc-example/src/bin/test.rs @@ -1,5 +1,7 @@ +#![allow(dead_code)] use crossbeam_channel::{bounded, Receiver, Sender}; use std::thread; +use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16}; trait FieldDataProvider: Send { fn get_data(&self) -> &[u8]; @@ -26,6 +28,18 @@ impl FieldDataProvider for FixedFieldDataWrapper { type FieldDataTraitObj = Box; +struct ExampleMgmSet { + mgm_vec: [f32; 3], + temperature: u16, +} + +#[derive(FromBytes, AsBytes, Unaligned)] +#[repr(C)] +struct ExampleMgmSetZc { + mgm_vec: [u8; 12], + temperatur: U16, +} + fn main() { let (s0, r0): (Sender, Receiver) = bounded(5); let data_wrapper = FixedFieldDataWrapper::from_two_u32(2, 3); diff --git a/spacepackets b/spacepackets index 94489da..603f688 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 94489da00323dc6caf24e05e240c80fc10b5d8cc +Subproject commit 603f688ac3e914de13037fd22ac544e125b6305b