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