From 975d02f49712bc05a00d5f79b27a468e5373d3d0 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 09:23:40 +1100 Subject: [PATCH 01/20] Restructure project to enable custom mavlink bindings generation Split the project into three crates: * mavlink-core: core MAVLink types including TCP, UDP and serial connections * mavlink-bindgen: a library & CLI for generating Rust bindings for MAVLink dialects * mavlink: generated MAVLink bindings for the MAVLink dialects in the mavlink/mavlink repo --- .gitmodules | 4 +- Cargo.toml | 103 +-------------- build/main.rs | 101 -------------- mavlink-bindgen/Cargo.toml | 16 +++ {build => mavlink-bindgen/src}/binder.rs | 2 +- mavlink-bindgen/src/error.rs | 23 ++++ mavlink-bindgen/src/lib.rs | 125 ++++++++++++++++++ mavlink-bindgen/src/main.rs | 30 +++++ {build => mavlink-bindgen/src}/parser.rs | 23 ++-- {build => mavlink-bindgen/src}/util.rs | 0 mavlink-core/Cargo.toml | 28 ++++ {src => mavlink-core/src}/bytes.rs | 0 {src => mavlink-core/src}/bytes_mut.rs | 0 .../src}/connection/direct_serial.rs | 0 {src => mavlink-core/src}/connection/file.rs | 0 {src => mavlink-core/src}/connection/mod.rs | 0 {src => mavlink-core/src}/connection/tcp.rs | 0 {src => mavlink-core/src}/connection/udp.rs | 0 {src => mavlink-core/src}/embedded.rs | 0 {src => mavlink-core/src}/error.rs | 0 {src => mavlink-core/src}/lib.rs | 51 ++++--- {src => mavlink-core/src}/utils.rs | 2 +- mavlink/Cargo.toml | 96 ++++++++++++++ mavlink/build/main.rs | 53 ++++++++ .../examples}/embedded/.cargo/config.toml | 0 .../examples}/embedded/Cargo.toml | 0 .../examples}/embedded/README.md | 0 .../examples}/embedded/memory.x | 0 .../examples}/embedded/src/main.rs | 0 .../examples}/mavlink-dump/Cargo.toml | 0 .../examples}/mavlink-dump/src/main.rs | 0 mavlink => mavlink/mavlink | 0 rustfmt.toml => mavlink/rustfmt.toml | 0 mavlink/src/lib.rs | 4 + .../tests}/direct_serial_tests.rs | 0 .../tests}/encode_decode_tests.rs | 0 {tests => mavlink/tests}/helper_tests.rs | 0 {tests => mavlink/tests}/log.tlog | Bin {tests => mavlink/tests}/mav_frame_tests.rs | 0 {tests => mavlink/tests}/process_log_files.rs | 0 .../tests}/tcp_loopback_tests.rs | 0 {tests => mavlink/tests}/test_shared/mod.rs | 0 .../tests}/udp_loopback_tests.rs | 0 .../tests}/v1_encode_decode_tests.rs | 0 .../tests}/v2_encode_decode_tests.rs | 0 45 files changed, 418 insertions(+), 243 deletions(-) delete mode 100644 build/main.rs create mode 100644 mavlink-bindgen/Cargo.toml rename {build => mavlink-bindgen/src}/binder.rs (91%) create mode 100644 mavlink-bindgen/src/error.rs create mode 100644 mavlink-bindgen/src/lib.rs create mode 100644 mavlink-bindgen/src/main.rs rename {build => mavlink-bindgen/src}/parser.rs (98%) rename {build => mavlink-bindgen/src}/util.rs (100%) create mode 100644 mavlink-core/Cargo.toml rename {src => mavlink-core/src}/bytes.rs (100%) rename {src => mavlink-core/src}/bytes_mut.rs (100%) rename {src => mavlink-core/src}/connection/direct_serial.rs (100%) rename {src => mavlink-core/src}/connection/file.rs (100%) rename {src => mavlink-core/src}/connection/mod.rs (100%) rename {src => mavlink-core/src}/connection/tcp.rs (100%) rename {src => mavlink-core/src}/connection/udp.rs (100%) rename {src => mavlink-core/src}/embedded.rs (100%) rename {src => mavlink-core/src}/error.rs (100%) rename {src => mavlink-core/src}/lib.rs (96%) rename {src => mavlink-core/src}/utils.rs (97%) create mode 100644 mavlink/Cargo.toml create mode 100644 mavlink/build/main.rs rename {examples => mavlink/examples}/embedded/.cargo/config.toml (100%) rename {examples => mavlink/examples}/embedded/Cargo.toml (100%) rename {examples => mavlink/examples}/embedded/README.md (100%) rename {examples => mavlink/examples}/embedded/memory.x (100%) rename {examples => mavlink/examples}/embedded/src/main.rs (100%) rename {examples => mavlink/examples}/mavlink-dump/Cargo.toml (100%) rename {examples => mavlink/examples}/mavlink-dump/src/main.rs (100%) rename mavlink => mavlink/mavlink (100%) rename rustfmt.toml => mavlink/rustfmt.toml (100%) create mode 100644 mavlink/src/lib.rs rename {tests => mavlink/tests}/direct_serial_tests.rs (100%) rename {tests => mavlink/tests}/encode_decode_tests.rs (100%) rename {tests => mavlink/tests}/helper_tests.rs (100%) rename {tests => mavlink/tests}/log.tlog (100%) rename {tests => mavlink/tests}/mav_frame_tests.rs (100%) rename {tests => mavlink/tests}/process_log_files.rs (100%) rename {tests => mavlink/tests}/tcp_loopback_tests.rs (100%) rename {tests => mavlink/tests}/test_shared/mod.rs (100%) rename {tests => mavlink/tests}/udp_loopback_tests.rs (100%) rename {tests => mavlink/tests}/v1_encode_decode_tests.rs (100%) rename {tests => mavlink/tests}/v2_encode_decode_tests.rs (100%) diff --git a/.gitmodules b/.gitmodules index 3fbebb0955..80bff682ff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "mavlink"] - path = mavlink +[submodule "mavlink/mavlink"] + path = mavlink/mavlink url = https://github.com/mavlink/mavlink diff --git a/Cargo.toml b/Cargo.toml index b099521299..65e9ef8b1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,105 +1,10 @@ +[workspace] +members = ["mavlink", "mavlink-bindgen", "mavlink-core"] +resolver = "1" -[package] -name = "mavlink" -version = "0.12.2" -authors = ["Todd Stellanova", "Michal Podhradsky", "Kevin Mehall", "Tim Ryan", "Patrick José Pereira", "Ibiyemi Abiodun"] -build = "build/main.rs" -description = "Implements the MAVLink data interchange format for UAVs." -readme = "README.md" -license = "MIT/Apache-2.0" -repository = "https://github.com/mavlink/rust-mavlink" -edition = "2018" -rust-version = "1.65.0" - -[build-dependencies] -crc-any = { version = "2.3.0", default-features = false } -quick-xml = "0.26" -quote = "1" -proc-macro2 = "1.0.43" -lazy_static = "1.2.0" -serde = { version = "1.0.115", optional = true, features = ["derive"] } - -[[example]] -name = "mavlink-dump" -path = "examples/mavlink-dump/src/main.rs" -required-features = ["ardupilotmega"] - -[dependencies] +[workspace.dependencies] crc-any = { version = "2.3.5", default-features = false } num-traits = { version = "0.2", default-features = false } num-derive = "0.3.2" bitflags = "1.2.1" -serial = { version = "0.4", optional = true } -serde = { version = "1.0.115", optional = true, features = ["derive"] } byteorder = { version = "1.3.4", default-features = false } -embedded-hal = { version = "0.2", optional = true } -nb = { version = "1.0", optional = true } -serde_arrays = { version = "0.1.0", optional = true } - -[features] -"all" = [ - "ardupilotmega", - "asluav", - "common", - "development", - "icarous", - "minimal", - "python_array_test", - "standard", - "test", - "ualberta", - "uavionix", - "avssuas", - "cubepilot", -] -"ardupilotmega" = ["common", "icarous", "uavionix"] -"asluav" = ["common"] -"avssuas" = ["common"] -"development" = ["common"] -"matrixpilot" = ["common"] -"minimal" = [] -"paparazzi" = ["common"] -"python_array_test" = ["common"] -"slugs" = ["common"] -"standard" = ["common"] -"test" = [] -"ualberta" = ["common"] -"uavionix" = ["common"] -"icarous" = [] -"common" = [] -"cubepilot" = ["common"] - -"all-dialects" = [ - "ardupilotmega", - "asluav", - "avssuas", - "development", - "matrixpilot", - "minimal", - "paparazzi", - "python_array_test", - "slugs", - "standard", - "test", - "ualberta", - "uavionix", - "icarous", - "common", - "cubepilot", -] - -"format-generated-code" = [] -"emit-description" = [] -"emit-extensions" = [] -"std" = ["byteorder/std"] -"udp" = [] -"tcp" = [] -"direct-serial" = [] -"embedded" = ["embedded-hal", "nb"] -"serde" = ["dep:serde", "dep:serde_arrays"] -default = ["std", "tcp", "udp", "direct-serial", "serial", "serde", "ardupilotmega"] - -# build with all features on docs.rs so that users viewing documentation -# can see everything -[package.metadata.docs.rs] -features = ["default", "all-dialects", "emit-description", "emit-extensions", "format-generated-code"] diff --git a/build/main.rs b/build/main.rs deleted file mode 100644 index 6c14eea2c8..0000000000 --- a/build/main.rs +++ /dev/null @@ -1,101 +0,0 @@ -#![recursion_limit = "256"] - -mod binder; -mod parser; -mod util; - -use crate::util::to_module_name; -use std::env; -use std::ffi::OsStr; -use std::fs::{read_dir, File}; -use std::io::BufWriter; -use std::path::{Path, PathBuf}; -use std::process::Command; - -pub fn main() { - let src_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - - // Update and init submodule - if let Err(error) = Command::new("git") - .arg("submodule") - .arg("update") - .arg("--init") - .current_dir(src_dir) - .status() - { - eprintln!("{error}"); - } - - // find & apply patches to XML definitions to avoid crashes - let mut patch_dir = src_dir.to_path_buf(); - patch_dir.push("build/patches"); - let mut mavlink_dir = src_dir.to_path_buf(); - mavlink_dir.push("mavlink"); - - if let Ok(dir) = read_dir(patch_dir) { - for entry in dir.flatten() { - if let Err(error) = Command::new("git") - .arg("apply") - .arg(entry.path().as_os_str()) - .current_dir(&mavlink_dir) - .status() - { - eprintln!("{error}"); - } - } - } - - let mut definitions_dir = src_dir.to_path_buf(); - definitions_dir.push("mavlink/message_definitions/v1.0"); - - let out_dir = env::var("OUT_DIR").unwrap(); - - let mut modules = vec![]; - - for entry in read_dir(&definitions_dir).expect("could not read definitions directory") { - let entry = entry.expect("could not read directory entry"); - - let definition_file = entry.file_name(); - let module_name = to_module_name(&definition_file); - - let mut definition_rs = PathBuf::from(&module_name); - definition_rs.set_extension("rs"); - - modules.push(module_name); - - let dest_path = Path::new(&out_dir).join(definition_rs); - let mut outf = BufWriter::new(File::create(&dest_path).unwrap()); - - // generate code - parser::generate( - &definitions_dir, - &definition_file.into_string().unwrap(), - &mut outf, - ); - dbg_format_code(&out_dir, &dest_path); - - // Re-run build if definition file changes - println!("cargo:rerun-if-changed={}", entry.path().to_string_lossy()); - } - - // output mod.rs - { - let dest_path = Path::new(&out_dir).join("mod.rs"); - let mut outf = File::create(&dest_path).unwrap(); - - // generate code - binder::generate(modules, &mut outf); - dbg_format_code(out_dir, dest_path); - } -} - -#[cfg(feature = "format-generated-code")] -fn dbg_format_code(cwd: impl AsRef, path: impl AsRef) { - if let Err(error) = Command::new("rustfmt").arg(path).current_dir(cwd).status() { - eprintln!("{error}"); - } -} - -// Does nothing -#[cfg(not(feature = "format-generated-code"))] -fn dbg_format_code(_: impl AsRef, _: impl AsRef) {} diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml new file mode 100644 index 0000000000..a1a6930964 --- /dev/null +++ b/mavlink-bindgen/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "mavlink-bindgen" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +crc-any = { workspace = true, default-features = false } +quick-xml = "0.26" +quote = "1" +proc-macro2 = "1.0.43" +lazy_static = "1.2.0" +serde = { version = "1.0.115", optional = true, features = ["derive"] } +clap = { version = "4.0", features = ["derive"] } +thiserror = "1.0.56" diff --git a/build/binder.rs b/mavlink-bindgen/src/binder.rs similarity index 91% rename from build/binder.rs rename to mavlink-bindgen/src/binder.rs index 099ef24e9b..b9a911cc1c 100644 --- a/build/binder.rs +++ b/mavlink-bindgen/src/binder.rs @@ -1,7 +1,7 @@ use quote::{format_ident, quote}; use std::io::Write; -pub fn generate(modules: Vec, out: &mut W) { +pub fn generate(modules: Vec<&str>, out: &mut W) { let modules_tokens = modules.into_iter().map(|module| { let module_ident = format_ident!("{}", module); diff --git a/mavlink-bindgen/src/error.rs b/mavlink-bindgen/src/error.rs new file mode 100644 index 0000000000..fec283634b --- /dev/null +++ b/mavlink-bindgen/src/error.rs @@ -0,0 +1,23 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum BindGenError { + /// Represents a failure to read the MAVLink definitions directory. + #[error("Could not read definitions directory {path}")] + CouldNotReadDefinitionsDirectory { + source: std::io::Error, + path: std::path::PathBuf, + }, + /// Represents a failure to read a directory entry in the MAVLink definitions directory. + #[error("Could not read MAVLink definitions directory entry {path}")] + CouldNotReadDirectoryEntryInDefinitionsDirectory { + source: std::io::Error, + path: std::path::PathBuf, + }, + /// Represents a failure to create a Rust file for the generated MAVLink bindings. + #[error("Could not create Rust bindings file {dest_path}")] + CouldNotCreateRustBindingsFile { + source: std::io::Error, + dest_path: std::path::PathBuf, + }, +} diff --git a/mavlink-bindgen/src/lib.rs b/mavlink-bindgen/src/lib.rs new file mode 100644 index 0000000000..da3145bed3 --- /dev/null +++ b/mavlink-bindgen/src/lib.rs @@ -0,0 +1,125 @@ +use crate::error::BindGenError; +use std::fs::{read_dir, File}; +use std::io::BufWriter; +use std::ops::Deref; +use std::path::{Path, PathBuf}; +use std::process::Command; + +pub mod binder; +pub mod error; +pub mod parser; +mod util; + +#[derive(Debug)] +pub struct GeneratedBinding { + pub module_name: String, + pub mavlink_xml: PathBuf, + pub rust_module: PathBuf, +} + +#[derive(Debug)] +pub struct GeneratedBindings { + pub bindings: Vec, + pub mod_rs: PathBuf, +} + +pub fn generate, P2: AsRef>( + definitions_dir: P1, + destination_dir: P2, +) -> Result { + _generate(definitions_dir.as_ref(), destination_dir.as_ref()) +} + +fn _generate( + definitions_dir: &Path, + destination_dir: &Path, +) -> Result { + let mut bindings = vec![]; + + for entry_maybe in read_dir(&definitions_dir).map_err(|source| { + BindGenError::CouldNotReadDefinitionsDirectory { + source, + path: definitions_dir.to_path_buf(), + } + })? { + let entry = entry_maybe.map_err(|source| { + BindGenError::CouldNotReadDirectoryEntryInDefinitionsDirectory { + source, + path: definitions_dir.to_path_buf(), + } + })?; + + let definition_file = PathBuf::from(entry.file_name()); + let module_name = util::to_module_name(&definition_file); + + let mut definition_rs = PathBuf::from(&module_name); + definition_rs.set_extension("rs"); + + let dest_path = destination_dir.join(definition_rs); + let mut outf = BufWriter::new(File::create(&dest_path).map_err(|source| { + BindGenError::CouldNotCreateRustBindingsFile { + source, + dest_path: dest_path.clone(), + } + })?); + + // generate code + parser::generate(&definitions_dir, &definition_file, &mut outf); + + bindings.push(GeneratedBinding { + module_name, + mavlink_xml: definition_file, + rust_module: dest_path, + }); + } + + // output mod.rs + { + let dest_path = destination_dir.join("mod.rs"); + let mut outf = File::create(&dest_path).map_err(|source| { + BindGenError::CouldNotCreateRustBindingsFile { + source, + dest_path: dest_path.clone(), + } + })?; + + // generate code + binder::generate( + bindings + .iter() + .map(|binding| binding.module_name.deref()) + .collect(), + &mut outf, + ); + + Ok(GeneratedBindings { + bindings, + mod_rs: dest_path, + }) + } +} + +pub fn format_generated_code(result: &GeneratedBindings) { + if let Err(error) = Command::new("rustfmt") + .args( + result + .bindings + .iter() + .map(|binding| binding.rust_module.clone()), + ) + .arg(result.mod_rs.clone()) + .status() + { + eprintln!("{error}"); + } +} + +pub fn emit_cargo_build_messages(result: &GeneratedBindings) { + for binding in &result.bindings { + // Re-run build if definition file changes + println!( + "cargo:rerun-if-changed={}", + binding.rust_module.to_string_lossy() + ); + } +} diff --git a/mavlink-bindgen/src/main.rs b/mavlink-bindgen/src/main.rs new file mode 100644 index 0000000000..56076853e1 --- /dev/null +++ b/mavlink-bindgen/src/main.rs @@ -0,0 +1,30 @@ +#![recursion_limit = "256"] + +use std::path::PathBuf; + +use clap::Parser; +use mavlink_bindgen::{emit_cargo_build_messages, format_generated_code, generate}; + +#[derive(Parser)] +struct Cli { + definitions_dir: PathBuf, + destination_dir: PathBuf, + #[arg(long)] + format_generated_code: bool, + #[arg(long)] + emit_cargo_build_messages: bool, +} + +pub fn main() { + let args = Cli::parse(); + let result = generate(args.definitions_dir, args.destination_dir) + .expect("failed to generate MAVLink Rust bindings"); + + if args.format_generated_code { + format_generated_code(&result); + } + + if args.emit_cargo_build_messages { + emit_cargo_build_messages(&result); + } +} diff --git a/build/parser.rs b/mavlink-bindgen/src/parser.rs similarity index 98% rename from build/parser.rs rename to mavlink-bindgen/src/parser.rs index a0618c5319..0d273e663d 100644 --- a/build/parser.rs +++ b/mavlink-bindgen/src/parser.rs @@ -140,7 +140,6 @@ impl MavProfile { quote! { #comment - use crate::MavlinkVersion; #[allow(unused_imports)] use num_derive::FromPrimitive; #[allow(unused_imports)] @@ -152,7 +151,7 @@ impl MavProfile { #[allow(unused_imports)] use bitflags::bitflags; - use crate::{Message, MessageData, error::*, bytes::Bytes, bytes_mut::BytesMut}; + use mavlink_core::{MavlinkVersion, Message, MessageData, bytes::Bytes, bytes_mut::BytesMut}; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize}; @@ -195,11 +194,11 @@ impl MavProfile { let id_width = format_ident!("u32"); quote! { - fn parse(version: MavlinkVersion, id: #id_width, payload: &[u8]) -> Result { + fn parse(version: MavlinkVersion, id: #id_width, payload: &[u8]) -> Result { match id { #(#structs::ID => #structs::deser(version, payload).map(Self::#enums),)* _ => { - Err(ParserError::UnknownMessage { id }) + Err(::mavlink_core::error::ParserError::UnknownMessage { id }) }, } } @@ -506,7 +505,7 @@ impl MavMessage { #(#ser_vars)* if matches!(version, MavlinkVersion::V2) { let len = __tmp.len(); - crate::remove_trailing_zeroes(&bytes[..len]) + ::mavlink_core::utils::remove_trailing_zeroes(&bytes[..len]) } else { __tmp.len() } @@ -606,7 +605,7 @@ impl MavMessage { const EXTRA_CRC: u8 = #extra_crc; const ENCODED_LEN: usize = #msg_encoded_len; - fn deser(_version: MavlinkVersion, __input: &[u8]) -> Result { + fn deser(_version: MavlinkVersion, __input: &[u8]) -> Result { #deser_vars } @@ -718,7 +717,7 @@ impl MavField { quote! { #tmp #name = #enum_name_ident::from_bits(tmp & #enum_name_ident::all().bits()) - .ok_or(ParserError::InvalidFlag { flag_type: #enum_name, value: tmp as u32 })?; + .ok_or(::mavlink_core::error::ParserError::InvalidFlag { flag_type: #enum_name, value: tmp as u32 })?; } } else { panic!("Display option not implemented"); @@ -730,7 +729,7 @@ impl MavField { quote!( #tmp #name = FromPrimitive::#val(tmp) - .ok_or(ParserError::InvalidEnum { enum_type: #enum_name, value: tmp as u32 })?; + .ok_or(::mavlink_core::error::ParserError::InvalidEnum { enum_type: #enum_name, value: tmp as u32 })?; ) } } else { @@ -1032,7 +1031,7 @@ fn is_valid_parent(p: Option, s: MavXmlElement) -> bool { pub fn parse_profile( definitions_dir: &Path, - definition_file: &String, + definition_file: &Path, parsed_files: &mut HashSet, ) -> MavProfile { let in_path = Path::new(&definitions_dir).join(definition_file); @@ -1045,7 +1044,7 @@ pub fn parse_profile( let mut message = MavMessage::default(); let mut mavenum = MavEnum::default(); let mut entry = MavEnumEntry::default(); - let mut include = String::new(); + let mut include = PathBuf::new(); let mut paramid: Option = None; let mut xml_filter = MavXmlFilter::default(); @@ -1283,7 +1282,7 @@ pub fn parse_profile( } } (Some(&Include), Some(&Mavlink)) => { - include = s.replace('\n', ""); + include = PathBuf::from(s.replace('\n', "")); } (Some(&Version), Some(&Mavlink)) => { eprintln!("TODO: version {s:?}"); @@ -1360,7 +1359,7 @@ pub fn parse_profile( /// Generate protobuf represenation of mavlink message set /// Generate rust representation of mavlink message set with appropriate conversion methods -pub fn generate(definitions_dir: &Path, definition_file: &String, output_rust: &mut W) { +pub fn generate(definitions_dir: &Path, definition_file: &Path, output_rust: &mut W) { let mut parsed_files: HashSet = HashSet::new(); let profile = parse_profile(definitions_dir, definition_file, &mut parsed_files); diff --git a/build/util.rs b/mavlink-bindgen/src/util.rs similarity index 100% rename from build/util.rs rename to mavlink-bindgen/src/util.rs diff --git a/mavlink-core/Cargo.toml b/mavlink-core/Cargo.toml new file mode 100644 index 0000000000..17940867be --- /dev/null +++ b/mavlink-core/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "mavlink-core" +version = "0.12.2" +authors = ["Todd Stellanova", "Michal Podhradsky", "Kevin Mehall", "Tim Ryan", "Patrick José Pereira", "Ibiyemi Abiodun"] +description = "Implements the MAVLink data interchange format for UAVs." +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/mavlink/rust-mavlink" +edition = "2018" +rust-version = "1.65.0" + +[dependencies] +crc-any = { workspace = true, default-features = false } +byteorder = { workspace = true, default-features = false } +embedded-hal = { version = "0.2", optional = true } +nb = { version = "1.0", optional = true } +serde = { version = "1.0.115", optional = true, features = ["derive"] } +serde_arrays = { version = "0.1.0", optional = true } +serial = { version = "0.4", optional = true } + +[features] +"std" = ["byteorder/std"] +"udp" = [] +"tcp" = [] +"direct-serial" = ["serial"] +"embedded" = ["embedded-hal", "nb"] +"serde" = ["dep:serde", "dep:serde_arrays"] +default = ["std", "tcp", "udp", "direct-serial", "serde"] diff --git a/src/bytes.rs b/mavlink-core/src/bytes.rs similarity index 100% rename from src/bytes.rs rename to mavlink-core/src/bytes.rs diff --git a/src/bytes_mut.rs b/mavlink-core/src/bytes_mut.rs similarity index 100% rename from src/bytes_mut.rs rename to mavlink-core/src/bytes_mut.rs diff --git a/src/connection/direct_serial.rs b/mavlink-core/src/connection/direct_serial.rs similarity index 100% rename from src/connection/direct_serial.rs rename to mavlink-core/src/connection/direct_serial.rs diff --git a/src/connection/file.rs b/mavlink-core/src/connection/file.rs similarity index 100% rename from src/connection/file.rs rename to mavlink-core/src/connection/file.rs diff --git a/src/connection/mod.rs b/mavlink-core/src/connection/mod.rs similarity index 100% rename from src/connection/mod.rs rename to mavlink-core/src/connection/mod.rs diff --git a/src/connection/tcp.rs b/mavlink-core/src/connection/tcp.rs similarity index 100% rename from src/connection/tcp.rs rename to mavlink-core/src/connection/tcp.rs diff --git a/src/connection/udp.rs b/mavlink-core/src/connection/udp.rs similarity index 100% rename from src/connection/udp.rs rename to mavlink-core/src/connection/udp.rs diff --git a/src/embedded.rs b/mavlink-core/src/embedded.rs similarity index 100% rename from src/embedded.rs rename to mavlink-core/src/embedded.rs diff --git a/src/error.rs b/mavlink-core/src/error.rs similarity index 100% rename from src/error.rs rename to mavlink-core/src/error.rs diff --git a/src/lib.rs b/mavlink-core/src/lib.rs similarity index 96% rename from src/lib.rs rename to mavlink-core/src/lib.rs index 409a96a4b0..783a4c7783 100644 --- a/src/lib.rs +++ b/mavlink-core/src/lib.rs @@ -30,12 +30,8 @@ use std::io::{Read, Write}; #[cfg(feature = "std")] use byteorder::ReadBytesExt; -#[cfg(feature = "std")] -mod connection; -#[cfg(feature = "std")] -pub use self::connection::{connect, MavConnection}; -mod utils; +pub mod utils; #[allow(unused_imports)] use utils::{remove_trailing_zeroes, RustDefault}; @@ -46,12 +42,13 @@ use crate::{bytes::Bytes, error::ParserError}; use crc_any::CRCu16; -// include generate definitions -include!(concat!(env!("OUT_DIR"), "/mod.rs")); - pub mod bytes; pub mod bytes_mut; pub mod error; +#[cfg(feature = "std")] +mod connection; +#[cfg(feature = "std")] +pub use self::connection::{connect, MavConnection}; #[cfg(feature = "embedded")] pub mod embedded; @@ -61,8 +58,8 @@ use embedded::{Read, Write}; pub const MAX_FRAME_SIZE: usize = 280; pub trait Message -where - Self: Sized, + where + Self: Sized, { fn message_id(&self) -> u32; fn message_name(&self) -> &'static str; @@ -306,9 +303,9 @@ impl MAVLinkV1MessageRaw { let payload_length: usize = self.payload_length().into(); self.checksum() == calculate_crc( - &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], - M::extra_crc(self.message_id().into()), - ) + &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], + M::extra_crc(self.message_id().into()), + ) } pub fn raw_bytes(&self) -> &[u8] { @@ -400,17 +397,17 @@ pub fn read_v1_msg( u32::from(message.message_id()), message.payload(), ) - .map(|msg| { - ( - MavHeader { - sequence: message.sequence(), - system_id: message.system_id(), - component_id: message.component_id(), - }, - msg, - ) - }) - .map_err(|err| err.into()); + .map(|msg| { + ( + MavHeader { + sequence: message.sequence(), + system_id: message.system_id(), + component_id: message.component_id(), + }, + msg, + ) + }) + .map_err(|err| err.into()); } } @@ -513,9 +510,9 @@ impl MAVLinkV2MessageRaw { let payload_length: usize = self.payload_length().into(); self.checksum() == calculate_crc( - &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], - M::extra_crc(self.message_id()), - ) + &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], + M::extra_crc(self.message_id()), + ) } pub fn raw_bytes(&self) -> &[u8] { diff --git a/src/utils.rs b/mavlink-core/src/utils.rs similarity index 97% rename from src/utils.rs rename to mavlink-core/src/utils.rs index 486c2ea0bb..c0516c154e 100644 --- a/src/utils.rs +++ b/mavlink-core/src/utils.rs @@ -4,7 +4,7 @@ /// /// There must always be at least one remaining byte even if it is a /// zero byte. -pub(crate) fn remove_trailing_zeroes(data: &[u8]) -> usize { +pub fn remove_trailing_zeroes(data: &[u8]) -> usize { let mut len = data.len(); for b in data[1..].iter().rev() { diff --git a/mavlink/Cargo.toml b/mavlink/Cargo.toml new file mode 100644 index 0000000000..984edaa6ac --- /dev/null +++ b/mavlink/Cargo.toml @@ -0,0 +1,96 @@ + +[package] +name = "mavlink" +version = "0.12.2" +authors = ["Todd Stellanova", "Michal Podhradsky", "Kevin Mehall", "Tim Ryan", "Patrick José Pereira", "Ibiyemi Abiodun"] +build = "build/main.rs" +description = "Implements the MAVLink data interchange format for UAVs." +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/mavlink/rust-mavlink" +edition = "2018" +rust-version = "1.65.0" + +[build-dependencies] +mavlink-bindgen = { path = "../mavlink-bindgen" } + +[[example]] +name = "mavlink-dump" +path = "examples/mavlink-dump/src/main.rs" +required-features = ["ardupilotmega"] + +[dependencies] +mavlink-core = { path = "../mavlink-core" } +num-traits = { workspace = true, default-features = false } +num-derive = { workspace = true } +bitflags = { workspace = true } +serde = { version = "1.0.115", optional = true, features = ["derive"] } +serde_arrays = { version = "0.1.0", optional = true } + +[features] +"all" = [ + "ardupilotmega", + "asluav", + "common", + "development", + "icarous", + "minimal", + "python_array_test", + "standard", + "test", + "ualberta", + "uavionix", + "avssuas", + "cubepilot", +] +"ardupilotmega" = ["common", "icarous", "uavionix"] +"asluav" = ["common"] +"avssuas" = ["common"] +"development" = ["common"] +"matrixpilot" = ["common"] +"minimal" = [] +"paparazzi" = ["common"] +"python_array_test" = ["common"] +"slugs" = ["common"] +"standard" = ["common"] +"test" = [] +"ualberta" = ["common"] +"uavionix" = ["common"] +"icarous" = [] +"common" = [] +"cubepilot" = ["common"] + +"all-dialects" = [ + "ardupilotmega", + "asluav", + "avssuas", + "development", + "matrixpilot", + "minimal", + "paparazzi", + "python_array_test", + "slugs", + "standard", + "test", + "ualberta", + "uavionix", + "icarous", + "common", + "cubepilot", +] + +"format-generated-code" = [] +"emit-description" = [] +"emit-extensions" = [] +"std" = ["mavlink-core/std"] +"udp" = ["mavlink-core/udp"] +"tcp" = ["mavlink-core/tcp"] +"direct-serial" = ["mavlink-core/direct-serial"] +"embedded" = ["mavlink-core/embedded"] +"serde" = ["mavlink-core/serde", "dep:serde", "dep:serde_arrays"] +default = ["std", "tcp", "udp", "direct-serial", "serde", "ardupilotmega"] + +# build with all features on docs.rs so that users viewing documentation +# can see everything +[package.metadata.docs.rs] +features = ["default", "all-dialects", "emit-description", "emit-extensions", "format-generated-code"] diff --git a/mavlink/build/main.rs b/mavlink/build/main.rs new file mode 100644 index 0000000000..383df5edbf --- /dev/null +++ b/mavlink/build/main.rs @@ -0,0 +1,53 @@ +#![recursion_limit = "256"] + +use std::env; +use std::fs::read_dir; +use std::path::Path; +use std::process::Command; +use mavlink_bindgen; + +pub fn main() { + let src_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + + // Update and init submodule + if let Err(error) = Command::new("git") + .arg("submodule") + .arg("update") + .arg("--init") + .current_dir(src_dir) + .status() + { + eprintln!("{error}"); + } + + // find & apply patches to XML definitions to avoid crashes + let mut patch_dir = src_dir.to_path_buf(); + patch_dir.push("build/patches"); + let mut mavlink_dir = src_dir.to_path_buf(); + mavlink_dir.push("mavlink"); + + if let Ok(dir) = read_dir(patch_dir) { + for entry in dir.flatten() { + if let Err(error) = Command::new("git") + .arg("apply") + .arg(entry.path().as_os_str()) + .current_dir(&mavlink_dir) + .status() + { + eprintln!("{error}"); + } + } + } + + let mut definitions_dir = src_dir.to_path_buf(); + definitions_dir.push("mavlink/message_definitions/v1.0"); + + let out_dir = env::var("OUT_DIR").unwrap(); + + let result = mavlink_bindgen::generate(definitions_dir, out_dir).expect("Failed to generate Rust MAVLink bindings"); + + #[cfg(feature = "format-generated-code")] + mavlink_bindgen::format_generated_code(&result); + + mavlink_bindgen::emit_cargo_build_messages(&result); +} diff --git a/examples/embedded/.cargo/config.toml b/mavlink/examples/embedded/.cargo/config.toml similarity index 100% rename from examples/embedded/.cargo/config.toml rename to mavlink/examples/embedded/.cargo/config.toml diff --git a/examples/embedded/Cargo.toml b/mavlink/examples/embedded/Cargo.toml similarity index 100% rename from examples/embedded/Cargo.toml rename to mavlink/examples/embedded/Cargo.toml diff --git a/examples/embedded/README.md b/mavlink/examples/embedded/README.md similarity index 100% rename from examples/embedded/README.md rename to mavlink/examples/embedded/README.md diff --git a/examples/embedded/memory.x b/mavlink/examples/embedded/memory.x similarity index 100% rename from examples/embedded/memory.x rename to mavlink/examples/embedded/memory.x diff --git a/examples/embedded/src/main.rs b/mavlink/examples/embedded/src/main.rs similarity index 100% rename from examples/embedded/src/main.rs rename to mavlink/examples/embedded/src/main.rs diff --git a/examples/mavlink-dump/Cargo.toml b/mavlink/examples/mavlink-dump/Cargo.toml similarity index 100% rename from examples/mavlink-dump/Cargo.toml rename to mavlink/examples/mavlink-dump/Cargo.toml diff --git a/examples/mavlink-dump/src/main.rs b/mavlink/examples/mavlink-dump/src/main.rs similarity index 100% rename from examples/mavlink-dump/src/main.rs rename to mavlink/examples/mavlink-dump/src/main.rs diff --git a/mavlink b/mavlink/mavlink similarity index 100% rename from mavlink rename to mavlink/mavlink diff --git a/rustfmt.toml b/mavlink/rustfmt.toml similarity index 100% rename from rustfmt.toml rename to mavlink/rustfmt.toml diff --git a/mavlink/src/lib.rs b/mavlink/src/lib.rs new file mode 100644 index 0000000000..8bea722eea --- /dev/null +++ b/mavlink/src/lib.rs @@ -0,0 +1,4 @@ +// include generate definitions +include!(concat!(env!("OUT_DIR"), "/mod.rs")); + +pub use mavlink_core::*; diff --git a/tests/direct_serial_tests.rs b/mavlink/tests/direct_serial_tests.rs similarity index 100% rename from tests/direct_serial_tests.rs rename to mavlink/tests/direct_serial_tests.rs diff --git a/tests/encode_decode_tests.rs b/mavlink/tests/encode_decode_tests.rs similarity index 100% rename from tests/encode_decode_tests.rs rename to mavlink/tests/encode_decode_tests.rs diff --git a/tests/helper_tests.rs b/mavlink/tests/helper_tests.rs similarity index 100% rename from tests/helper_tests.rs rename to mavlink/tests/helper_tests.rs diff --git a/tests/log.tlog b/mavlink/tests/log.tlog similarity index 100% rename from tests/log.tlog rename to mavlink/tests/log.tlog diff --git a/tests/mav_frame_tests.rs b/mavlink/tests/mav_frame_tests.rs similarity index 100% rename from tests/mav_frame_tests.rs rename to mavlink/tests/mav_frame_tests.rs diff --git a/tests/process_log_files.rs b/mavlink/tests/process_log_files.rs similarity index 100% rename from tests/process_log_files.rs rename to mavlink/tests/process_log_files.rs diff --git a/tests/tcp_loopback_tests.rs b/mavlink/tests/tcp_loopback_tests.rs similarity index 100% rename from tests/tcp_loopback_tests.rs rename to mavlink/tests/tcp_loopback_tests.rs diff --git a/tests/test_shared/mod.rs b/mavlink/tests/test_shared/mod.rs similarity index 100% rename from tests/test_shared/mod.rs rename to mavlink/tests/test_shared/mod.rs diff --git a/tests/udp_loopback_tests.rs b/mavlink/tests/udp_loopback_tests.rs similarity index 100% rename from tests/udp_loopback_tests.rs rename to mavlink/tests/udp_loopback_tests.rs diff --git a/tests/v1_encode_decode_tests.rs b/mavlink/tests/v1_encode_decode_tests.rs similarity index 100% rename from tests/v1_encode_decode_tests.rs rename to mavlink/tests/v1_encode_decode_tests.rs diff --git a/tests/v2_encode_decode_tests.rs b/mavlink/tests/v2_encode_decode_tests.rs similarity index 100% rename from tests/v2_encode_decode_tests.rs rename to mavlink/tests/v2_encode_decode_tests.rs From ac556e19a28b2d04d8f680ca8d5cdb082c8e5e54 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 18:43:05 +1100 Subject: [PATCH 02/20] run GitHub checks From 18612a2bf07c78d0a5ffe7841a2de644390965d3 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 18:43:57 +1100 Subject: [PATCH 03/20] reformat --- mavlink-core/src/lib.rs | 41 ++++++++++++++++++++--------------------- mavlink/build/main.rs | 5 +++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/mavlink-core/src/lib.rs b/mavlink-core/src/lib.rs index 783a4c7783..c5f86e4ac1 100644 --- a/mavlink-core/src/lib.rs +++ b/mavlink-core/src/lib.rs @@ -30,7 +30,6 @@ use std::io::{Read, Write}; #[cfg(feature = "std")] use byteorder::ReadBytesExt; - pub mod utils; #[allow(unused_imports)] use utils::{remove_trailing_zeroes, RustDefault}; @@ -44,9 +43,9 @@ use crc_any::CRCu16; pub mod bytes; pub mod bytes_mut; -pub mod error; #[cfg(feature = "std")] mod connection; +pub mod error; #[cfg(feature = "std")] pub use self::connection::{connect, MavConnection}; @@ -58,8 +57,8 @@ use embedded::{Read, Write}; pub const MAX_FRAME_SIZE: usize = 280; pub trait Message - where - Self: Sized, +where + Self: Sized, { fn message_id(&self) -> u32; fn message_name(&self) -> &'static str; @@ -303,9 +302,9 @@ impl MAVLinkV1MessageRaw { let payload_length: usize = self.payload_length().into(); self.checksum() == calculate_crc( - &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], - M::extra_crc(self.message_id().into()), - ) + &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], + M::extra_crc(self.message_id().into()), + ) } pub fn raw_bytes(&self) -> &[u8] { @@ -397,17 +396,17 @@ pub fn read_v1_msg( u32::from(message.message_id()), message.payload(), ) - .map(|msg| { - ( - MavHeader { - sequence: message.sequence(), - system_id: message.system_id(), - component_id: message.component_id(), - }, - msg, - ) - }) - .map_err(|err| err.into()); + .map(|msg| { + ( + MavHeader { + sequence: message.sequence(), + system_id: message.system_id(), + component_id: message.component_id(), + }, + msg, + ) + }) + .map_err(|err| err.into()); } } @@ -510,9 +509,9 @@ impl MAVLinkV2MessageRaw { let payload_length: usize = self.payload_length().into(); self.checksum() == calculate_crc( - &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], - M::extra_crc(self.message_id()), - ) + &self.0[1..(1 + Self::HEADER_SIZE + payload_length)], + M::extra_crc(self.message_id()), + ) } pub fn raw_bytes(&self) -> &[u8] { diff --git a/mavlink/build/main.rs b/mavlink/build/main.rs index 383df5edbf..fdd6174289 100644 --- a/mavlink/build/main.rs +++ b/mavlink/build/main.rs @@ -1,10 +1,10 @@ #![recursion_limit = "256"] +use mavlink_bindgen; use std::env; use std::fs::read_dir; use std::path::Path; use std::process::Command; -use mavlink_bindgen; pub fn main() { let src_dir = Path::new(env!("CARGO_MANIFEST_DIR")); @@ -44,7 +44,8 @@ pub fn main() { let out_dir = env::var("OUT_DIR").unwrap(); - let result = mavlink_bindgen::generate(definitions_dir, out_dir).expect("Failed to generate Rust MAVLink bindings"); + let result = mavlink_bindgen::generate(definitions_dir, out_dir) + .expect("Failed to generate Rust MAVLink bindings"); #[cfg(feature = "format-generated-code")] mavlink_bindgen::format_generated_code(&result); From 8c0d9cd820c05790290197141edd28f9bc324b24 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 19:21:13 +1100 Subject: [PATCH 04/20] attempt to fix cross compile test --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9011cc0c69..6b55972120 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,6 +51,10 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: 1.65.0 + - uses: actions-rs/cargo@v1 + with: + command: install cross + args: --locked - uses: actions-rs/cargo@v1 with: use-cross: true From 491728e7c611eb7ece89e60837149742e52b2f6c Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 19:22:41 +1100 Subject: [PATCH 05/20] attempt to install cross --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6b55972120..db42ae524e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,8 +53,8 @@ jobs: toolchain: 1.65.0 - uses: actions-rs/cargo@v1 with: - command: install cross - args: --locked + command: install + args: cross --locked - uses: actions-rs/cargo@v1 with: use-cross: true From e789af8756525556aa2b9da4c396be9a53aaf8d7 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 19:34:15 +1100 Subject: [PATCH 06/20] Downgrade clap to support MSRV 1.65.0 --- mavlink-bindgen/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index a1a6930964..1a9498f523 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -12,5 +12,5 @@ quote = "1" proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } -clap = { version = "4.0", features = ["derive"] } +clap = { version = "~4.3.24", features = ["derive"] } thiserror = "1.0.56" From 0ee3bb9162943aeb2140eda88af948790fee3d6d Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 19:45:13 +1100 Subject: [PATCH 07/20] Downgrade clap_lex to support MSRV 1.65.0 --- mavlink-bindgen/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index 1a9498f523..bf66db81e6 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -13,4 +13,6 @@ proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } clap = { version = "~4.3.24", features = ["derive"] } +# Required to support MSRV 1.65.0 +clap_lex = { version = "=0.5.0" } thiserror = "1.0.56" From 1479ea1430ceea051b61da63f1f2295afa1b7e8c Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 19:53:09 +1100 Subject: [PATCH 08/20] Another downgrade --- mavlink-bindgen/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index bf66db81e6..41fcdbb83e 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -13,6 +13,8 @@ proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } clap = { version = "~4.3.24", features = ["derive"] } +thiserror = "1.0.56" + # Required to support MSRV 1.65.0 clap_lex = { version = "=0.5.0" } -thiserror = "1.0.56" +anstream = { version = "=0.3.0" } From 054b7cc8eb3f2cde8189e35c02992ce5f7a73eed Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 20:01:27 +1100 Subject: [PATCH 09/20] downgrade anstyle --- .idea/workspace.xml | 126 +++++++++++++++++++++++++++++++++++++ mavlink-bindgen/Cargo.toml | 1 + 2 files changed, 127 insertions(+) create mode 100644 .idea/workspace.xml diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..782ec503db --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1707604355173 + + + + + + \ No newline at end of file diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index 41fcdbb83e..12096562f7 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -18,3 +18,4 @@ thiserror = "1.0.56" # Required to support MSRV 1.65.0 clap_lex = { version = "=0.5.0" } anstream = { version = "=0.3.0" } +anstyle = { version = "=1.0.2" } \ No newline at end of file From eb49850c406558b49fd178d1c2dda1722da97f9f Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 20:19:28 +1100 Subject: [PATCH 10/20] Simplify support for MSRV 1.65.0 --- mavlink-bindgen/Cargo.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index 12096562f7..ad1663e7ff 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -12,10 +12,5 @@ quote = "1" proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } -clap = { version = "~4.3.24", features = ["derive"] } +clap = { version = "~4.3.24", default-features = false, features = ["std", "help", "usage", "error-context", "derive"] } thiserror = "1.0.56" - -# Required to support MSRV 1.65.0 -clap_lex = { version = "=0.5.0" } -anstream = { version = "=0.3.0" } -anstyle = { version = "=1.0.2" } \ No newline at end of file From 45be934e75492e52ef200d326289325c1c4fe54c Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 20:32:28 +1100 Subject: [PATCH 11/20] Hopefully this works --- mavlink-bindgen/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index ad1663e7ff..a3bbb4b903 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -14,3 +14,7 @@ lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } clap = { version = "~4.3.24", default-features = false, features = ["std", "help", "usage", "error-context", "derive"] } thiserror = "1.0.56" + +# Required to support MSRV 1.65.0 +clap_lex = { version = "=0.5.0" } +anstyle = { version = "=1.0.2" } From 42c7f36c5a48f19a04a3396bc26781d9d06d7d9a Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 21:37:14 +1100 Subject: [PATCH 12/20] fix embedded build --- .idea/workspace.xml | 126 ------------------------------------ mavlink-bindgen/Cargo.toml | 11 +++- mavlink-bindgen/src/cli.rs | 28 ++++++++ mavlink-bindgen/src/main.rs | 31 ++------- mavlink/Cargo.toml | 4 +- 5 files changed, 44 insertions(+), 156 deletions(-) delete mode 100644 .idea/workspace.xml create mode 100644 mavlink-bindgen/src/cli.rs diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 782ec503db..0000000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1707604355173 - - - - - - \ No newline at end of file diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index a3bbb4b903..2a38c32a45 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -12,9 +12,14 @@ quote = "1" proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } -clap = { version = "~4.3.24", default-features = false, features = ["std", "help", "usage", "error-context", "derive"] } +clap = { version = "~4.3.24", optional = true, features = ["derive"] } thiserror = "1.0.56" # Required to support MSRV 1.65.0 -clap_lex = { version = "=0.5.0" } -anstyle = { version = "=1.0.2" } +clap_lex = { version = "=0.5.0", optional=true } +clap_builder = { version = "~4.3.24", optional=true} +anstyle = { version = "=1.0.2", optional=true } + +[features] +cli = ["dep:clap", "dep:clap_lex", "dep:clap_builder", "dep:anstyle"] +default = ["cli"] diff --git a/mavlink-bindgen/src/cli.rs b/mavlink-bindgen/src/cli.rs new file mode 100644 index 0000000000..02eb59038f --- /dev/null +++ b/mavlink-bindgen/src/cli.rs @@ -0,0 +1,28 @@ +use std::path::PathBuf; + +use clap::Parser; +use mavlink_bindgen::{emit_cargo_build_messages, format_generated_code, generate}; + +#[derive(Parser)] +struct Cli { + definitions_dir: PathBuf, + destination_dir: PathBuf, + #[arg(long)] + format_generated_code: bool, + #[arg(long)] + emit_cargo_build_messages: bool, +} + +pub fn main() { + let args = Cli::parse(); + let result = generate(args.definitions_dir, args.destination_dir) + .expect("failed to generate MAVLink Rust bindings"); + + if args.format_generated_code { + format_generated_code(&result); + } + + if args.emit_cargo_build_messages { + emit_cargo_build_messages(&result); + } +} diff --git a/mavlink-bindgen/src/main.rs b/mavlink-bindgen/src/main.rs index 56076853e1..660ba5ec7f 100644 --- a/mavlink-bindgen/src/main.rs +++ b/mavlink-bindgen/src/main.rs @@ -1,30 +1,11 @@ #![recursion_limit = "256"] -use std::path::PathBuf; - -use clap::Parser; -use mavlink_bindgen::{emit_cargo_build_messages, format_generated_code, generate}; - -#[derive(Parser)] -struct Cli { - definitions_dir: PathBuf, - destination_dir: PathBuf, - #[arg(long)] - format_generated_code: bool, - #[arg(long)] - emit_cargo_build_messages: bool, -} +#[cfg(feature = "cli")] +mod cli; pub fn main() { - let args = Cli::parse(); - let result = generate(args.definitions_dir, args.destination_dir) - .expect("failed to generate MAVLink Rust bindings"); - - if args.format_generated_code { - format_generated_code(&result); - } - - if args.emit_cargo_build_messages { - emit_cargo_build_messages(&result); - } + #[cfg(feature = "cli")] + cli::main(); + #[cfg(not(feature = "cli"))] + panic!("Compiled without cli feature"); } diff --git a/mavlink/Cargo.toml b/mavlink/Cargo.toml index 984edaa6ac..728e630a37 100644 --- a/mavlink/Cargo.toml +++ b/mavlink/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" rust-version = "1.65.0" [build-dependencies] -mavlink-bindgen = { path = "../mavlink-bindgen" } +mavlink-bindgen = { path = "../mavlink-bindgen", default-features = false} [[example]] name = "mavlink-dump" @@ -20,7 +20,7 @@ path = "examples/mavlink-dump/src/main.rs" required-features = ["ardupilotmega"] [dependencies] -mavlink-core = { path = "../mavlink-core" } +mavlink-core = { path = "../mavlink-core", default-features = false} num-traits = { workspace = true, default-features = false } num-derive = { workspace = true } bitflags = { workspace = true } From d851c7614120f4c3ce9d5cd8dad7b73635848003 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 21:47:33 +1100 Subject: [PATCH 13/20] Fix build on MSRV --- mavlink-bindgen/Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index 2a38c32a45..7ecbbd2b0f 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -12,14 +12,16 @@ quote = "1" proc-macro2 = "1.0.43" lazy_static = "1.2.0" serde = { version = "1.0.115", optional = true, features = ["derive"] } -clap = { version = "~4.3.24", optional = true, features = ["derive"] } +clap = { version = "~4.3.24", optional = true, default-features =false, features = ["derive", "help", "usage", "error-context"] } thiserror = "1.0.56" # Required to support MSRV 1.65.0 clap_lex = { version = "=0.5.0", optional=true } clap_builder = { version = "~4.3.24", optional=true} anstyle = { version = "=1.0.2", optional=true } +anstyle-query = { version = "=1.0.0", optional=true } +anstyle-parse = { version = "=0.2.1", optional=true } [features] -cli = ["dep:clap", "dep:clap_lex", "dep:clap_builder", "dep:anstyle"] +cli = ["dep:clap", "dep:clap_lex", "dep:clap_builder", "dep:anstyle", "dep:anstyle-query", "dep:anstyle-parse"] default = ["cli"] From 4713ca41f798fea6f00ef0c441f9ace35733fc22 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 22:08:58 +1100 Subject: [PATCH 14/20] Make cli feature not default --- mavlink-bindgen/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml index 7ecbbd2b0f..e5f3ee534b 100644 --- a/mavlink-bindgen/Cargo.toml +++ b/mavlink-bindgen/Cargo.toml @@ -24,4 +24,3 @@ anstyle-parse = { version = "=0.2.1", optional=true } [features] cli = ["dep:clap", "dep:clap_lex", "dep:clap_builder", "dep:anstyle", "dep:anstyle-query", "dep:anstyle-parse"] -default = ["cli"] From 9a8b1d8bc0cf3511712d6bba0d42b0fcc309476a Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 23:02:07 +1100 Subject: [PATCH 15/20] Only build the mavlink package in tests. The mavlink-bindgen crate does not itself need to run on embedded hardware --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index db42ae524e..cda9bab153 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -107,7 +107,7 @@ jobs: with: use-cross: true command: build - args: --verbose --release --target=${{ matrix.TARGET }} ${{ matrix.FLAGS }} + args: --verbose --release --package=mavlink --target=${{ matrix.TARGET }} ${{ matrix.FLAGS }} test-embedded-size: needs: build From 5c52c640d93bda0e11f58dfb9a157511832b6afa Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 11 Feb 2024 23:12:04 +1100 Subject: [PATCH 16/20] Attempt to support no_std in mavlink again --- mavlink/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mavlink/src/lib.rs b/mavlink/src/lib.rs index 8bea722eea..a1b71eaa5a 100644 --- a/mavlink/src/lib.rs +++ b/mavlink/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std)] // include generate definitions include!(concat!(env!("OUT_DIR"), "/mod.rs")); From 80718a657409e4af3defad199c1377b5e956621a Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sat, 17 Feb 2024 13:17:03 +1100 Subject: [PATCH 17/20] Fix for the last GitHub action --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cda9bab153..313eb75862 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -118,7 +118,7 @@ jobs: with: target: thumbv7em-none-eabihf - name: Build - run: cargo +nightly build --target thumbv7em-none-eabihf --manifest-path examples/embedded/Cargo.toml --out-dir $PWD --release -Z unstable-options + run: cargo +nightly build --target thumbv7em-none-eabihf --manifest-path mavlink/examples/embedded/Cargo.toml --out-dir $PWD --release -Z unstable-options docs: needs: internal-tests From 50f7ffda7492613c162f7f4fe4ca8f60517ccb75 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sat, 17 Feb 2024 13:36:25 +1100 Subject: [PATCH 18/20] Make the embedded example work in the cargo workspace --- .idea/workspace.xml | 128 +++++++++++++++++++++++++++ mavlink-embedded | Bin 0 -> 30092 bytes mavlink/examples/embedded/Cargo.toml | 2 + 3 files changed, 130 insertions(+) create mode 100644 .idea/workspace.xml create mode 100755 mavlink-embedded diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..2a7f278391 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1707604355173 + + + + + + \ No newline at end of file diff --git a/mavlink-embedded b/mavlink-embedded new file mode 100755 index 0000000000000000000000000000000000000000..eabfdbbcde5f07fc98ff9d1f059e19bbf0509f96 GIT binary patch literal 30092 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 Date: Sun, 18 Feb 2024 12:41:04 +1100 Subject: [PATCH 19/20] Remove unused import --- mavlink/build/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/mavlink/build/main.rs b/mavlink/build/main.rs index fdd6174289..7206d20658 100644 --- a/mavlink/build/main.rs +++ b/mavlink/build/main.rs @@ -1,6 +1,5 @@ #![recursion_limit = "256"] -use mavlink_bindgen; use std::env; use std::fs::read_dir; use std::path::Path; From 551669d24e202dd0ca77b8aefb355bc20dcbadd6 Mon Sep 17 00:00:00 2001 From: Graham Dennis Date: Sun, 18 Feb 2024 12:42:31 +1100 Subject: [PATCH 20/20] Remove accidentally committed binary --- mavlink-embedded | Bin 30092 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 mavlink-embedded diff --git a/mavlink-embedded b/mavlink-embedded deleted file mode 100755 index eabfdbbcde5f07fc98ff9d1f059e19bbf0509f96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30092 zcmdsg3z%G0mF_-u>Qqr=FxNL+bzr>e@O{GP6R)GrsCac49r6Ba?{lh7ovy0x z7M+=U&-YcIv-f)JwbxpE?X~xL^uaCL&yysH#Ycvn%;J)X%I+Eb$uh-cgG>f&1?y!w zR1wSsCjG9!HT|;DFQ#Xllf>>oJ^ctybr(NB>+{RhAL2`gv{E{$w_lNaSFB#!yHdJr zHDj5IB=<5V7uibbsNC7dO!msXr*)m)b=I1u{kIrASa^u#2&rf_g};Z0%>PV+e&!U0tZp z7g^jNLMzm$y0-RHMQ0Z@+GPr2)WIrs6hi2U7;{)}og4Z@;J!L`RI{Rn!v$MeLx5;R zaa7b8m$bhKgOJi=l{2<#J=6NB^75`Xbd7*upb=+l|5>og(F)5%L?ra;^-?3zF$C8D zS);IZJ#=v_YF3M8h+-`jseWA-7lE<$W<>Ie#s(uh9hYcAA-Nh2M-ngeC1Dd1IE~%L z^WYiec9CXcD^sOHy18t1tQk033?*}rhPQNywH8%4?pQC*^f&XO zfMCB?}eBo$R-o!F@4uHr2kT)QRJ_oK(9f$gpWU!1`eS9Tj zKcZSgPVo95g3LL<$-IFFBf-Fh-9As14$JID^O;xoVEooub*^CSJ~W)|1~tpvjY|$a z3MFY|78JimS$>=<3n*pTyKt42zJEM*{u4kS!T`@6gGwA1;3qm?cm=Me!CZbCb>GEL zlCmeAfOEFE4u$ON$eXjjMX%&+9zD0ke%%74d z7h|aAe*<_2`jY993THyJ$G|Cbl!AUson5;@mg%Pgf|vyHHlRD1HB!$CP-WI|K)!-H z7YLb?rTmpR+vsdYmAW@U>W9$3Oj+tVliDj2erH!dx}G^xFwK7%p0H^M6I12#LLCV>AU_8$y^EByM=Jap z)L(!;GVe)pxJz&-%!7J@dU|gX`j-OQ?W21?gr{Ua6!HHM2jq_i)f7qi-=y9wx_1`I z@Q9S(g7ZmmmCWBr`7%I!4 zuOjX*L{u*bsuR%CMO6PUT)4>cFY=zUe28v*mDKl=w8BH1cM<=ikcMO?A(nDE{AdvK zXJ&&W<+uqpNSv*5Cm?gA*)wCvnF7Kx_d$}C-vIn<8SsxwqTQpo$9;mAz_|pM`xQEr zc`T-XECMl5(g;EqN6398b=7yM1_x};Bx5B59VT%qjF3}HDmAg{pQsiGCj}Pg0|2nd zxh3^z=_2xONh9>tG?&u>BNEeNq>EOgX7wnq6n`>9%9`xBxK2pr5{0_@#E3y8RU_r8 zO(|&rfpTLzN!v*1P+&9=!`}s zq_`p?j`Y+s;AQQRCp+=_3eo(OCZbGgesrWA&(cvZ!@|uJ{P%MI%9*Hm`e@He@5h`l_ z3yu7eSQM!utna6=64s-Ll@>BXZQ_Vb2_buVO+rWtXb|$)2s0KEJ&p$(g*jlnvXNJE zI8yKfhMwY)XoW%|FgB$yxFxu7BNQk_Cy(8XrYTkmO&={?Owlq@`*0%%^yrPKIYzoT z-~cW*jRt9iLMqn>#nc)rimDN-t0GpIgQ9_cjbL?{0}`sGsGCqNMY`4hHKMMo_C8+2 zyToJ12nA(HCG1rXH)1E9i-L2S`BRPP=;b%-%!TJt?2eq`e>Y+a=A;Q}gkm@bjDmfz?`Fmki(>IAE^kt_GZm@%u{fl+6b z;PO5oa>h!A*s}ZalSVFtF>ghivXW6Q04e>X@zwmALb$YhO;VKWG0x9GHP92Rx1**5 zCTXl42F9D8xcoxF_6cE%Zmw_9_X6bzmO&>ML*xiVnF+1VF z>%jHX5UR0uHH5ia^a|SGON?#kXvT&(Jh#vN7|qUsF7q5Rgk%Brj6Dv+W!ZBHH9rR9 z+>6>+&6h)Xp=L66=0Otd-s6!%QE8o&p|gAf2sTrK^9o6xLep1JUS>;jANqeWElN(7 zn0zfN--hmH4oDd~%g;fq+eq5$B>8cyG(SMscS`aII&}iM$IYPnF}i>3i70$W%FtPU z6_y?2#PfTSd>Ll-4M52JL}J-{(Tn>~k?BQNZzH@vO;W5w76u253_hZuo&Atjx?Rdy zRE^^_2-9(FA@?V=puqt?EVEPVI5ttvRXWzP+<6=>c8fB*3iyDqOwlq>7GXXx&B&%uOj$9r3Q~1Knh44XxK|5cO#)c z{v_VFyqS=_gS*Iww>JQcumCT#|%2 zsr&~v=N^)0adQ^Pf9|BNwKnB@fg+6*pvq5T7?7LZiyAuq9KVi@g|62|odzG4VbUob z=Oik4$GSdB_&8pPUq+G&`6Ee1eSd&;Jo1PZphdDCDc4bI=2f9BU+eR8hI=99KwZw!U<2~gxA3x?xEBRgwLSn2_ihV zz~pCv`fUu@jtc}jsZ<*IE_Cn=#U-I*!|DI`w+pr z4dC_2F^pY}nwZy%T(%KPM_@?eMSC&-gYfSwayS^0d1{2iMs_xTzeXU#B9wiRrHdR2um@#=$07gXnJp{V`BP z$Hxo#fry^#h0_n6h}o9BBWl0O=|2vEC5WH9Jtt+~3%Q?$PIBcAsS(l=4SX7>;_TaxLX3rrXIEsU#=1FYi`d&4U|Rkc0K?GA^eXQT0qB0 znML+@NMoow$^)|0SkR$X>W=a>gqAUos5^=bp&MvEgZZB16Fv>X} zhR))g^K_)H-^ZwnGZ?aQJyFc?bcrab9+M_{m&iFUB}9S%^gA4M75T}M&oCrEVmc~x z!)zJ$TU^!oQsZ<$G5mm4`4QL0XDE*!G2UY5n64FG3}5UFtu(Y7_b1I4KERLo488Ls zKBw^s2(v>UotQ!v>Vx1uhhNqdem^1LXeEEF$HM}xhSyAvw*e=^J_Qxm<)CE&9q~en zreiv2+M^?G_cT#td!jQ<5p=}oCqxmmuehMlO2-?;iCr0;DNMzO(95-O-?}_;dxS%* zUd}IW=jHJDf0?#b|Nl_+FIP9ql_PGi72O{j-m2Z@*2i+D&&%brT>QAb<w9+oyRaM&!O1@+0 z<+5vUVKd`nUNAZ~=?D8pr>cHX9Sxnaadyu5*v`p`U=rL$z3G`TpST+1W3D|mIX*TS zltgtvJWG~lmdoW**-$;z^S6M+pKo>!D$rmSqLHLt;9Caaj3za8ylY; zo18J6>V#$`aH%)or>dG;Q9aiWty0;sD_fX1HNAh-b-dksohsKCx5Bc-HD=~q&RefI zmZcl66@-SPZec>kmP$NhPO~>L$M?kru+ix@*oMBTRd+#as&(5zGcEaynvm6WDqg6& zn(Nr6=4g=hH868fg?cBarrWe)k=152gEa0`gHdWo>m|*%R70~36K3MR&Z@!8+&Fo6I6dQ4M)R>oi*EZ?$<_m>>}smz zhTKHL1;VLnqX$gRP3T6Wqt4BYT^*2vYWm))Gd&FlADs+#QumEO)jZb=O0H|UKJ@wf zbzgXrt$KE7mqO1lOQo{KOKzqvaVU7X_ZR0=TyuR7}o+%yFoCjkpzj5 zrfG<2QLs6Db-4RYd1HGr@FqY;-T^+;SyQOF^Kz zu49xd-WC>4&(Q#G8wSO|t&84v-05(%YQWC%uDT=`Pl<$3HRp$r!?9qVl5JZsRDei@ zSdW;%N7?9J#NZj`?f0OpSoR5LAA_e7*SRrpN3ds3mB-zLmUxfRMlk8PV` zhn{YiVS{o-*UKf_a1)NUME4gC8-}WdAgu+isq3Z-bE5u?xpKRBB_c_s););hn}Md5 zRoyE4uJ4zOcJ8)-+^TV^1tnK6nP#9@Jl9q+Z-U?A23;h`!flo~L6R~3O3BnqhGv>2 z6Jciyo13J-!Ds8hXRiycdd&>xOG8IwbH+!7Y4?U>ZH8GCfOS4^ML|m|Crh>NSFBJs zbluT(6W;BJXa^T9|j2yr(nQ)6OY-4q9W_F_=OwVjwF!OIvi&_z0v~i~D zZNz9OR%bSzy%4SF`>KX4z_Tqs(8{5?!P_}kRJBqoGEa_!ZSQ5mZDP(Sn~%?D#b0g@LbYW?<>I zt(iV$iIGcLJX5xK_MnTxg0vYaD_RbaVVYK14J*Fk7&KV^cwScFvsf+BT-JmhC7Zrs zIicxTrN9X=QM7g(D5+hjEQE#F& zT2-gDx|$K>8j^OQv^JVImppA#P_|Vc5mi+~y;O0Wux$`ZuDaUkbyNdmRV%xeZDKKN zm}R|;7}FT1^h)D;V`$EDhc3lme~7O-EHTa3MuS#@p+_giW+t3jZx_!hNS}64DTTIP zHf^I~dgU!ltl4XgnKSz*JzG?2h(giYISeK}N(%k5?pK^jP(m6OSPq32F~rzp6>5*x z9&NO}lt6EXA(BPSwhbL~yC;@7Edsrv!)eTBTxZ9`zc!ZN-pgqIT9I zTUihfgT{BU@8YQ<7v&+lVNR)t;V?7nRA-|>K{lc77%{KduHox$rR;k;;!=n_3Ogi? zGi!1ULu-+edINek_YNvoCLi(7raN40{o?}R0z6zFbHffX0Alvsg@?X8r8%sr)G zLf4xI6X;8Kg0f}$x?Ry--_(WhMt!$T&?B{t*IIjPp$OEWW(6+R=VjduHOCSToS<$n z59MmmlU52V2KrTki_#WBeJhK+o5XMCunT6T@hU|r1A9)ihv%9Vj8bx}7WB|yG(j}Z zJUX_`k~5D(yNB4}i&Fwq3$S?7LJJOs%u1}DFlyK(@h%J&&lAqfZrX>5mzHCEY1u}U zWWa2nC6I~Cimg{%-BC?b4IP+hDK7ncrT$vk7F(K3B*<(*Xl2gKM6{wvd0Kiyfy}LH z*uudA$51s#)ilh!wXvEsJn3^$yEQEKbX&{!T`V@yFcvlzPga_{72IM; zfz_>GAeKVc&|KZdRxBTqw6x&c(+ZN$CF+2!yhVPnI zutIih!>%~+Xv+Ap%1CkL`Zb_G2fKg5rvN#cgEb=NIoe9arbB~*Fg-Tt zXmNEn4imIQIhbwx*nqasU>U2tIGGeHtyJE%c(M!`iyPqv?(XUIWDqU0D4_eH=c`aT z7G)Jzqg~KFPLquz>=ytzuwBP2`G)Ek*f`Y1f*_&r)E1B!r=YXEl4-yMc4(Mb4O1AY zhb4GtneiRpHdB<(T-EJ+p}u8sbK`zsA$HtmlP#wdGg5PG;JfsGO0fuS2o zQvSO%L3OsJT4fZPDG8_Z!g&l^h1eXe+ZzEH{Y#WF)zo~w?QY&uay}ooaIn*;VS}NJ zH3S&$L3XY+6XSba=Md z*`c-)!vXOJH#)#xwQLn@U&kp2A?`7WETGvm41r4c(M(Nb2KGL%iH+rE;A4ZlU0;$@ zUR&SN!5BjryHb{BmtDgyRj`V}ZgGH}YS@MD>Ct&+*XYdt8P6FXXSki#N{b8f1{fC& zAQ)Fd&C|=c38Es+OgkIjYfd>}+GnZBTGF_@?F*4OmN89L)JnPRV5Sc()63lvKaO1kC-t{u1t zk=P>P+k^{O1NIERG23i40L|+aANSil+}){QyRL*z(?SgPqOgqG7^s zjFvRu#O)K|*!3{qHv6P7xU`LaExHrl%;;@EbfbKG5YDm-cQbDLW-%u{gwYw=kTOab zJ%M3k-YDyVFZPCNDqZp-uDq|St& z(*q8djP2Ytn{qtdqoouGUBW&WZl9JM&nyLq-F%M?4xPf+u$rp}Kl1j#F$@#!AWI4= zftXSfVLr|r1jRZqg_0Xps zXm8w^+&Q>?`|EcMo=mqZyum#|bp|`{gIdw56x9urq>u6agC~1d;CY%=QU~GH+6GPE zpjoG!LSf(8hnqz8`@|8(t*~5A$BsNJ zWIA)b_$tjRX+T;nA0w@i)=KN76Qm*OmGm4Kp8n>~MrZMis&t^Y8_&eE_!(tfvSU)^ zO;H`e=)fBS?A+e`tY0Edd9dF>>f1K3f7M9KNF0e4PR;>=vmGwrVxWr`We{-ogqYX>L4Ny5|RG{42lY5H_|x&2$L zy~W_^_7^KJ#&5auFBgBY_LnPvy8U!{vG)Gh@N|C`YcD;X)A)2lg$=`zimNq*`6r16)l?=-*v-^yu!Nta1~q%(TwEuGgrgYOm4LGK}v4dQaF^SB)I zjLT{KbeVXyWy%?o@N~Hu|5iTm zEZ)SUgZkVGhc_1C@Z6Oe$8kS?=ZW0)#)jNAg2#GH(sNJ?IQdzU|6!E3H_MG%(8v9b z+oN)`J`JJ%YY`86Cvah|c5^MKi}C24!G(BnZY<=Eao-F6>AX1ECcSSs+$7JYJd(tU z`NaB*%k*C2U;@4e*B30{b2yi5>&~V)B4=r^>Y%YbdM9!r&cgOyY|87F z9N9naFTGEBLCXG=^T+TjIlOVb8N=w^%Uy}JMl(MkT|Y|`77o(&AY{+7DO}+zv%l%> zp%bd;y-X>6BWB^98NMIR#I0g_;R#RU5+#2gldiFH6SvzVz{HdvRpTvbTGlbykd)p| zdDSpJDub7+Gja8hq!c=Lq$+huQ98Hr${6pkM0FRZ5TC&d^1YqgQ?=hlZA_n)V-An? ziP~OjA75w`V%@S%QhK7c{u+wPviYVu!b1aM%gozY+vvlyN{*=+*lxuOGdgzK@r(c- zAvSS)6c+(KWYBnni{B?8?bh^1uX9BO@gP@PZ5yF0bVh!YltowNR~GTDFZwc!kUoa` z0y;R{6grNV*_GAu#|Gv(kLRzHnxgF&X!j2kTcLqVr~Li_E|Ls3gqLd~(W*|lr>H2~ zIG;TWglb^(Z(u{x9U2&3QnNSg7WltiwKV*jBm7^r#^(xFg$gfSAT5WUCZNO3q5l(~ z>m=(OIoL!QFy2oh_?-uv)BhrZzoP~GHxc}%7Vzuf(bWE-7VY0CNezQ3cAJ|cx?f-0 zT<+T<_%B<)-yOk!+5-MwX*hFq+Fc8s@+Ts?uUy+iAAsYdki0)%1f0S}gS!L%*$DpW z7W7X>@JCy~p8}kG?&<#gM_M^u260LLUWE9m#SmYLT71j3`7;&{E^xXvBf9jfYg!;2 z#>XhghW~b;xlV44;J=FCn-He5?4+i_3hzwd!>5i{otlY)3sY8h##(%PR(QkBh#{@Q z9dTIZt<;6#j&5qxqY04=(Z+Wa;Zow^d%RIhdyWb5l)hTk4-wD@@^ea0uBZ$YmA>3o zrDvnkw>2mK#lfQdk1WJ_UMb|{pRr-3Pu@RIfH1BYkguLs`ZjQq4V*+7$jLuq^Gc8Q zYDCwglsxuX2u0~GlBa$q>D4D2K*kqvB&+eJ)6Yy?4$D1h4|zvY_Ym;=$uH(oO= zTHwOWV@nM4R=sb(jQduv!r10Mp1`_38m{%Z>kvLcLVV<#uPF+it7^*m3$)OuDFqYF zU;PdEHOtA*UrWKUPrgeUhVbu?dk=*@e{GR!asCGB=UyOyER2;Sz$oT!P!)IVy zRsrcdI>?`UZoFe~Arqz!!7GbG7{F{$cW`cO4v7x^wbR`S5x}n3F$=;dNY2 zKC4L3bBL$>1e;gZyUMz8W&L(VM?33D2m^xc9ah$DSJtZwYt@CgVT9Xvo}%l@dhm&v z@K$s31~mV=P+6Oki^W>k*4BHuw%$wBM&o`f@70Z5Qw8~R`=P0u(FIafoyjs(1^@5t zl3&OSb9atI7nuqc>Xe_!9m#em-SQEbi1d7WN0`mZ-(#fhy!;51di)r--JO|v22_MvYtVT8_0WX2mg?b8^68D&6zh(;hcs;3O>pi2VhHxf*xkzNU7Yz1nGnoj!w(N+*KsQ^<0F@eZ$IT7?<0LLeQRhW!)|^_U70H;#zL(&FBGl3|FE z*qdWxbHFgvbmZXODSsdSkMVb|jd||rA?f0C&|jaftUDyUH|kLA>AdrL+|9VQou|L5 zg{KeBW5mJJ@8#Y8YGmgRUo)?)B|FpjK0mr7jGSCYDT;couw?zPvKFpze$5rWj6vHc zfAHYlvELnm-;G7gxu22WXsE<6fotSM9T;d}BY&6(|5FS`8jHCuF*zoOBafW_gz1nX z=a2dLUnk$WPejgl^C;IRKTYxAu4^e0$Unf)Lnx&DA`n@I(t|KU!SNNt%IfXh7Pm)) z-zCDEFhW51B8?Cba^#3SB3ucq7hyKe9$IXIB?8I=NSJAThcVezo8WKbsbeRC0*%#f z`TB!*D=Xi(LFrbNuJe_Z+qZ7ps&sGX*N19X+xb;thtefqjam9<2o9@q@*NqGk{~$M zGmz687YAa#=|akSkaC<(`TsEFQ~!+Q2twuLyWxhSmcmY#{I-Mms2j(sm6gIqrE5b} z%gKNhQ_YLTdPgF?`x0N?bjpv)MF`d>fBwJ`Ma#c~2dL)}=BVyHh?$zm#5CBcs3iaP z@6jkC3NdMVgn&2H49|V&NzA>}vrk~|<)ZSLIRVn- zPXdH^4xzdBelMYm5T09zQ%Cwmi;t$%iQZ_^ z{*aT8$VVF1N0ixOrtFme*MWJZe}}U2QKf%_Vr^GeqUHYFsmjWY3oERRHL!Jv_v7o_ zO)UAt`->c8;Z#)U@38obPW5lNSh4aCaQvq@e!u(>+$!Q$ClQ3yJS6!AHNSG(Hl_bm z#o9*9c}KeBzmmxZR?5#E2o(z`2|%$SD-c~=*(rY&UF=48b|}^}O8*5Ix=O#F?BFn( zMD<1?5|wsiz#YsF%HM_aS&{QSh2YbnknCufG$FbO=YtsiTRA=IYW?TkxPe2^i>=&j zALGu~FMkCd#(PDLB|(<_cL0HRy|+2}U*8;3%Q^X*3}pEel$9GGD-2a@3rgf&K+i59 z$}agM^5WX~)N-`(0+bQk;69lPB!81^AUwKmS%@X1;|kzz6jemxMizemzq@KqvLV-;PItzE2&k!2_2{0|JJMsBL7H{g7(`w<->Bg zFt9bUUn&2H0vm18A;X);+PP1Di4D^gozc)eaTx1E%d{LsTn$>Z4E&|FOb*1yOiune zT0zsdVO@cx1KK1pUcd!Sl8EGD0={19d2|`=zWgl_x|2w|;&jj*7KvRH-+0NgUq~0d zpF{Ac31Tx4?b3n=ooExjk;f5Ki_dHJ;O@|2G!(z%F^!v-iAM%&?<=wbM-tDOyMmzh z?%snn27CEG+u=_opUo@jTTsvQD|&-|0*|jHpTA|FhG=+vc@(GA^W`e4qPLFeE4|{` z-)C_Zy{UN$XGIVA-iylU+f$##J;C&ggxey-F?JkQx%5USyABk1c>0St(HkxWP8B~U zN#Dcy8B``7lDr%^(MML!Za}NDu%Wz{y%Qhp6`u>BfAf@ly7FOaPrUN@N?h`f_-w~T z{K=g+Krs4P&0#{~ zamJ?>{z_<)zOTT};R>Q}#J!KJF8RnQ{mUu(&eBU9((sib_B~F=KOF+5FgAX5@BKJR z(fg$IDf8NQ4(GT3YouiKHRxuW$(%57;6<<45Jn<6@vR1T z4xdkpDZ;8V5yS<$!Be}Q^5V9RH5!y>_fJ!KX8**j3HOL#!fj&T+?5I(T|2w67M+->kCj9A2A+9 zD|BxA|~;7oXQ{26}nHI=Ub9wQ}0M=a_X$_;q0$Cvl