Open zeenix opened 2 years ago
But
Array
seems to assume that only Variants will be put into it, so I've only been able to construct arrays with variant(struct), which is not entirely the same.
Array
is for arrays in a Value
(as in VARIANT
type in D-Bus). For just arrays, you just use Vec
or slice.
Actually look at the code again, Array
only keeps the elements as Value
to allow arbitrary types dynamically. All elements are however, expected to be the same type and encoded/decoded as such. There are conversions provided to convert between Vec
and Array
but also between Vec
and Value
directly so you rarely need to use Array
directly.
Having said that, I think it's a bit of an oversight that Array::get
gets you all elements as Value
but Dict::get
gets you a specific element and converts it into a concrete type for you. At least Array
should provide a way to get an element with a concrete type.
In GitLab by @WhyNotHugo on Apr 21, 2022, 12:19
Right, so it seems that if I want an array of non-variants, I need to use Array::new
and pass a signature. It works, but it's eventually pretty ugly:
let es = Structure::from((command[0].clone(), command, true));
let mut a = Array::new(Signature::try_from("(sasb)").unwrap());
a.append(Value::Structure(es)).unwrap();
let props: Vec<(&str, Value)> = vec![
("ExecStart", Value::Array(a)),
];
I think it really makes sense for Array
to be a generic type, so I can use Array<Mysig>
. This would allow something like:
let a : Array<MySignature> = vec!(...).into();
Note that an Array<Variant>
would still be valid (for arrays with mixed variant types).
That aside, a macro for Signature
would be super useful; if the signature string is invalid, I'd prefer a compile-time failure in this case, and not a runtime failure.
Both together would allow for something nice and simple (but also more compile-time validations):
let a : Array<signature!("(sasb)")> = vec!(...).into
Right, so it seems that if I want an array of non-variants, I need to use
Array::new
and pass a signature. It works, but it's eventually pretty ugly:
but why don't use use a Vec
instead? If you need to put it into a variant, you can convert back and forth to/from a Value
.
As I wrote, need to use Array
directly should be very rare.
And Array
can't be a generic type, because that'd need Value
to be a generic type too and that couldn't work for various reasons.
In GitLab by @WhyNotHugo on Apr 21, 2022, 18:45
I haven't been able to use Vec
directly.
Using a Vec<Structure>
(e.g.: let a = vec!(es);
):
error[E0308]: mismatched types
--> src/main.rs:71:36
|
71 | ("ExecStart", Value::Array(a)),
| ^ expected struct `zbus::zvariant::Array`, found struct `Vec`
|
= note: expected struct `zbus::zvariant::Array<'_>`
found struct `Vec<zbus::zvariant::Structure<'_>>`
error[E0277]: the trait bound `zbus::zvariant::Structure<'_>: Type` is not satisfied
--> src/main.rs:71:38
|
71 | ("ExecStart", Value::Array(a.into())),
| ^^^^ the trait `Type` is not implemented for `zbus::zvariant::Structure<'_>`
|
= note: required because of the requirements on the impl of `From<Vec<zbus::zvariant::Structure<'_>>>` for `zbus::zvariant::Array<'_>`
= note: required because of the requirements on the impl of `Into<zbus::zvariant::Array<'_>>` for `Vec<zbus::zvariant::Structure<'_>>`
Using let a = vec!(Value::from(es));
builds, but sends an array of variants,
not an array of structs, so it's the wrong data type an doesn't work.
I can't get an array of non-variants to work. I don't see how it's possible; once data is put into an array, some information is lost. Specifically, when later serialising there's no way to determine if it's an array of structs, or an array of variants [which are structs].
And Array can't be a generic type, because that'd need Value to be a generic type too and that couldn't work for various reasons.
I think my idea was not clear: Array can be generic in the sense that one can use something like:
array_of_ints: Array<u32>
array_of_structs: Array<Structure>
array_of_variants: Array<Value>
The generic parameter for array would just need to implement the Into<Value>
trait.
Using a
Vec<Structure>
(e.g.:let a = vec!(es);
):
Same thing about Structure
, you're not expected to be using it directly. Use a struct or tuple directly if you need that.
In GitLab by @WhyNotHugo on Apr 21, 2022, 21:13
Ooooh! This turned out to be so much simpler!
let exec_start = (command[0].clone(), command, true);
let props: Vec<(&str, Value)> = vec![
("RemainAfterExit", remain_after_exit.into()),
("ExecStart", vec![exec_start].into()),
("ExitType", exit_type.to_string().into()),
];
In GitLab by @WhyNotHugo on Apr 20, 2022, 23:52
I need to create an array with a struct. I basically, want to do this:
But
Array
seems to assume that only Variants will be put into it, so I've only been able to construct arrays with variant(struct), which is not entirely the same.Is this possible an oversight in the API?