Raptor 4.0.0-rc.1
A fast and space-efficient pre-filter
Loading...
Searching...
No Matches
validators.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2026 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2026 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <sharg/parser.hpp>
13
14#include <seqan3/io/sequence_file/input.hpp>
15
17
18namespace raptor::detail
19{
20
29{
30 static std::vector<std::string> const result{
31 seqan3::detail::valid_file_extensions<typename seqan3::sequence_file_input<>::valid_formats>()};
32 return result;
33}
34
37{
38 static std::vector<std::string> const result = []()
39 {
41#ifdef SEQAN3_HAS_BZIP2
42 result.push_back("bz2");
43#endif
44#ifdef SEQAN3_HAS_ZLIB
45 result.push_back("gz");
46 result.push_back("bgzf");
47#endif
48 return result;
49 }(); // GCOVR_EXCL_LINE
50 return result;
51}
52
55{
56 static std::vector<std::string> const result = []()
57 {
60 {
61 result = sequence_extensions(); // GCOVR_EXCL_LINE
62 }
63 else
64 {
65 for (auto && sequence_extension : sequence_extensions())
66 {
67 result.push_back(sequence_extension);
68 for (auto && compression_extension : compression_extensions())
69 {
70 result.push_back(sequence_extension);
71 result.back() += '.';
72 result.back() += compression_extension;
73 }
74 }
75 }
76 return result;
77 }();
78 return result;
79}
80
81} // namespace raptor::detail
82
83namespace raptor
84{
85
87{
88 using option_value_type = size_t;
89
90 void operator()(option_value_type const & val) const
91 {
92 if (!std::has_single_bit(val))
93 throw sharg::validation_error{"The value must be a power of two."};
94 }
95
96 static std::string get_help_page_message()
97 {
98 return "Value must be a power of two.";
99 }
100};
101
103{
104public:
105 using option_value_type = size_t;
106
107 positive_integer_validator() = default;
109 positive_integer_validator & operator=(positive_integer_validator const &) = default;
112 ~positive_integer_validator() = default;
113
114 explicit positive_integer_validator(bool const is_zero_positive_) : is_zero_positive{is_zero_positive_}
115 {}
116
117 void operator()(option_value_type const & val) const
118 {
119 if (!is_zero_positive && !val)
120 throw sharg::validation_error{"The value must be a positive integer."};
121 }
122
123 std::string get_help_page_message() const
124 {
125 if (is_zero_positive)
126 return "Value must be a positive integer or 0.";
127 else
128 return "Value must be a positive integer.";
129 }
130
131private:
132 bool is_zero_positive{false};
133};
134
136{
137public:
139
140 size_validator() = default;
141 size_validator(size_validator const &) = default;
142 size_validator & operator=(size_validator const &) = default;
143 size_validator(size_validator &&) = default;
144 size_validator & operator=(size_validator &&) = default;
145 ~size_validator() = default;
146
147 explicit size_validator(std::string const & pattern) : expression{pattern}
148 {}
149
150 void operator()(option_value_type const & cmp) const
151 {
152 if (!std::regex_match(cmp, expression))
153 throw sharg::validation_error{
154 seqan3::detail::to_string("Value ",
155 cmp,
156 " must be an integer followed by [k,m,g,t] (case insensitive).")};
157 }
158
159 template <std::ranges::forward_range range_type>
161 void operator()(range_type const & v) const
162 {
163 std::for_each(v.begin(),
164 v.end(),
165 [&](auto cmp)
166 {
167 (*this)(cmp);
168 });
169 }
170
171 std::string get_help_page_message() const
172 {
173 return "Must be an integer followed by [k,m,g,t] (case insensitive).";
174 }
175
176private:
177 std::regex expression;
178};
179
181{
182public:
184
185 bin_validator() = default;
186 bin_validator(bin_validator const &) = default;
187 bin_validator & operator=(bin_validator const &) = default;
188 bin_validator(bin_validator &&) = default;
189 bin_validator & operator=(bin_validator &&) = default;
190 ~bin_validator() = default;
191
192 void operator()(option_value_type const & values) const
193 {
194 if (values.empty())
195 throw sharg::validation_error{"The list of input files cannot be empty."};
196
197 bool const is_minimiser_input = std::filesystem::path{values[0][0]}.extension() == ".minimiser";
198
199 for (std::vector<std::string> const & vector_of_paths : values)
200 {
201 for (std::string const & value : vector_of_paths)
202 {
203 std::filesystem::path const file_path{value};
204
205 if (is_minimiser_input && (file_path.extension() != ".minimiser"))
206 throw sharg::validation_error{"You cannot mix sequence and minimiser files as input."};
207 if (!std::filesystem::exists(file_path))
208 throw sharg::validation_error{"The file " + value + " does not exist."};
209 if (std::filesystem::file_size(file_path) == 0u)
210 throw sharg::validation_error{"The file " + value + " is empty."};
211
212 if (is_minimiser_input)
213 minimiser_file_validator(file_path);
214 else
215 sequence_file_validator(file_path);
216 }
217 }
218 }
219
220 std::string get_help_page_message() const
221 {
222 return seqan3::detail::to_string("The file must contain at least one file path per line, with multiple paths "
223 "being separated by a whitespace. Each line in the file corresponds to one "
224 "bin. Valid extensions for the paths in the file are [minimiser] when "
225 "using preprocessed input from \\fBraptor prepare\\fP, and ",
226 raptor::detail::sequence_extensions(),
227#if defined(SEQAN3_HAS_BZIP2) || defined(SEQAN3_HAS_ZLIB)
228 ", possibly followed by ",
229 raptor::detail::compression_extensions(),
230#endif
231 ". ");
232 }
233
234private:
235 sharg::input_file_validator minimiser_file_validator{{"minimiser"}};
236
237public:
238 sharg::input_file_validator sequence_file_validator{raptor::detail::combined_extensions()};
239};
240
242{
243public:
245
246 output_directory_validator() = default;
248 output_directory_validator & operator=(output_directory_validator const &) = default;
251 ~output_directory_validator() = default;
252
253 void operator()(option_value_type const & value) const
254 {
255 std::filesystem::path const out_dir{value};
256 std::error_code ec{};
258 if (ec)
259 // GCOVR_EXCL_START
260 throw sharg::validation_error{
261 sharg::detail::to_string("Failed to create directory\"", out_dir.c_str(), "\": ", ec.message())};
262 // GCOVR_EXCL_STOP
263
264 validator(out_dir);
265 }
266
267 std::string get_help_page_message() const
268 {
269 return "A valid path for the output directory.";
270 }
271
272private:
273 sharg::output_directory_validator validator{};
274};
275
277{
278public:
280
281 output_file_validator() = default;
283 output_file_validator & operator=(output_file_validator const &) = default;
285 output_file_validator & operator=(output_file_validator &&) = default;
286 ~output_file_validator() = default;
287
288 output_file_validator(sharg::output_file_open_options mode) : validator{mode}
289 {}
290
291 void operator()(option_value_type const & value) const
292 {
293 std::filesystem::path const out_path{value};
294 std::filesystem::path const out_dir{out_path.parent_path()};
295 if (!out_dir.empty())
296 {
297 // GCOVR_EXCL_START
298 std::error_code ec{};
300 if (ec)
301 throw sharg::validation_error{
302 sharg::detail::to_string("Failed to create directory \"", out_dir.c_str(), "\": ", ec.message())};
303 // GCOVR_EXCL_STOP
304 }
305
306 validator(out_path);
307 }
308
309 std::string get_help_page_message() const
310 {
311 return "A valid path for the output file. Write permissions must be granted.";
312 }
313
314private:
315 sharg::output_file_validator validator{sharg::output_file_open_options::open_or_create};
316};
317
318class sequence_file_validator : public sharg::input_file_validator
319{
320private:
321 using base_t = sharg::input_file_validator;
322
323public:
324 using base_t::base_t;
325
326 std::string get_help_page_message() const
327 {
328 return seqan3::detail::to_string(
329 "The input file must exist and read permissions must be granted. Valid file extensions are ",
330 raptor::detail::sequence_extensions(),
331#if defined(SEQAN3_HAS_BZIP2) || defined(SEQAN3_HAS_ZLIB)
332 ", possibly followed by ",
333 raptor::detail::compression_extensions(),
334#endif
335 ". ");
336 }
337};
338
339} // namespace raptor
T back(T... args)
Definition validators.hpp:181
Definition validators.hpp:242
Definition validators.hpp:277
Definition validators.hpp:103
Definition validators.hpp:319
Definition validators.hpp:136
T create_directories(T... args)
T empty(T... args)
T exists(T... args)
T file_size(T... args)
T for_each(T... args)
T has_single_bit(T... args)
Provides raptor::window.
T min(T... args)
T parent_path(T... args)
T push_back(T... args)
T regex_match(T... args)
Definition validators.hpp:87
std::vector< std::string > const & compression_extensions()
The valid extensions of a compressed file.
Definition validators.hpp:36
std::vector< std::string > const & combined_extensions()
The valid extensions of a sequence file, including compressed ones.
Definition validators.hpp:54
std::vector< std::string > const & sequence_extensions()
The valid extensions of a sequence file.
Definition validators.hpp:28
Hide me