feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
@@ -0,0 +1,13 @@
|
||||
#[derive(darling::FromDeriveInput)]
|
||||
#[darling(attributes(example), forward_attrs(example))]
|
||||
pub struct Example {
|
||||
ignored: String,
|
||||
}
|
||||
|
||||
#[derive(darling::FromField)]
|
||||
#[darling(attributes(example), forward_attrs(example))]
|
||||
pub struct ExampleField {
|
||||
ignored: String,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,11 @@
|
||||
error: attribute path `example` will not be forwarded because it is also listed in `attributes`
|
||||
--> tests/compile-fail/attr_forwarded_and_parsed.rs:2:46
|
||||
|
|
||||
2 | #[darling(attributes(example), forward_attrs(example))]
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute path `example` will not be forwarded because it is also listed in `attributes`
|
||||
--> tests/compile-fail/attr_forwarded_and_parsed.rs:8:46
|
||||
|
|
||||
8 | #[darling(attributes(example), forward_attrs(example))]
|
||||
| ^^^^^^^
|
||||
@@ -0,0 +1,15 @@
|
||||
use darling::FromDeriveInput;
|
||||
use syn::Attribute;
|
||||
|
||||
fn bad_converter(attrs: Vec<Attribute>) -> Vec<Attribute> {
|
||||
attrs
|
||||
}
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
#[darling(forward_attrs)]
|
||||
struct Receiver {
|
||||
#[darling(with = bad_converter)]
|
||||
attrs: Vec<Attribute>,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/compile-fail/attrs_with_bad_fn.rs:11:22
|
||||
|
|
||||
11 | #[darling(with = bad_converter)]
|
||||
| ^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected `Result<_, Error>`, found `Vec<Attribute>`
|
||||
| arguments to this method are incorrect
|
||||
|
|
||||
= note: expected enum `Result<_, darling::Error>`
|
||||
found struct `Vec<Attribute>`
|
||||
note: method defined here
|
||||
--> core/src/error/mod.rs
|
||||
|
|
||||
| pub fn handle<T>(&mut self, result: Result<T>) -> Option<T> {
|
||||
| ^^^^^^
|
||||
help: try wrapping the expression in `Ok`
|
||||
|
|
||||
11 | #[darling(with = Ok(bad_converter))]
|
||||
| +++ +
|
||||
@@ -0,0 +1,10 @@
|
||||
use darling::FromDeriveInput;
|
||||
use syn::{Attribute, Ident};
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
struct HelloArgs {
|
||||
ident: Ident,
|
||||
attrs: Vec<Attribute>,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: field will not be populated because `forward_attrs` is not set on the struct
|
||||
--> tests/compile-fail/attrs_without_forward_attrs.rs:7:5
|
||||
|
|
||||
7 | attrs: Vec<Attribute>,
|
||||
| ^^^^^
|
||||
@@ -0,0 +1,12 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct Receiver {
|
||||
#[darling(default = "usize::default")]
|
||||
not_u32: String,
|
||||
|
||||
#[darling(multiple, default = "usize::default")]
|
||||
also_not_u32: Vec<String>,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,16 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/compile-fail/default_expr_wrong_type.rs:5:25
|
||||
|
|
||||
5 | #[darling(default = "usize::default")]
|
||||
| ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
|
||||
| |
|
||||
| expected `String`, found `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/compile-fail/default_expr_wrong_type.rs:8:35
|
||||
|
|
||||
8 | #[darling(multiple, default = "usize::default")]
|
||||
| ^^^^^^^^^^^^^^^^ expected `Vec<String>`, found `usize`
|
||||
|
|
||||
= note: expected struct `Vec<String>`
|
||||
found type `usize`
|
||||
@@ -0,0 +1,12 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
enum Choice {
|
||||
#[darling(word)]
|
||||
A,
|
||||
#[darling(word)]
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,11 @@
|
||||
error: `#[darling(word)]` can only be applied to one variant
|
||||
--> tests/compile-fail/duplicate_word_across_variants.rs:5:15
|
||||
|
|
||||
5 | #[darling(word)]
|
||||
| ^^^^
|
||||
|
||||
error: `#[darling(word)]` can only be applied to one variant
|
||||
--> tests/compile-fail/duplicate_word_across_variants.rs:7:15
|
||||
|
|
||||
7 | #[darling(word)]
|
||||
| ^^^^
|
||||
@@ -0,0 +1,10 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
enum Choice {
|
||||
#[darling(word, word)]
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Duplicate field `word`
|
||||
--> tests/compile-fail/duplicate_word_on_variant.rs:5:21
|
||||
|
|
||||
5 | #[darling(word, word)]
|
||||
| ^^^^
|
||||
@@ -0,0 +1,21 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct Inner {
|
||||
left: String,
|
||||
right: String,
|
||||
}
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct Outer {
|
||||
#[darling(flatten, multiple, with = demo, skip = true)]
|
||||
field: Inner,
|
||||
}
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct ThisIsFine {
|
||||
#[darling(flatten, multiple = false)]
|
||||
field: Inner,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,17 @@
|
||||
error: `flatten` and `multiple` cannot be used together
|
||||
--> tests/compile-fail/flatten_meta_conflicts.rs:11:24
|
||||
|
|
||||
11 | #[darling(flatten, multiple, with = demo, skip = true)]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: `flatten` and `with` cannot be used together
|
||||
--> tests/compile-fail/flatten_meta_conflicts.rs:11:34
|
||||
|
|
||||
11 | #[darling(flatten, multiple, with = demo, skip = true)]
|
||||
| ^^^^
|
||||
|
||||
error: `flatten` and `skip` cannot be used together
|
||||
--> tests/compile-fail/flatten_meta_conflicts.rs:11:47
|
||||
|
|
||||
11 | #[darling(flatten, multiple, with = demo, skip = true)]
|
||||
| ^^^^
|
||||
@@ -0,0 +1,28 @@
|
||||
//! Test that multiple fields cannot be marked `flatten` at once.
|
||||
|
||||
use darling::{FromDeriveInput, FromMeta};
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct Inner {
|
||||
left: String,
|
||||
right: String,
|
||||
}
|
||||
|
||||
#[derive(FromMeta)]
|
||||
pub struct Example {
|
||||
#[darling(flatten)]
|
||||
first: Inner,
|
||||
#[darling(flatten)]
|
||||
last: Inner,
|
||||
}
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
pub struct FdiExample {
|
||||
ident: syn::Ident,
|
||||
#[darling(flatten)]
|
||||
first: Inner,
|
||||
#[darling(flatten)]
|
||||
last: Inner,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,23 @@
|
||||
error: `#[darling(flatten)]` can only be applied to one field
|
||||
--> tests/compile-fail/flatten_multiple_fields.rs:13:15
|
||||
|
|
||||
13 | #[darling(flatten)]
|
||||
| ^^^^^^^
|
||||
|
||||
error: `#[darling(flatten)]` can only be applied to one field
|
||||
--> tests/compile-fail/flatten_multiple_fields.rs:15:15
|
||||
|
|
||||
15 | #[darling(flatten)]
|
||||
| ^^^^^^^
|
||||
|
||||
error: `#[darling(flatten)]` can only be applied to one field
|
||||
--> tests/compile-fail/flatten_multiple_fields.rs:22:15
|
||||
|
|
||||
22 | #[darling(flatten)]
|
||||
| ^^^^^^^
|
||||
|
||||
error: `#[darling(flatten)]` can only be applied to one field
|
||||
--> tests/compile-fail/flatten_multiple_fields.rs:24:15
|
||||
|
|
||||
24 | #[darling(flatten)]
|
||||
| ^^^^^^^
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
/// This usage of `from_expr` is VALID because there are no unit variants that should conflict with the
|
||||
/// implementation.
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_expr = |expr| Ok(HasNoUnits::Variant2 { other: format!("{:?}", expr) }))]
|
||||
enum HasNoUnits {
|
||||
Variant1 { field: String },
|
||||
Variant2 { other: String },
|
||||
}
|
||||
|
||||
/// This usage of `from_expr` is invalid because unit variants already generate a from_expr
|
||||
/// method, and we don't allow using the from_expr override when it conflicts with the macro's
|
||||
/// "normal" operation.
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_expr = |expr| Ok(HasUnits::Variant2))]
|
||||
enum HasUnits {
|
||||
Variant1 { field: String },
|
||||
Variant2,
|
||||
}
|
||||
|
||||
fn newtype_from_expr(_expr: &syn::Expr) -> darling::Result<Newtype> {
|
||||
Ok(Newtype(true))
|
||||
}
|
||||
|
||||
// This usage of `from_expr` is invalid because newtype structs call the inner type's `from_meta`
|
||||
// directly from their `from_meta`, so the custom `from_expr` will never be called in normal usage.
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_expr = newtype_from_expr)]
|
||||
struct Newtype(bool);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,11 @@
|
||||
error: `from_expr` cannot be used on enums with non-skipped unit variants because it conflicts with the generated impl
|
||||
--> tests/compile-fail/from_expr.rs:16:23
|
||||
|
|
||||
16 | #[darling(from_expr = |expr| Ok(HasUnits::Variant2))]
|
||||
| ^
|
||||
|
||||
error: `from_expr` cannot be used on newtype structs because the implementation is entirely delegated to the inner type
|
||||
--> tests/compile-fail/from_expr.rs:29:23
|
||||
|
|
||||
29 | #[darling(from_expr = newtype_from_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
// This usage of `from_word` is invalid because unit structs already generate a from_word
|
||||
// method, and we don't allow using the from_word override when it conflicts with the macro's
|
||||
// "normal" operation.
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_word = || Ok(Unit))]
|
||||
struct Unit;
|
||||
|
||||
fn newtype_from_word() -> darling::Result<Newtype> {
|
||||
Ok(Newtype(true))
|
||||
}
|
||||
|
||||
// This usage of `from_word` is invalid because newtype structs call the inner type's `from_meta`
|
||||
// directly from their `from_meta`, so the custom `from_word` will never be called in normal usage.
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_word = newtype_from_word)]
|
||||
struct Newtype(bool);
|
||||
|
||||
#[derive(FromMeta)]
|
||||
#[darling(from_word = || Ok(Wordy::Options { thing: "Hello".to_string() }))]
|
||||
enum Wordy {
|
||||
#[darling(word)]
|
||||
Normal,
|
||||
Options {
|
||||
thing: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,17 @@
|
||||
error: `from_word` cannot be used on unit structs because it conflicts with the generated impl
|
||||
--> tests/compile-fail/from_word.rs:7:23
|
||||
|
|
||||
7 | #[darling(from_word = || Ok(Unit))]
|
||||
| ^
|
||||
|
||||
error: `from_word` cannot be used on newtype structs because the implementation is entirely delegated to the inner type
|
||||
--> tests/compile-fail/from_word.rs:17:23
|
||||
|
|
||||
17 | #[darling(from_word = newtype_from_word)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `from_word` cannot be used with an enum that also uses `word`
|
||||
--> tests/compile-fail/from_word.rs:21:23
|
||||
|
|
||||
21 | #[darling(from_word = || Ok(Wordy::Options { thing: "Hello".to_string() }))]
|
||||
| ^
|
||||
@@ -0,0 +1,16 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
struct NotImplFm;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct OuterFm {
|
||||
inner: NotImplFm,
|
||||
}
|
||||
|
||||
#[derive(darling::FromDeriveInput)]
|
||||
#[darling(attributes(hello))]
|
||||
struct OuterFdi {
|
||||
inner: NotImplFm,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,33 @@
|
||||
error[E0277]: the trait bound `NotImplFm: FromMeta` is not satisfied
|
||||
--> tests/compile-fail/not_impl_from_meta.rs:7:12
|
||||
|
|
||||
7 | inner: NotImplFm,
|
||||
| ^^^^^^^^^ the trait `FromMeta` is not implemented for `NotImplFm`
|
||||
|
|
||||
= help: the following other types implement trait `FromMeta`:
|
||||
bool
|
||||
char
|
||||
isize
|
||||
i8
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i128
|
||||
and $N others
|
||||
|
||||
error[E0277]: the trait bound `NotImplFm: FromMeta` is not satisfied
|
||||
--> tests/compile-fail/not_impl_from_meta.rs:13:12
|
||||
|
|
||||
13 | inner: NotImplFm,
|
||||
| ^^^^^^^^^ the trait `FromMeta` is not implemented for `NotImplFm`
|
||||
|
|
||||
= help: the following other types implement trait `FromMeta`:
|
||||
bool
|
||||
char
|
||||
isize
|
||||
i8
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i128
|
||||
and $N others
|
||||
@@ -0,0 +1,18 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct NoDefault(String);
|
||||
|
||||
#[derive(FromMeta)]
|
||||
struct Recevier {
|
||||
#[darling(skip)]
|
||||
skipped: NoDefault,
|
||||
|
||||
#[darling(skip = true)]
|
||||
explicitly_skipped: NoDefault,
|
||||
|
||||
#[darling(skip = false)]
|
||||
not_skipped_no_problem: NoDefault,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,23 @@
|
||||
error[E0277]: the trait bound `NoDefault: std::default::Default` is not satisfied
|
||||
--> tests/compile-fail/skip_field_not_impl_default.rs:8:15
|
||||
|
|
||||
8 | #[darling(skip)]
|
||||
| ^^^^ the trait `std::default::Default` is not implemented for `NoDefault`
|
||||
|
|
||||
help: consider annotating `NoDefault` with `#[derive(Default)]`
|
||||
|
|
||||
4 + #[derive(Default)]
|
||||
5 | struct NoDefault(String);
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `NoDefault: std::default::Default` is not satisfied
|
||||
--> tests/compile-fail/skip_field_not_impl_default.rs:11:22
|
||||
|
|
||||
11 | #[darling(skip = true)]
|
||||
| ^^^^ the trait `std::default::Default` is not implemented for `NoDefault`
|
||||
|
|
||||
help: consider annotating `NoDefault` with `#[derive(Default)]`
|
||||
|
|
||||
4 + #[derive(Default)]
|
||||
5 | struct NoDefault(String);
|
||||
|
|
||||
@@ -0,0 +1,21 @@
|
||||
use darling::{FromDeriveInput, FromMeta};
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
#[darling(attributes(demo))]
|
||||
pub struct Receiver {
|
||||
example1: String,
|
||||
#[darling(
|
||||
// This should fail because `example1` is a local that's been captured
|
||||
// from the `FromDeriveInput` impl. That's disallowed because exposing
|
||||
// those internals would make any change to the derived method body a
|
||||
// potentially-breaking change.
|
||||
with = |m| Ok(
|
||||
String::from_meta(m)?.to_uppercase()
|
||||
+ example1.1.as_ref().map(|s| s.as_str()).unwrap_or("")
|
||||
),
|
||||
default
|
||||
)]
|
||||
example2: String,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,30 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/compile-fail/with_closure_capture.rs:12:16
|
||||
|
|
||||
12 | with = |m| Ok(
|
||||
| ^ arguments to this function are incorrect
|
||||
| ________________|
|
||||
| |
|
||||
13 | | String::from_meta(m)?.to_uppercase()
|
||||
14 | | + example1.1.as_ref().map(|s| s.as_str()).unwrap_or("")
|
||||
15 | | ),
|
||||
| |_________^ expected fn pointer, found closure
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a syn::attr::Meta) -> Result<String, darling::Error>`
|
||||
found closure `{closure@$DIR/tests/compile-fail/with_closure_capture.rs:12:16: 12:19}`
|
||||
note: closures can only be coerced to `fn` types if they do not capture any variables
|
||||
--> tests/compile-fail/with_closure_capture.rs:14:15
|
||||
|
|
||||
14 | + example1.1.as_ref().map(|s| s.as_str()).unwrap_or("")
|
||||
| ^^^^^^^^ `example1` captured here
|
||||
help: the return type of this call is `{closure@$DIR/tests/compile-fail/with_closure_capture.rs:12:16: 12:19}` due to the type of the argument passed
|
||||
--> tests/compile-fail/with_closure_capture.rs:12:16
|
||||
|
|
||||
12 | with = |m| Ok(
|
||||
| ________________^
|
||||
13 | | String::from_meta(m)?.to_uppercase()
|
||||
14 | | + example1.1.as_ref().map(|s| s.as_str()).unwrap_or("")
|
||||
15 | | ),
|
||||
| |_________- this argument influences the return type of `{{root}}`
|
||||
note: function defined here
|
||||
--> $RUST/core/src/convert/mod.rs
|
||||
@@ -0,0 +1,10 @@
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(FromMeta)]
|
||||
enum Meta {
|
||||
Unit,
|
||||
#[darling(word)]
|
||||
NotUnit(String)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Unexpected field: `word`. `#[darling(word)]` can only be applied to a unit variant
|
||||
--> tests/compile-fail/word_on_wrong_variant_type.rs:6:15
|
||||
|
|
||||
6 | #[darling(word)]
|
||||
| ^^^^
|
||||
Reference in new issue
Block a user