• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 #pragma once
18 
19 #include <algorithm>
20 #include <memory>
21 #include <string>
22 
23 #include "common/libs/utils/collect.h"
24 #include "common/libs/utils/contains.h"
25 #include "common/libs/utils/result.h"
26 #include "host/commands/cvd/selector/constant_reference.h"
27 #include "host/commands/cvd/selector/instance_database_types.h"
28 
29 namespace cuttlefish {
30 namespace selector {
31 
32 Result<std::string> GetCuttlefishConfigPath(const std::string& home);
33 
34 std::string GenInternalGroupName();
35 std::string GenDefaultGroupName();
36 std::string LocalDeviceNameRule(const std::string& group_name,
37                                 const std::string& instance_name);
38 
39 // [A-Za-z0-9_]+, e.g. 0, tv, my_phone07, etc
40 // Or, it can include "-" in the middle
41 // ([A-Za-z0-9_]+[-])*[A-Za-z0-9_]
42 bool IsValidInstanceName(const std::string& token);
43 
44 // [A-Za-z_][A-Za-z0-9_]*, e.g. cool_group, cv0_d, cf, etc
45 // but can't start with [0-9]
46 bool IsValidGroupName(const std::string& token);
47 
48 // <valid group name>-<valid instance name>
49 bool IsValidDeviceName(const std::string& token);
50 
51 struct DeviceName {
52   std::string group_name;
53   std::string per_instance_name;
54 };
55 Result<DeviceName> BreakDeviceName(const std::string& device_name);
56 
57 /**
58  * Runs simple tests to see if it could potentially be a host artifacts dir
59  *
60  */
61 bool PotentiallyHostArtifactsPath(const std::string& host_binaries_dir);
62 
63 /**
64  * simply returns:
65  *
66  * "Only up to n must match" or
67  * "Only up to n must match by field " + FieldName
68  *
69  */
70 std::string GenerateTooManyInstancesErrorMsg(const int n,
71                                              const std::string& field_name);
72 
73 /**
74  * return all the elements in container that satisfies predicate.
75  *
76  * Container has Wrappers, where each Wrapper is typically,
77  * std::unique/shared_ptr of T, or some wrapper of T, etc. Set is a set of T.
78  *
79  * This method returns the Set of T, as long as its corresponding Wrapper in
80  * Container meets the predicate.
81  */
82 template <typename T, typename Wrapper, typename Set, typename Container>
Collect(const Container & container,std::function<bool (const Wrapper &)> predicate,std::function<T (const Wrapper &)> convert)83 Set Collect(const Container& container,
84             std::function<bool(const Wrapper&)> predicate,
85             std::function<T(const Wrapper&)> convert) {
86   Set output;
87   for (const auto& t : container) {
88     if (!predicate(t)) {
89       continue;
90     }
91     output.insert(convert(t));
92   }
93   return output;
94 }
95 
96 /*
97  * Returns a Set of ConstRef<T>, which essentially satisfies "predicate"
98  *
99  * Container has a list/set of std::unique_ptr<T>. We collect all the
100  * const references of each object owned by Container, which meets the
101  * condition defined by predicate.
102  *
103  */
104 template <typename T, typename Container>
CollectToSet(Container && container,std::function<bool (const std::unique_ptr<T> &)> predicate)105 Set<ConstRef<T>> CollectToSet(
106     Container&& container,
107     std::function<bool(const std::unique_ptr<T>&)> predicate) {
108   auto convert = [](const std::unique_ptr<T>& uniq_ptr) {
109     return Cref(*uniq_ptr);
110   };
111   return Collect<ConstRef<T>, std::unique_ptr<T>, Set<ConstRef<T>>>(
112       std::forward<Container>(container), std::move(predicate),
113       std::move(convert));
114 }
115 
116 /**
117  * Given:
118  *  Containers have a list of n `Container`s. Each Container may have
119  *  m Element. Each is stored as a unique_ptr.
120  *
121  * Goal:
122  *  To collect Elements from each Container with Container's APIs. The
123  *  collected Elements meet the condition implicitly defined in collector.
124  *
125  * E.g. InstanceDatabase has InstanceGroups, each has Instances. We want
126  * all the Instances its build-target was TV. Then, collector will look
127  * like this:
128  * [&build_target](const std::unique_ptr<InstanceGroup>& group) {
129  *   return group->FindByBuildTarget(build_target);
130  * }
131  *
132  * We take the union of all the returned subsets from each collector call.
133  */
134 template <typename Element, typename Container, typename Containers>
CollectAllElements(std::function<Result<Set<ConstRef<Element>>> (const std::unique_ptr<Container> &)> collector,const Containers & outermost_container)135 Result<Set<ConstRef<Element>>> CollectAllElements(
136     std::function<
137         Result<Set<ConstRef<Element>>>(const std::unique_ptr<Container>&)>
138         collector,
139     const Containers& outermost_container) {
140   Set<ConstRef<Element>> output;
141   for (const auto& container_ptr : outermost_container) {
142     auto subset = CF_EXPECT(collector(container_ptr));
143     output.insert(subset.cbegin(), subset.cend());
144   }
145   return {output};
146 }
147 
148 template <typename S>
AtMostOne(S && s,const std::string & err_msg)149 Result<typename std::remove_reference<S>::type> AtMostOne(
150     S&& s, const std::string& err_msg) {
151   CF_EXPECT(AtMostN(std::forward<S>(s), 1), err_msg);
152   return {std::forward<S>(s)};
153 }
154 
155 template <typename RetSet, typename AnyContainer>
Intersection(const RetSet & u,AnyContainer && v)156 RetSet Intersection(const RetSet& u, AnyContainer&& v) {
157   RetSet result;
158   if (u.empty() || v.empty()) {
159     return result;
160   }
161   for (auto const& e : v) {
162     if (Contains(u, e)) {
163       result.insert(e);
164     }
165   }
166   return result;
167 }
168 
169 template <typename RetSet, typename AnyContainer, typename... Containers>
Intersection(const RetSet & u,AnyContainer && v,Containers &&...s)170 RetSet Intersection(const RetSet& u, AnyContainer&& v, Containers&&... s) {
171   RetSet first = Intersection(u, std::forward<AnyContainer>(v));
172   if (first.empty()) {
173     return first;
174   }
175   return Intersection(first, std::forward<Containers>(s)...);
176 }
177 
178 }  // namespace selector
179 }  // namespace cuttlefish
180