firefly_meta/meta.rs
1use serde::{Deserialize, Serialize};
2
3#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
4#[allow(clippy::module_name_repetitions)]
5pub struct Meta<'a> {
6 pub app_id: &'a str,
7 /// App name is shown in the launcher in the list of apps.
8 pub app_name: &'a str,
9 pub author_id: &'a str,
10 pub author_name: &'a str,
11 /// Launcher is the app that starts first when runtime is launched.
12 pub launcher: bool,
13 /// Let the app to use privileged and dangerous runtime API.
14 pub sudo: bool,
15 /// The ever-incrementing version number of the app build.
16 /// Used by netplay to ensure both devices running the same version.
17 pub version: u32,
18}
19
20impl<'a> Meta<'a> {
21 /// Load metadata from bytes generated by [`Meta::encode`].
22 ///
23 /// # Errors
24 ///
25 /// May return an error if the buffer does not contain valid metadata.
26 pub fn decode(s: &'a [u8]) -> Result<Self, postcard::Error> {
27 postcard::from_bytes(s)
28 }
29
30 /// Encode the matadata using the buffer.
31 ///
32 /// The buffer is required to avoid allocations on the crate side.
33 /// Use [`Meta::size`] to calculate the required buffer size.
34 ///
35 /// # Errors
36 ///
37 /// May return an error if the buffer is no big enough.
38 pub fn encode<'b>(&self, buf: &'b mut [u8]) -> Result<&'b mut [u8], postcard::Error> {
39 postcard::to_slice(self, buf)
40 }
41
42 /// Calculate the buffer size required to encode the meta.
43 #[must_use]
44 #[allow(clippy::missing_panics_doc)]
45 pub fn size(&self) -> usize {
46 let flavor = postcard::ser_flavors::Size::default();
47 postcard::serialize_with_flavor(self, flavor).unwrap()
48 }
49}
50
51/// A struct with only a few safe fields from Meta.
52///
53/// It is used to serialize information about an app outside of the app dir.
54/// Since it is outside, it escapes the hash and signature checks
55/// and so it must not store any information that must be verified before use.
56#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
57#[allow(clippy::module_name_repetitions)]
58pub struct ShortMeta<'a> {
59 pub app_id: &'a str,
60 pub author_id: &'a str,
61}
62
63impl<'a> ShortMeta<'a> {
64 /// Load metadata from bytes generated by [`ShortMeta::encode`].
65 ///
66 /// # Errors
67 ///
68 /// May return an error if the buffer does not contain valid metadata.
69 pub fn decode(s: &'a [u8]) -> Result<Self, postcard::Error> {
70 postcard::from_bytes(s)
71 }
72
73 /// Encode the matadata using the buffer.
74 ///
75 /// The buffer is required to avoid allocations on the crate side.
76 /// Use [`ShortMeta::size`] to calculate the required buffer size.
77 ///
78 /// # Errors
79 ///
80 /// May return an error if the buffer is no big enough.
81 pub fn encode<'b>(&self, buf: &'b mut [u8]) -> Result<&'b mut [u8], postcard::Error> {
82 postcard::to_slice(self, buf)
83 }
84
85 /// Calculate the buffer size required to encode the meta.
86 #[must_use]
87 #[allow(clippy::missing_panics_doc)]
88 pub fn size(&self) -> usize {
89 let flavor = postcard::ser_flavors::Size::default();
90 postcard::serialize_with_flavor(self, flavor).unwrap()
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_roundtrip() {
100 let given = Meta {
101 app_id: "some-app-id",
102 app_name: "Some App Name",
103 author_id: "some-author-id",
104 author_name: "Some Author Name",
105 launcher: false,
106 sudo: false,
107 version: 12,
108 };
109 let mut buf = vec![0; given.size()];
110 let raw = given.encode(&mut buf).unwrap();
111 let actual = Meta::decode(raw).unwrap();
112 assert_eq!(given, actual);
113 }
114}