blob: bd09e24ef6f108833d06d2754402d73c31191a4a [file] [log] [blame]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +02001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mårten Kongstad403658f2023-06-14 09:51:56 +020017use anyhow::{bail, ensure, Context, Result};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020018use clap::ValueEnum;
Mårten Kongstada1029092023-05-08 11:51:59 +020019use protobuf::Message;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020020use std::io::Read;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020021use std::path::PathBuf;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020022
Dennis Shen1dc9ad42023-05-12 00:21:55 +000023use crate::codegen_cpp::generate_cpp_code;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020024use crate::codegen_java::generate_java_code;
Mårten Kongstadf73b9632023-05-24 15:43:47 +020025use crate::codegen_rust::generate_rust_code;
Mårten Kongstad403658f2023-06-14 09:51:56 +020026use crate::protos::{
27 ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag, ProtoParsedFlags, ProtoTracepoint,
28};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020029
30pub struct Input {
Mårten Kongstad403658f2023-06-14 09:51:56 +020031 pub source: String,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020032 pub reader: Box<dyn Read>,
33}
34
Mårten Kongstad403658f2023-06-14 09:51:56 +020035impl Input {
36 fn try_parse_flags(&mut self) -> Result<ProtoParsedFlags> {
37 let mut buffer = Vec::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020038 self.reader
39 .read_to_end(&mut buffer)
40 .with_context(|| format!("failed to read {}", self.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020041 crate::protos::parsed_flags::try_from_binary_proto(&buffer)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020042 .with_context(|| self.error_context())
43 }
44
45 fn error_context(&self) -> String {
46 format!("failed to parse {}", self.source)
Mårten Kongstad403658f2023-06-14 09:51:56 +020047 }
48}
49
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020050pub struct OutputFile {
51 pub path: PathBuf, // relative to some root directory only main knows about
52 pub contents: Vec<u8>,
53}
54
Mårten Kongstad403658f2023-06-14 09:51:56 +020055const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
56const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
57
58pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>) -> Result<Vec<u8>> {
59 let mut parsed_flags = ProtoParsedFlags::new();
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020060
Mårten Kongstadfa23d292023-05-11 14:47:02 +020061 for mut input in declarations {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020062 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020063 input
64 .reader
65 .read_to_string(&mut contents)
66 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020067
68 let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020069 .with_context(|| input.error_context())?;
Mårten Kongstad30950782023-05-09 13:31:29 +020070 ensure!(
Mårten Kongstad403658f2023-06-14 09:51:56 +020071 package == flag_declarations.package(),
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020072 "failed to parse {}: expected package {}, got {}",
Mårten Kongstad30950782023-05-09 13:31:29 +020073 input.source,
Mårten Kongstad9fb58962023-05-31 13:02:13 +020074 package,
Mårten Kongstad403658f2023-06-14 09:51:56 +020075 flag_declarations.package()
Mårten Kongstad30950782023-05-09 13:31:29 +020076 );
Mårten Kongstad403658f2023-06-14 09:51:56 +020077 for mut flag_declaration in flag_declarations.flag.into_iter() {
78 crate::protos::flag_declaration::verify_fields(&flag_declaration)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020079 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020080
81 // create ParsedFlag using FlagDeclaration and default values
82 let mut parsed_flag = ProtoParsedFlag::new();
83 parsed_flag.set_package(package.to_string());
84 parsed_flag.set_name(flag_declaration.take_name());
85 parsed_flag.set_namespace(flag_declaration.take_namespace());
86 parsed_flag.set_description(flag_declaration.take_description());
Mårten Kongstad1b8636b2023-06-22 10:12:24 +020087 parsed_flag.bug.append(&mut flag_declaration.bug);
Mårten Kongstad403658f2023-06-14 09:51:56 +020088 parsed_flag.set_state(DEFAULT_FLAG_STATE);
89 parsed_flag.set_permission(DEFAULT_FLAG_PERMISSION);
90 let mut tracepoint = ProtoTracepoint::new();
91 tracepoint.set_source(input.source.clone());
92 tracepoint.set_state(DEFAULT_FLAG_STATE);
93 tracepoint.set_permission(DEFAULT_FLAG_PERMISSION);
94 parsed_flag.trace.push(tracepoint);
95
96 // verify ParsedFlag looks reasonable
97 crate::protos::parsed_flag::verify_fields(&parsed_flag)?;
98
99 // verify ParsedFlag can be added
100 ensure!(
101 parsed_flags.parsed_flag.iter().all(|other| other.name() != parsed_flag.name()),
102 "failed to declare flag {} from {}: flag already declared",
103 parsed_flag.name(),
104 input.source
105 );
106
107 // add ParsedFlag to ParsedFlags
108 parsed_flags.parsed_flag.push(parsed_flag);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200109 }
110 }
111
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200112 for mut input in values {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200113 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200114 input
115 .reader
116 .read_to_string(&mut contents)
117 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200118 let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200119 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200120 for flag_value in flag_values.flag_value.into_iter() {
121 crate::protos::flag_value::verify_fields(&flag_value)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200122 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200123
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000124 let Some(parsed_flag) = parsed_flags
125 .parsed_flag
126 .iter_mut()
127 .find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name())
128 else {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200129 // (silently) skip unknown flags
130 continue;
131 };
132
133 parsed_flag.set_state(flag_value.state());
134 parsed_flag.set_permission(flag_value.permission());
135 let mut tracepoint = ProtoTracepoint::new();
136 tracepoint.set_source(input.source.clone());
137 tracepoint.set_state(flag_value.state());
138 tracepoint.set_permission(flag_value.permission());
139 parsed_flag.trace.push(tracepoint);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200140 }
141 }
142
Zhi Dou92cf0ec2023-07-19 19:29:22 +0000143 // Create a sorted parsed_flags
144 crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200145 crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200146 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200147 parsed_flags.write_to_vec(&mut output)?;
148 Ok(output)
149}
150
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000151#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
152pub enum CodegenMode {
153 Production,
154 Test,
155}
156
157pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200158 let parsed_flags = input.try_parse_flags()?;
159 let Some(package) = find_unique_package(&parsed_flags) else {
160 bail!("no parsed flags, or the parsed flags use different packages");
161 };
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000162 generate_java_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200163}
164
Dennis Shen8d544f72023-06-29 00:45:42 +0000165pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200166 let parsed_flags = input.try_parse_flags()?;
167 let Some(package) = find_unique_package(&parsed_flags) else {
168 bail!("no parsed flags, or the parsed flags use different packages");
169 };
Dennis Shen8d544f72023-06-29 00:45:42 +0000170 generate_cpp_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200171}
172
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000173pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200174 let parsed_flags = input.try_parse_flags()?;
175 let Some(package) = find_unique_package(&parsed_flags) else {
176 bail!("no parsed flags, or the parsed flags use different packages");
177 };
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000178 generate_rust_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200179}
180
181pub fn create_device_config_defaults(mut input: Input) -> Result<Vec<u8>> {
182 let parsed_flags = input.try_parse_flags()?;
183 let mut output = Vec::new();
184 for parsed_flag in parsed_flags
185 .parsed_flag
186 .into_iter()
187 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200188 {
189 let line = format!(
Mårten Kongstad202102f2023-06-08 11:22:44 +0200190 "{}:{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200191 parsed_flag.namespace(),
192 parsed_flag.package(),
193 parsed_flag.name(),
194 match parsed_flag.state() {
195 ProtoFlagState::ENABLED => "enabled",
196 ProtoFlagState::DISABLED => "disabled",
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200197 }
198 );
199 output.extend_from_slice(line.as_bytes());
200 }
201 Ok(output)
202}
203
Mårten Kongstad403658f2023-06-14 09:51:56 +0200204pub fn create_device_config_sysprops(mut input: Input) -> Result<Vec<u8>> {
205 let parsed_flags = input.try_parse_flags()?;
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200206 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200207 for parsed_flag in parsed_flags
208 .parsed_flag
209 .into_iter()
210 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200211 {
212 let line = format!(
213 "persist.device_config.{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200214 parsed_flag.package(),
215 parsed_flag.name(),
216 match parsed_flag.state() {
217 ProtoFlagState::ENABLED => "true",
218 ProtoFlagState::DISABLED => "false",
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200219 }
220 );
221 output.extend_from_slice(line.as_bytes());
222 }
223 Ok(output)
224}
225
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200226#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
Mårten Kongstadba94e6a2023-05-16 11:00:16 +0200227pub enum DumpFormat {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200228 Text,
Mårten Kongstadea498142023-07-20 11:07:35 +0200229 Verbose,
Mårten Kongstada1029092023-05-08 11:51:59 +0200230 Protobuf,
Mårten Kongstad3228b292023-06-26 10:17:42 +0200231 Textproto,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200232}
233
Mårten Kongstad403658f2023-06-14 09:51:56 +0200234pub fn dump_parsed_flags(mut input: Vec<Input>, format: DumpFormat) -> Result<Vec<u8>> {
235 let individually_parsed_flags: Result<Vec<ProtoParsedFlags>> =
236 input.iter_mut().map(|i| i.try_parse_flags()).collect();
237 let parsed_flags: ProtoParsedFlags =
238 crate::protos::parsed_flags::merge(individually_parsed_flags?)?;
239
Mårten Kongstadaf677032023-05-17 16:18:25 +0200240 let mut output = Vec::new();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200241 match format {
242 DumpFormat::Text => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200243 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200244 let line = format!(
Mårten Kongstad3fa2f072023-07-20 09:35:05 +0200245 "{}/{}: {:?} + {:?}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200246 parsed_flag.package(),
247 parsed_flag.name(),
Mårten Kongstad3fa2f072023-07-20 09:35:05 +0200248 parsed_flag.permission(),
249 parsed_flag.state()
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200250 );
251 output.extend_from_slice(line.as_bytes());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200252 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200253 }
Mårten Kongstadea498142023-07-20 11:07:35 +0200254 DumpFormat::Verbose => {
255 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
256 let sources: Vec<_> =
257 parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
258 let line = format!(
259 "{}/{}: {:?} + {:?} ({})\n",
260 parsed_flag.package(),
261 parsed_flag.name(),
262 parsed_flag.permission(),
263 parsed_flag.state(),
264 sources.join(", ")
265 );
266 output.extend_from_slice(line.as_bytes());
267 }
268 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200269 DumpFormat::Protobuf => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200270 parsed_flags.write_to_vec(&mut output)?;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200271 }
Mårten Kongstad3228b292023-06-26 10:17:42 +0200272 DumpFormat::Textproto => {
273 let s = protobuf::text_format::print_to_string_pretty(&parsed_flags);
274 output.extend_from_slice(s.as_bytes());
275 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200276 }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200277 Ok(output)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200278}
279
Mårten Kongstad403658f2023-06-14 09:51:56 +0200280fn find_unique_package(parsed_flags: &ProtoParsedFlags) -> Option<&str> {
281 let Some(package) = parsed_flags.parsed_flag.first().map(|pf| pf.package()) else {
282 return None;
283 };
284 if parsed_flags.parsed_flag.iter().any(|pf| pf.package() != package) {
285 return None;
286 }
287 Some(package)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200288}
289
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200290#[cfg(test)]
291mod tests {
292 use super::*;
Mårten Kongstada1029092023-05-08 11:51:59 +0200293
294 #[test]
Mårten Kongstad403658f2023-06-14 09:51:56 +0200295 fn test_parse_flags() {
296 let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
297 crate::protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
298
299 let enabled_ro =
300 parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_ro").unwrap();
301 assert!(crate::protos::parsed_flag::verify_fields(enabled_ro).is_ok());
302 assert_eq!("com.android.aconfig.test", enabled_ro.package());
303 assert_eq!("enabled_ro", enabled_ro.name());
304 assert_eq!("This flag is ENABLED + READ_ONLY", enabled_ro.description());
305 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
306 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
307 assert_eq!(3, enabled_ro.trace.len());
308 assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
309 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
310 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
311 assert_eq!("tests/first.values", enabled_ro.trace[1].source());
312 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[1].state());
313 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[1].permission());
314 assert_eq!("tests/second.values", enabled_ro.trace[2].source());
315 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
316 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
317
318 assert_eq!(4, parsed_flags.parsed_flag.len());
319 for pf in parsed_flags.parsed_flag.iter() {
320 let first = pf.trace.first().unwrap();
321 assert_eq!(DEFAULT_FLAG_STATE, first.state());
322 assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
323
324 let last = pf.trace.last().unwrap();
325 assert_eq!(pf.state(), last.state());
326 assert_eq!(pf.permission(), last.permission());
327 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200328 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200329
330 #[test]
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200331 fn test_create_device_config_defaults() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200332 let input = parse_test_flags_as_input();
333 let bytes = create_device_config_defaults(input).unwrap();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200334 let text = std::str::from_utf8(&bytes).unwrap();
Mårten Kongstad202102f2023-06-08 11:22:44 +0200335 assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200336 }
337
338 #[test]
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200339 fn test_create_device_config_sysprops() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200340 let input = parse_test_flags_as_input();
341 let bytes = create_device_config_sysprops(input).unwrap();
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200342 let text = std::str::from_utf8(&bytes).unwrap();
Mårten Kongstadfbd71e22023-05-31 13:29:35 +0200343 assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200344 }
345
346 #[test]
Mårten Kongstada1029092023-05-08 11:51:59 +0200347 fn test_dump_text_format() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200348 let input = parse_test_flags_as_input();
349 let bytes = dump_parsed_flags(vec![input], DumpFormat::Text).unwrap();
Mårten Kongstada1029092023-05-08 11:51:59 +0200350 let text = std::str::from_utf8(&bytes).unwrap();
Mårten Kongstad3fa2f072023-07-20 09:35:05 +0200351 assert!(text.contains("com.android.aconfig.test/disabled_ro: READ_ONLY + DISABLED"));
Mårten Kongstada1029092023-05-08 11:51:59 +0200352 }
353
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200354 #[test]
355 fn test_dump_protobuf_format() {
Mårten Kongstad3228b292023-06-26 10:17:42 +0200356 let expected = protobuf::text_format::parse_from_str::<ProtoParsedFlags>(
357 crate::test::TEST_FLAGS_TEXTPROTO,
358 )
359 .unwrap()
360 .write_to_bytes()
361 .unwrap();
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200362
363 let input = parse_test_flags_as_input();
364 let actual = dump_parsed_flags(vec![input], DumpFormat::Protobuf).unwrap();
365
366 assert_eq!(expected, actual);
367 }
368
Mårten Kongstad3228b292023-06-26 10:17:42 +0200369 #[test]
370 fn test_dump_textproto_format() {
371 let input = parse_test_flags_as_input();
372 let bytes = dump_parsed_flags(vec![input], DumpFormat::Textproto).unwrap();
373 let text = std::str::from_utf8(&bytes).unwrap();
374 assert_eq!(crate::test::TEST_FLAGS_TEXTPROTO.trim(), text.trim());
375 }
376
Mårten Kongstad403658f2023-06-14 09:51:56 +0200377 fn parse_test_flags_as_input() -> Input {
378 let parsed_flags = crate::test::parse_test_flags();
379 let binary_proto = parsed_flags.write_to_bytes().unwrap();
380 let cursor = std::io::Cursor::new(binary_proto);
381 let reader = Box::new(cursor);
382 Input { source: "test.data".to_string(), reader }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200383 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200384}