blob: 41815b7c4d15edac631b9ad34c6db536bfae96e7 [file] [log] [blame]
Mårten Kongstadbb520722023-04-26 13:16:41 +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
17use anyhow::{anyhow, Context, Error, Result};
18
19use crate::protos::{ProtoAndroidConfig, ProtoFlag, ProtoOverride, ProtoOverrideConfig};
20
21#[derive(Debug, PartialEq, Eq)]
22pub struct Flag {
23 pub id: String,
24 pub description: String,
25 pub value: bool,
26}
27
28impl Flag {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020029 #[allow(dead_code)] // only used in unit tests
Mårten Kongstadbb520722023-04-26 13:16:41 +020030 pub fn try_from_text_proto(text_proto: &str) -> Result<Flag> {
31 let proto: ProtoFlag = crate::protos::try_from_text_proto(text_proto)
32 .with_context(|| text_proto.to_owned())?;
33 proto.try_into()
34 }
35
36 pub fn try_from_text_proto_list(text_proto: &str) -> Result<Vec<Flag>> {
37 let proto: ProtoAndroidConfig = crate::protos::try_from_text_proto(text_proto)
38 .with_context(|| text_proto.to_owned())?;
39 proto.flag.into_iter().map(|proto_flag| proto_flag.try_into()).collect()
40 }
41}
42
43impl TryFrom<ProtoFlag> for Flag {
44 type Error = Error;
45
46 fn try_from(proto: ProtoFlag) -> Result<Self, Self::Error> {
47 let Some(id) = proto.id else {
48 return Err(anyhow!("missing 'id' field"));
49 };
50 let Some(description) = proto.description else {
51 return Err(anyhow!("missing 'description' field"));
52 };
53 let Some(value) = proto.value else {
54 return Err(anyhow!("missing 'value' field"));
55 };
56 Ok(Flag { id, description, value })
57 }
58}
59
60#[derive(Debug, PartialEq, Eq)]
61pub struct Override {
62 pub id: String,
63 pub value: bool,
64}
65
66impl Override {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020067 #[allow(dead_code)] // only used in unit tests
Mårten Kongstadbb520722023-04-26 13:16:41 +020068 pub fn try_from_text_proto(text_proto: &str) -> Result<Override> {
69 let proto: ProtoOverride = crate::protos::try_from_text_proto(text_proto)?;
70 proto.try_into()
71 }
72
73 pub fn try_from_text_proto_list(text_proto: &str) -> Result<Vec<Override>> {
74 let proto: ProtoOverrideConfig = crate::protos::try_from_text_proto(text_proto)?;
75 proto.override_.into_iter().map(|proto_flag| proto_flag.try_into()).collect()
76 }
77}
78
79impl TryFrom<ProtoOverride> for Override {
80 type Error = Error;
81
82 fn try_from(proto: ProtoOverride) -> Result<Self, Self::Error> {
83 let Some(id) = proto.id else {
84 return Err(anyhow!("missing 'id' field"));
85 };
86 let Some(value) = proto.value else {
87 return Err(anyhow!("missing 'value' field"));
88 };
89 Ok(Override { id, value })
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_flag_try_from_text_proto() {
99 let expected = Flag {
100 id: "1234".to_owned(),
101 description: "Description of the flag".to_owned(),
102 value: true,
103 };
104
105 let s = r#"
106 id: "1234"
107 description: "Description of the flag"
108 value: true
109 "#;
110 let actual = Flag::try_from_text_proto(s).unwrap();
111
112 assert_eq!(expected, actual);
113 }
114
115 #[test]
116 fn test_flag_try_from_text_proto_missing_field() {
117 let s = r#"
118 description: "Description of the flag"
119 value: true
120 "#;
121 let error = Flag::try_from_text_proto(s).unwrap_err();
122 assert!(format!("{:?}", error).contains("Message not initialized"));
123 }
124
125 #[test]
126 fn test_flag_try_from_text_proto_list() {
127 let expected = vec![
128 Flag { id: "a".to_owned(), description: "A".to_owned(), value: true },
129 Flag { id: "b".to_owned(), description: "B".to_owned(), value: false },
130 ];
131
132 let s = r#"
133 flag {
134 id: "a"
135 description: "A"
136 value: true
137 }
138 flag {
139 id: "b"
140 description: "B"
141 value: false
142 }
143 "#;
144 let actual = Flag::try_from_text_proto_list(s).unwrap();
145
146 assert_eq!(expected, actual);
147 }
148
149 #[test]
150 fn test_override_try_from_text_proto_list() {
151 let expected = Override { id: "1234".to_owned(), value: true };
152
153 let s = r#"
154 id: "1234"
155 value: true
156 "#;
157 let actual = Override::try_from_text_proto(s).unwrap();
158
159 assert_eq!(expected, actual);
160 }
161}