Flox Package Database 1
CRUD Operations on Nix Package Metadata
Loading...
Searching...
No Matches
util.hh
Go to the documentation of this file.
1/* ========================================================================== *
2 *
3 * @file flox/core/util.hh
4 *
5 * @brief Miscellaneous helper functions.
6 *
7 *
8 * -------------------------------------------------------------------------- */
9
10#pragma once
11
12#include <filesystem>
13#include <initializer_list>
14#include <sstream>
15#include <string> // For `std::string' and `std::string_view'
16#include <string_view>
17#include <variant>
18#include <vector>
19
20#include <nix/attrs.hh>
21#include <nix/flake/flakeref.hh>
22#include <nlohmann/json.hpp>
23
25#include "flox/core/types.hh"
26
27
28/* -------------------------------------------------------------------------- */
29
30/* Backported from C++20a for C++20b compatability. */
31
38template<class... Ts>
39struct overloaded : Ts...
40{
41 using Ts::operator()...;
42};
43
44template<class... Ts>
45overloaded( Ts... ) -> overloaded<Ts...>;
46
47
48/* -------------------------------------------------------------------------- */
49
54namespace nlohmann {
55
56/* -------------------------------------------------------------------------- */
57
59template<typename A, typename B>
60struct adl_serializer<std::variant<A, B>>
61{
62
64 static void
65 to_json( json & jto, const std::variant<A, B> & var )
66 {
67 if ( std::holds_alternative<A>( var ) ) { jto = std::get<A>( var ); }
68 else { jto = std::get<B>( var ); }
69 }
70
72 static void
73 from_json( const json & jfrom, std::variant<A, B> & var )
74 {
75 try
76 {
77 var = jfrom.template get<A>();
78 }
79 catch ( ... )
80 {
81 var = jfrom.template get<B>();
82 }
83 }
84
85}; /* End struct `adl_serializer<std::variant<A, B>>' */
86
87
88/* -------------------------------------------------------------------------- */
89
103template<typename A, typename... Types>
104struct adl_serializer<std::variant<A, Types...>>
105{
106
108 static void
109 to_json( json & jto, const std::variant<A, Types...> & var )
110 {
111 /* This _unwraps_ the inner type and calls the proper `to_json'.
112 * The compiler does the heavy lifting for us here <3. */
113 std::visit( [&]( auto unwrapped ) -> void { jto = unwrapped; }, var );
114 }
115
117 static void
118 from_json( const json & jfrom, std::variant<A, Types...> & var )
119 {
120 /* Try getting typename `A', or recur. */
121 try
122 {
123 var = jfrom.template get<A>();
124 }
125 catch ( ... )
126 {
127 /* Strip typename `A' from variant, and call recursively. */
128 using next_variant = std::variant<Types...>;
129
130 /* Coerce to `next_variant' type. */
131 next_variant next = jfrom.template get<next_variant>();
132 std::visit( [&]( auto unwrapped ) -> void { var = unwrapped; }, next );
133 }
134 }
135
136}; /* End struct `adl_serializer<std::variant<A, Types...>>' */
137
138
139/* -------------------------------------------------------------------------- */
140
142template<>
143struct adl_serializer<nix::fetchers::Attrs>
144{
145
147 static void
148 to_json( json & jto, const nix::fetchers::Attrs & attrs )
149 {
150 /* That was easy. */
151 jto = nix::fetchers::attrsToJSON( attrs );
152 }
153
155 static void
156 from_json( const json & jfrom, nix::fetchers::Attrs & attrs )
157 {
158 /* That was easy. */
159 attrs = nix::fetchers::jsonToAttrs( jfrom );
160 }
161
162}; /* End struct `adl_serializer<nix::fetchers::Attrs>' */
163
164
165/* -------------------------------------------------------------------------- */
166
168template<>
169struct adl_serializer<nix::FlakeRef>
170{
171
173 static void
174 to_json( json & jto, const nix::FlakeRef & ref )
175 {
176 /* That was easy. */
177 jto = nix::fetchers::attrsToJSON( ref.toAttrs() );
178 }
179
181 static nix::FlakeRef
182 from_json( const json & jfrom )
183 {
184 if ( jfrom.is_object() )
185 {
186 return { nix::FlakeRef::fromAttrs(
187 nix::fetchers::jsonToAttrs( jfrom ) ) };
188 }
189 return { nix::parseFlakeRef( jfrom.get<std::string>() ) };
190 }
191
192}; /* End struct `adl_serializer<nix::FlakeRef>' */
193
194
195/* -------------------------------------------------------------------------- */
196
197} // namespace nlohmann
198
199
200/* -------------------------------------------------------------------------- */
201
202namespace flox {
203
204/* -------------------------------------------------------------------------- */
205
207inline static const std::vector<std::string> &
209{
210 static const std::vector<std::string> defaultSystems
211 = { "x86_64-linux", "aarch64-linux", "x86_64-darwin", "aarch64-darwin" };
212 return defaultSystems;
213}
214
215
217inline static const std::vector<std::string> &
219{
220 static const std::vector<std::string> defaultSubtrees
221 = { "packages", "legacyPackages" };
222 return defaultSubtrees;
223}
224
225
226/* -------------------------------------------------------------------------- */
227
233bool
234isSQLiteDb( const std::string & dbPath );
235
236
237/* -------------------------------------------------------------------------- */
238
244nix::FlakeRef
245parseFlakeRef( const std::string & flakeRef );
246
247
248/* -------------------------------------------------------------------------- */
249
255nlohmann::json
256parseOrReadJSONObject( const std::string & jsonOrPath );
257
258
259/* -------------------------------------------------------------------------- */
260
262nlohmann::json
263tomlToJSON( std::string_view toml );
264
265
266/* -------------------------------------------------------------------------- */
267
269nlohmann::json
270yamlToJSON( std::string_view yaml );
271
272
273/* -------------------------------------------------------------------------- */
274
282nlohmann::json
283readAndCoerceJSON( const std::filesystem::path & path );
284
285
286/* -------------------------------------------------------------------------- */
287
293std::vector<std::string>
294splitAttrPath( std::string_view path );
295
296
297/* -------------------------------------------------------------------------- */
298
304bool
305isUInt( std::string_view str );
306
307
308/* -------------------------------------------------------------------------- */
309
316bool
317hasPrefix( std::string_view prefix, std::string_view str );
318
319
320/* -------------------------------------------------------------------------- */
321
323std::string &
324ltrim( std::string & str );
325
327std::string &
328rtrim( std::string & str );
329
331std::string &
332trim( std::string & str );
333
334
336[[nodiscard]] std::string
337ltrim_copy( std::string_view str );
338
340[[nodiscard]] std::string
341rtrim_copy( std::string_view str );
342
344[[nodiscard]] std::string
345trim_copy( std::string_view str );
346
347
348/* -------------------------------------------------------------------------- */
349
353std::string
354extract_json_errmsg( nlohmann::json::exception & err );
355
356/* -------------------------------------------------------------------------- */
357
363template<typename Exception = FloxException>
364static void
365assertIsJSONObject( const nlohmann::json & value,
366 const std::string & who = "JSON value" )
367{
368 if ( ! value.is_object() )
369 {
370 std::stringstream oss;
371 oss << "expected " << who << " to be an object, but found "
372 << ( value.is_array() ? "an" : "a" ) << ' ' << value.type_name()
373 << '.';
374 throw Exception( oss.str() );
375 }
376}
377
378
379/* -------------------------------------------------------------------------- */
380
389template<typename T>
390std::vector<T>
391merge_vectors( const std::vector<T> & lower, const std::vector<T> & higher )
392{
393 std::vector<T> merged = higher;
394 for ( const auto & value : lower )
395 {
396 if ( std::find( merged.begin(), merged.end(), value ) == merged.end() )
397 {
398 merged.emplace_back( value );
399 }
400 }
401 return merged;
402}
403
404
405/* -------------------------------------------------------------------------- */
406
411template<typename T>
412[[nodiscard]] std::vector<std::optional<T>>
413vectorMapOptional( const std::vector<T> & orig )
414{
415 std::vector<std::optional<T>> rsl;
416 for ( const T & val : orig )
417 {
418 rsl.emplace_back( std::make_optional<T>( val ) );
419 }
420 return rsl;
421}
422
423/* -------------------------------------------------------------------------- */
424
428std::string
429displayableGlobbedPath( const AttrPathGlob & attrs );
430
431/* -------------------------------------------------------------------------- */
432
433} // namespace flox
434
435
436/* -------------------------------------------------------------------------- *
437 *
438 *
439 *
440 * ========================================================================== */
Definitions of various std::exception children used for throwing errors with nice messages and typed ...
Interfaces for use by flox.
Definition: command.cc:29
std::string & trim(std::string &str)
trim from both ends ( in place ).
Definition: util.cc:259
std::string & ltrim(std::string &str)
trim from start ( in place ).
Definition: util.cc:236
std::vector< std::string > splitAttrPath(std::string_view path)
Split an attribute path string.
Definition: util.cc:140
bool hasPrefix(std::string_view prefix, std::string_view str)
Does the string @str have the prefix prefix?
Definition: util.cc:226
std::string & rtrim(std::string &str)
trim from end ( in place ).
Definition: util.cc:247
std::string trim_copy(std::string_view str)
trim from both ends ( copying ).
Definition: util.cc:284
nix::FlakeRef parseFlakeRef(const std::string &flakeRef)
Parse a flake reference from either a JSON attrset or URI string.
Definition: util.cc:76
static const std::vector< std::string > & getDefaultSubtrees()
‘flake’ subtrees to resolve/search in.
Definition: util.hh:218
std::vector< T > merge_vectors(const std::vector< T > &lower, const std::vector< T > &higher)
Merge two std::vector containers by putting all elements of the higher prioirty vector first,...
Definition: util.hh:391
nlohmann::json tomlToJSON(std::string_view toml)
Convert a TOML string to JSON.
static const std::vector< std::string > & getDefaultSystems()
Systems to resolve/search in.
Definition: util.hh:208
std::string displayableGlobbedPath(const flox::AttrPathGlob &attrs)
Convert a AttrPathGlob to a string for display.
Definition: util.cc:309
std::vector< std::optional< T > > vectorMapOptional(const std::vector< T > &orig)
Constructs a std::vector<std::optional<T>> from a std::vector<T>.
Definition: util.hh:413
bool isUInt(std::string_view str)
Is the string @str a positive natural number?
Definition: util.cc:212
std::vector< std::optional< std::string > > AttrPathGlob
An attribute path which may contain null members to represent globs.
Definition: types.hh:41
bool isSQLiteDb(const std::string &dbPath)
Detect if a path is a SQLite3 database file.
Definition: util.cc:35
std::string rtrim_copy(std::string_view str)
trim from end ( copying ).
Definition: util.cc:276
std::string ltrim_copy(std::string_view str)
trim from start ( copying ).
Definition: util.cc:268
static void assertIsJSONObject(const nlohmann::json &value, const std::string &who="JSON value")
Assert that a JSON value is an object, or throw an exception.
Definition: util.hh:365
nlohmann::json parseOrReadJSONObject(const std::string &jsonOrPath)
Parse a JSON object from an inline string or a path to a JSON file.
Definition: util.cc:88
std::string extract_json_errmsg(nlohmann::json::exception &err)
Extract the user-friendly portion of a nlohmann::json::exception.
Definition: util.cc:295
nlohmann::json readAndCoerceJSON(const std::filesystem::path &path)
Read a file and coerce its contents to JSON based on its extension.
Definition: util.cc:102
nlohmann::json yamlToJSON(std::string_view yaml)
Convert a YAML string to JSON.
Extension to the ‘nlohmann::json’ serializer to support additional Argument Dependent Lookup (ADL) ty...
Definition: util.hh:54
static nix::FlakeRef from_json(const json &jfrom)
Move-only conversion of a JSON object to a nix::FlakeRef.
Definition: util.hh:182
static void to_json(json &jto, const nix::FlakeRef &ref)
Convert a nix::FlakeRef to a JSON object.
Definition: util.hh:174
static void to_json(json &jto, const nix::fetchers::Attrs &attrs)
Convert a nix::fetchers::Attrs to a JSON object.
Definition: util.hh:148
static void from_json(const json &jfrom, nix::fetchers::Attrs &attrs)
Convert a JSON object to a nix::fetchers::Attrs.
Definition: util.hh:156
static void from_json(const json &jfrom, std::variant< A, B > &var)
Convert a JSON type to a std::variant<A, B>.
Definition: util.hh:73
static void to_json(json &jto, const std::variant< A, B > &var)
Convert a std::variant<A, B> to a JSON type.
Definition: util.hh:65
static void to_json(json &jto, const std::variant< A, Types... > &var)
Convert a std::variant<A, Types...> to a JSON type.
Definition: util.hh:109
static void from_json(const json &jfrom, std::variant< A, Types... > &var)
Convert a JSON type to a std::variant<Types...>.
Definition: util.hh:118
Helper type for std::visit( overloaded { ... }, x ); pattern.
Definition: util.hh:40
Miscellaneous typedefs and aliases.