mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 00:22:10 +03:00
Unify Retry and Repeat types with Count.
This commit is contained in:
parent
25d6716145
commit
1cdc491867
@ -31,7 +31,7 @@ error: Invalid variable type
|
||||
| GET http://localhost:8000/unused
|
||||
| ...
|
||||
29 | repeat: {{count}}
|
||||
| ^^^^^ expecting integer, actual value is integer <-2>
|
||||
| ^^^^^ expecting integer >= -1, actual value is integer <-2>
|
||||
|
|
||||
|
||||
error: Invalid variable type
|
||||
@ -58,6 +58,6 @@ error: Invalid variable type
|
||||
| GET http://localhost:8000/unused
|
||||
| ...
|
||||
50 | retry: {{count}}
|
||||
| ^^^^^ expecting integer, actual value is foo
|
||||
| ^^^^^ expecting integer, actual value is string <foo>
|
||||
|
|
||||
|
||||
|
@ -24,7 +24,7 @@ use std::{env, fs, io};
|
||||
|
||||
use clap::ArgMatches;
|
||||
use hurl::runner::{Input, Value};
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
use super::variables::{parse as parse_variable, parse_value};
|
||||
use super::CliOptionsError;
|
||||
@ -366,10 +366,10 @@ pub fn proxy(arg_matches: &ArgMatches) -> Option<String> {
|
||||
get::<String>(arg_matches, "proxy")
|
||||
}
|
||||
|
||||
pub fn repeat(arg_matches: &ArgMatches) -> Option<Repeat> {
|
||||
pub fn repeat(arg_matches: &ArgMatches) -> Option<Count> {
|
||||
match get::<i32>(arg_matches, "repeat") {
|
||||
Some(-1) => Some(Repeat::Forever),
|
||||
Some(n) => Some(Repeat::Count(n as usize)),
|
||||
Some(-1) => Some(Count::Infinite),
|
||||
Some(n) => Some(Count::Finite(n as usize)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@ -378,10 +378,10 @@ pub fn resolves(arg_matches: &ArgMatches) -> Vec<String> {
|
||||
get_strings(arg_matches, "resolve").unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn retry(arg_matches: &ArgMatches) -> Option<Retry> {
|
||||
pub fn retry(arg_matches: &ArgMatches) -> Option<Count> {
|
||||
match get::<i32>(arg_matches, "retry") {
|
||||
Some(-1) => Some(Retry::Infinite),
|
||||
Some(r) => Some(Retry::Finite(r as usize)),
|
||||
Some(-1) => Some(Count::Infinite),
|
||||
Some(r) => Some(Count::Finite(r as usize)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use hurl_core::ast::Entry;
|
||||
use crate::cli;
|
||||
use crate::runner::{RunnerOptions, RunnerOptionsBuilder, Value};
|
||||
pub use error::CliOptionsError;
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
/// Represents the list of all options that can be used in Hurl command line.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -81,9 +81,9 @@ pub struct CliOptions {
|
||||
pub path_as_is: bool,
|
||||
pub progress_bar: bool,
|
||||
pub proxy: Option<String>,
|
||||
pub repeat: Option<Repeat>,
|
||||
pub repeat: Option<Count>,
|
||||
pub resolves: Vec<String>,
|
||||
pub retry: Option<Retry>,
|
||||
pub retry: Option<Count>,
|
||||
pub retry_interval: Duration,
|
||||
pub ssl_no_revoke: bool,
|
||||
pub tap_file: Option<PathBuf>,
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use hurl_core::typing::Repeat;
|
||||
use hurl_core::typing::Count;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::runner::{HurlResult, Input, RunnerOptions, Value};
|
||||
@ -87,14 +87,14 @@ pub struct JobQueue<'job> {
|
||||
/// Current index of the job, referencing the input job list.
|
||||
index: usize,
|
||||
/// Repeat mode of this queue (finite or infinite).
|
||||
repeat: Repeat,
|
||||
repeat: Count,
|
||||
/// Current index of the repeat.
|
||||
repeat_index: usize,
|
||||
}
|
||||
|
||||
impl<'job> JobQueue<'job> {
|
||||
/// Create a new queue, with a list of `jobs` and a `repeat` mode.
|
||||
pub fn new(jobs: &'job [Job], repeat: Repeat) -> Self {
|
||||
pub fn new(jobs: &'job [Job], repeat: Count) -> Self {
|
||||
JobQueue {
|
||||
jobs,
|
||||
index: 0,
|
||||
@ -108,8 +108,8 @@ impl<'job> JobQueue<'job> {
|
||||
/// If queue is created in loop forever mode ([`Repeat::Forever`]), returns `None`.
|
||||
pub fn jobs_count(&self) -> Option<usize> {
|
||||
match self.repeat {
|
||||
Repeat::Count(n) => Some(self.jobs.len() * n),
|
||||
Repeat::Forever => None,
|
||||
Count::Finite(n) => Some(self.jobs.len() * n),
|
||||
Count::Infinite => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ impl Iterator for JobQueue<'_> {
|
||||
if self.index >= self.jobs.len() {
|
||||
self.repeat_index = self.repeat_index.checked_add(1).unwrap_or(0);
|
||||
match self.repeat {
|
||||
Repeat::Count(n) => {
|
||||
Count::Finite(n) => {
|
||||
if self.repeat_index >= n {
|
||||
None
|
||||
} else {
|
||||
@ -138,7 +138,7 @@ impl Iterator for JobQueue<'_> {
|
||||
Some(self.job_at(0))
|
||||
}
|
||||
}
|
||||
Repeat::Forever => {
|
||||
Count::Infinite => {
|
||||
self.index = 1;
|
||||
Some(self.job_at(0))
|
||||
}
|
||||
@ -155,7 +155,7 @@ mod tests {
|
||||
use crate::parallel::job::{Job, JobQueue};
|
||||
use crate::runner::{Input, RunnerOptionsBuilder};
|
||||
use crate::util::logger::LoggerOptionsBuilder;
|
||||
use hurl_core::typing::Repeat;
|
||||
use hurl_core::typing::Count;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn new_job(file: &str, index: usize) -> Job {
|
||||
@ -179,7 +179,7 @@ mod tests {
|
||||
new_job("c.hurl", 2),
|
||||
];
|
||||
|
||||
let mut queue = JobQueue::new(&jobs, Repeat::Count(2));
|
||||
let mut queue = JobQueue::new(&jobs, Count::Finite(2));
|
||||
|
||||
assert_eq!(queue.next(), Some(new_job("a.hurl", 0)));
|
||||
assert_eq!(queue.next(), Some(new_job("b.hurl", 1)));
|
||||
@ -196,7 +196,7 @@ mod tests {
|
||||
fn input_queue_is_infinite() {
|
||||
let jobs = [new_job("foo.hurl", 0)];
|
||||
|
||||
let mut queue = JobQueue::new(&jobs, Repeat::Forever);
|
||||
let mut queue = JobQueue::new(&jobs, Count::Infinite);
|
||||
assert_eq!(queue.next(), Some(new_job("foo.hurl", 0)));
|
||||
assert_eq!(queue.next(), Some(new_job("foo.hurl", 1)));
|
||||
assert_eq!(queue.next(), Some(new_job("foo.hurl", 2)));
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
use hurl_core::error::{DisplaySourceError, OutputFormat};
|
||||
use hurl_core::typing::Repeat;
|
||||
use hurl_core::typing::Count;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
|
||||
@ -53,7 +53,7 @@ pub struct ParallelRunner {
|
||||
/// Output type for each completed job on standard output.
|
||||
output_type: OutputType,
|
||||
/// Repeat mode for the runner: infinite or finite.
|
||||
repeat: Repeat,
|
||||
repeat: Count,
|
||||
}
|
||||
|
||||
/// Represents a worker's state.
|
||||
@ -106,7 +106,7 @@ impl ParallelRunner {
|
||||
pub fn new(
|
||||
workers_count: usize,
|
||||
output_type: OutputType,
|
||||
repeat: Repeat,
|
||||
repeat: Count,
|
||||
test: bool,
|
||||
progress_bar: bool,
|
||||
color: bool,
|
||||
|
@ -28,7 +28,7 @@ use hurl::runner::{HurlResult, Input, Output};
|
||||
use hurl::util::term::{Stdout, WriteMode};
|
||||
use hurl::{output, parallel, runner};
|
||||
use hurl_core::error::{DisplaySourceError, OutputFormat};
|
||||
use hurl_core::typing::Repeat;
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
/// Runs Hurl `files` sequentially, given a current directory and command-line options (see
|
||||
/// [`crate::cli::options::CliOptions`]). This function returns a list of [`HurlRun`] results or
|
||||
@ -40,7 +40,7 @@ pub fn run_seq(
|
||||
) -> Result<Vec<HurlRun>, CliError> {
|
||||
let mut runs = vec![];
|
||||
|
||||
let repeat = options.repeat.unwrap_or_default();
|
||||
let repeat = options.repeat.unwrap_or(Count::Finite(1));
|
||||
let queue = InputQueue::new(files, repeat);
|
||||
|
||||
// When dumped HTTP responses, we truncate existing output file on first save, then append
|
||||
@ -165,8 +165,8 @@ pub fn run_par(
|
||||
// We're going to use the right numbers of workers. We don't need to use more workers than there
|
||||
// are input files (repeat option act as if we're dealing with a multiplied number of files)
|
||||
let workers_count = match options.repeat {
|
||||
Some(Repeat::Count(n)) => min(files.len() * n, workers_count),
|
||||
Some(Repeat::Forever) => workers_count,
|
||||
Some(Count::Finite(n)) => min(files.len() * n, workers_count),
|
||||
Some(Count::Infinite) => workers_count,
|
||||
None => min(files.len(), workers_count),
|
||||
};
|
||||
let variables = &options.variables;
|
||||
@ -188,7 +188,7 @@ pub fn run_par(
|
||||
let mut runner = ParallelRunner::new(
|
||||
workers_count,
|
||||
output_type,
|
||||
options.repeat.unwrap_or_default(),
|
||||
options.repeat.unwrap_or(Count::Finite(1)),
|
||||
options.test,
|
||||
options.progress_bar,
|
||||
options.color,
|
||||
@ -233,14 +233,14 @@ pub struct InputQueue<'input> {
|
||||
/// Current index of the input, referencing the input list.
|
||||
index: usize,
|
||||
/// Repeat mode of this queue (finite or infinite).
|
||||
repeat: Repeat,
|
||||
repeat: Count,
|
||||
/// Current index of the repeat.
|
||||
repeat_index: usize,
|
||||
}
|
||||
|
||||
impl<'input> InputQueue<'input> {
|
||||
/// Create a new queue, with a list of `inputs` and a `repeat` mode.
|
||||
pub fn new(inputs: &'input [Input], repeat: Repeat) -> Self {
|
||||
pub fn new(inputs: &'input [Input], repeat: Count) -> Self {
|
||||
InputQueue {
|
||||
inputs,
|
||||
index: 0,
|
||||
@ -262,7 +262,7 @@ impl Iterator for InputQueue<'_> {
|
||||
if self.index >= self.inputs.len() {
|
||||
self.repeat_index = self.repeat_index.checked_add(1).unwrap_or(0);
|
||||
match self.repeat {
|
||||
Repeat::Count(n) => {
|
||||
Count::Finite(n) => {
|
||||
if self.repeat_index >= n {
|
||||
None
|
||||
} else {
|
||||
@ -270,7 +270,7 @@ impl Iterator for InputQueue<'_> {
|
||||
Some(self.input_at(0))
|
||||
}
|
||||
}
|
||||
Repeat::Forever => {
|
||||
Count::Infinite => {
|
||||
self.index = 1;
|
||||
Some(self.input_at(0))
|
||||
}
|
||||
@ -286,13 +286,13 @@ impl Iterator for InputQueue<'_> {
|
||||
mod tests {
|
||||
use crate::run::InputQueue;
|
||||
use hurl::runner::Input;
|
||||
use hurl_core::typing::Repeat;
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
#[test]
|
||||
fn input_queue_is_finite() {
|
||||
let files = [Input::new("a"), Input::new("b"), Input::new("c")];
|
||||
|
||||
let mut queue = InputQueue::new(&files, Repeat::Count(4));
|
||||
let mut queue = InputQueue::new(&files, Count::Finite(4));
|
||||
assert_eq!(queue.next(), Some(Input::new("a")));
|
||||
assert_eq!(queue.next(), Some(Input::new("b")));
|
||||
assert_eq!(queue.next(), Some(Input::new("c")));
|
||||
@ -312,7 +312,7 @@ mod tests {
|
||||
fn input_queue_is_infinite() {
|
||||
let files = [Input::new("a")];
|
||||
|
||||
let mut queue = InputQueue::new(&files, Repeat::Forever);
|
||||
let mut queue = InputQueue::new(&files, Count::Infinite);
|
||||
assert_eq!(queue.next(), Some(Input::new("a")));
|
||||
assert_eq!(queue.next(), Some(Input::new("a")));
|
||||
assert_eq!(queue.next(), Some(Input::new("a")));
|
||||
|
@ -26,7 +26,7 @@ use hurl_core::ast::{
|
||||
};
|
||||
use hurl_core::error::DisplaySourceError;
|
||||
use hurl_core::parser;
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
use crate::http::{Call, Client};
|
||||
use crate::runner::event::EventListener;
|
||||
@ -217,7 +217,7 @@ pub fn run_entries(
|
||||
}
|
||||
|
||||
// Repeat 0 is equivalent to skip.
|
||||
if options.repeat == Some(Repeat::Count(0)) {
|
||||
if options.repeat == Some(Count::Finite(0)) {
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!("Entry {entry_index} is skipped (repeat 0 times)"));
|
||||
entry_index += 1;
|
||||
@ -268,7 +268,7 @@ pub fn run_entries(
|
||||
repeat_count = 0;
|
||||
entry_index += 1;
|
||||
}
|
||||
Some(Repeat::Count(n)) => {
|
||||
Some(Count::Finite(n)) => {
|
||||
if repeat_count >= n {
|
||||
repeat_count = 0;
|
||||
entry_index += 1;
|
||||
@ -278,7 +278,7 @@ pub fn run_entries(
|
||||
));
|
||||
}
|
||||
}
|
||||
Some(Repeat::Forever) => {
|
||||
Some(Count::Infinite) => {
|
||||
logger.debug_important(&format!("Repeat entry {entry_index} (x{repeat_count})"));
|
||||
}
|
||||
}
|
||||
@ -319,7 +319,7 @@ fn run_request(
|
||||
let mut has_error = !result.errors.is_empty();
|
||||
|
||||
// The retry threshold can only be reached with a finite positive number of retries
|
||||
let retry_max_reached = if let Some(Retry::Finite(r)) = options.retry {
|
||||
let retry_max_reached = if let Some(Count::Finite(r)) = options.retry {
|
||||
retry_count > r
|
||||
} else {
|
||||
false
|
||||
|
@ -19,10 +19,10 @@ use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use hurl_core::ast::{
|
||||
BooleanOption, Entry, EntryOption, Float, NaturalOption, Number as AstNumber, OptionKind,
|
||||
RepeatOption, RetryOption, SectionValue, VariableDefinition, VariableValue,
|
||||
BooleanOption, CountOption, Entry, EntryOption, Float, NaturalOption, Number as AstNumber,
|
||||
OptionKind, SectionValue, VariableDefinition, VariableValue,
|
||||
};
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
use crate::http::{IpResolve, RequestedHttpVersion};
|
||||
use crate::runner::template::{eval_expression, eval_template};
|
||||
@ -200,7 +200,7 @@ pub fn get_entry_options(
|
||||
entry_options.proxy = Some(value);
|
||||
}
|
||||
OptionKind::Repeat(value) => {
|
||||
let value = eval_repeat_option(value, variables)?;
|
||||
let value = eval_count_option(value, variables)?;
|
||||
entry_options.repeat = Some(value);
|
||||
}
|
||||
OptionKind::Resolve(value) => {
|
||||
@ -208,7 +208,7 @@ pub fn get_entry_options(
|
||||
entry_options.resolves.push(value);
|
||||
}
|
||||
OptionKind::Retry(value) => {
|
||||
let value = eval_retry_option(value, variables)?;
|
||||
let value = eval_count_option(value, variables)?;
|
||||
entry_options.retry = Some(value);
|
||||
}
|
||||
OptionKind::RetryInterval(value) => {
|
||||
@ -320,7 +320,6 @@ fn eval_boolean_option(
|
||||
}
|
||||
}
|
||||
|
||||
/// Evals a natural option value (>=0), given a set of `variables`.
|
||||
fn eval_natural_option(
|
||||
natural_value: &NaturalOption,
|
||||
variables: &HashMap<String, Value>,
|
||||
@ -352,53 +351,18 @@ fn eval_natural_option(
|
||||
}
|
||||
}
|
||||
|
||||
/// Render an AST repeat option with a `variables` set.
|
||||
fn eval_repeat_option(
|
||||
repeat_option_value: &RepeatOption,
|
||||
fn eval_count_option(
|
||||
count_value: &CountOption,
|
||||
variables: &HashMap<String, Value>,
|
||||
) -> Result<Repeat, RunnerError> {
|
||||
match repeat_option_value {
|
||||
RepeatOption::Literal(repeat) => Ok(*repeat),
|
||||
RepeatOption::Expression(expr) => match eval_expression(expr, variables)? {
|
||||
) -> Result<Count, RunnerError> {
|
||||
match count_value {
|
||||
CountOption::Literal(repeat) => Ok(*repeat),
|
||||
CountOption::Expression(expr) => match eval_expression(expr, variables)? {
|
||||
Value::Number(Number::Integer(value)) => {
|
||||
if value == -1 {
|
||||
Ok(Repeat::Forever)
|
||||
Ok(Count::Infinite)
|
||||
} else if value >= 0 {
|
||||
Ok(Repeat::Count(value as usize))
|
||||
} else {
|
||||
let kind = RunnerErrorKind::TemplateVariableInvalidType {
|
||||
name: expr.variable.name.clone(),
|
||||
value: format!("integer <{value}>"),
|
||||
expecting: "integer".to_string(),
|
||||
};
|
||||
Err(RunnerError::new(expr.variable.source_info, kind, false))
|
||||
}
|
||||
}
|
||||
v => {
|
||||
let kind = RunnerErrorKind::TemplateVariableInvalidType {
|
||||
name: expr.variable.name.clone(),
|
||||
value: v.format(),
|
||||
expecting: "integer".to_string(),
|
||||
};
|
||||
Err(RunnerError::new(expr.variable.source_info, kind, false))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Render an AST retry option with a `variables` set.
|
||||
fn eval_retry_option(
|
||||
retry_option_value: &RetryOption,
|
||||
variables: &HashMap<String, Value>,
|
||||
) -> Result<Retry, RunnerError> {
|
||||
match retry_option_value {
|
||||
RetryOption::Literal(retry) => Ok(*retry),
|
||||
RetryOption::Expression(expr) => match eval_expression(expr, variables)? {
|
||||
Value::Number(Number::Integer(value)) => {
|
||||
if value == -1 {
|
||||
Ok(Retry::Infinite)
|
||||
} else if value >= 0 {
|
||||
Ok(Retry::Finite(value as usize))
|
||||
Ok(Count::Finite(value as usize))
|
||||
} else {
|
||||
let kind = RunnerErrorKind::TemplateVariableInvalidType {
|
||||
name: expr.variable.name.clone(),
|
||||
@ -411,7 +375,7 @@ fn eval_retry_option(
|
||||
v => {
|
||||
let kind = RunnerErrorKind::TemplateVariableInvalidType {
|
||||
name: expr.variable.name.clone(),
|
||||
value: v.to_string(),
|
||||
value: v.format(),
|
||||
expecting: "integer".to_string(),
|
||||
};
|
||||
Err(RunnerError::new(expr.variable.source_info, kind, false))
|
||||
|
@ -18,7 +18,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use hurl_core::ast::Entry;
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
use crate::http::{IpResolve, RequestedHttpVersion};
|
||||
use crate::runner::Output;
|
||||
@ -54,9 +54,9 @@ pub struct RunnerOptionsBuilder {
|
||||
post_entry: Option<fn() -> bool>,
|
||||
pre_entry: Option<fn(Entry) -> bool>,
|
||||
proxy: Option<String>,
|
||||
repeat: Option<Repeat>,
|
||||
repeat: Option<Count>,
|
||||
resolves: Vec<String>,
|
||||
retry: Option<Retry>,
|
||||
retry: Option<Count>,
|
||||
retry_interval: Duration,
|
||||
skip: bool,
|
||||
ssl_no_revoke: bool,
|
||||
@ -322,7 +322,7 @@ impl RunnerOptionsBuilder {
|
||||
}
|
||||
|
||||
/// Set the number of repetition for a given entry.
|
||||
pub fn repeat(&mut self, repeat: Option<Repeat>) -> &mut Self {
|
||||
pub fn repeat(&mut self, repeat: Option<Count>) -> &mut Self {
|
||||
self.repeat = repeat;
|
||||
self
|
||||
}
|
||||
@ -336,7 +336,7 @@ impl RunnerOptionsBuilder {
|
||||
/// Sets maximum number of retries.
|
||||
///
|
||||
/// Default is 0.
|
||||
pub fn retry(&mut self, retry: Option<Retry>) -> &mut Self {
|
||||
pub fn retry(&mut self, retry: Option<Count>) -> &mut Self {
|
||||
self.retry = retry;
|
||||
self
|
||||
}
|
||||
@ -470,9 +470,9 @@ pub struct RunnerOptions {
|
||||
pub(crate) post_entry: Option<fn() -> bool>,
|
||||
pub(crate) pre_entry: Option<fn(Entry) -> bool>,
|
||||
pub(crate) proxy: Option<String>,
|
||||
pub(crate) repeat: Option<Repeat>,
|
||||
pub(crate) repeat: Option<Count>,
|
||||
pub(crate) resolves: Vec<String>,
|
||||
pub(crate) retry: Option<Retry>,
|
||||
pub(crate) retry: Option<Count>,
|
||||
pub(crate) retry_interval: Duration,
|
||||
pub(crate) skip: bool,
|
||||
pub(crate) ssl_no_revoke: bool,
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
use crate::ast::json;
|
||||
use crate::reader::Pos;
|
||||
use crate::typing::{Repeat, Retry};
|
||||
use crate::typing::Count;
|
||||
|
||||
///
|
||||
/// Hurl AST
|
||||
@ -726,9 +726,9 @@ pub enum OptionKind {
|
||||
Output(Template),
|
||||
PathAsIs(BooleanOption),
|
||||
Proxy(Template),
|
||||
Repeat(RepeatOption),
|
||||
Repeat(CountOption),
|
||||
Resolve(Template),
|
||||
Retry(RetryOption),
|
||||
Retry(CountOption),
|
||||
RetryInterval(NaturalOption),
|
||||
Skip(BooleanOption),
|
||||
UnixSocket(Template),
|
||||
@ -831,14 +831,8 @@ pub enum NaturalOption {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum RepeatOption {
|
||||
Literal(Repeat),
|
||||
Expression(Expr),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum RetryOption {
|
||||
Literal(Retry),
|
||||
pub enum CountOption {
|
||||
Literal(Count),
|
||||
Expression(Expr),
|
||||
}
|
||||
|
||||
|
@ -187,20 +187,11 @@ impl fmt::Display for NaturalOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RepeatOption {
|
||||
impl fmt::Display for CountOption {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
RepeatOption::Literal(v) => write!(f, "{}", v),
|
||||
RepeatOption::Expression(v) => write!(f, "{}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RetryOption {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
RetryOption::Literal(v) => write!(f, "{}", v),
|
||||
RetryOption::Expression(v) => write!(f, "{}", v),
|
||||
CountOption::Literal(v) => write!(f, "{}", v),
|
||||
CountOption::Expression(v) => write!(f, "{}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::typing::{Repeat, Retry};
|
||||
use crate::typing::Count;
|
||||
|
||||
/// Returns an HTML string of the Hurl file `hurl_file`.
|
||||
///
|
||||
@ -238,9 +238,9 @@ impl HtmlFormatter {
|
||||
OptionKind::Output(filename) => self.fmt_filename(filename),
|
||||
OptionKind::PathAsIs(value) => self.fmt_bool_option(value),
|
||||
OptionKind::Proxy(value) => self.fmt_template(value),
|
||||
OptionKind::Repeat(value) => self.fmt_repeat_option(value),
|
||||
OptionKind::Repeat(value) => self.fmt_count_option(value),
|
||||
OptionKind::Resolve(value) => self.fmt_template(value),
|
||||
OptionKind::Retry(value) => self.fmt_retry_option(value),
|
||||
OptionKind::Retry(value) => self.fmt_count_option(value),
|
||||
OptionKind::RetryInterval(value) => self.fmt_natural_option(value),
|
||||
OptionKind::Skip(value) => self.fmt_bool_option(value),
|
||||
OptionKind::UnixSocket(value) => self.fmt_template(value),
|
||||
@ -253,31 +253,17 @@ impl HtmlFormatter {
|
||||
self.fmt_lt(&option.line_terminator0);
|
||||
}
|
||||
|
||||
fn fmt_repeat_option(&mut self, repeat_option: &RepeatOption) {
|
||||
match repeat_option {
|
||||
RepeatOption::Literal(repeat) => self.fmt_repeat(repeat),
|
||||
RepeatOption::Expression(expr) => self.fmt_expr(expr),
|
||||
fn fmt_count_option(&mut self, count_option: &CountOption) {
|
||||
match count_option {
|
||||
CountOption::Literal(repeat) => self.fmt_count(*repeat),
|
||||
CountOption::Expression(expr) => self.fmt_expr(expr),
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_repeat(&mut self, repeat: &Repeat) {
|
||||
match repeat {
|
||||
Repeat::Count(n) => self.fmt_number(n),
|
||||
Repeat::Forever => self.fmt_number(-1),
|
||||
};
|
||||
}
|
||||
|
||||
fn fmt_retry_option(&mut self, retry_option: &RetryOption) {
|
||||
match retry_option {
|
||||
RetryOption::Literal(retry) => self.fmt_retry(retry),
|
||||
RetryOption::Expression(expr) => self.fmt_expr(expr),
|
||||
};
|
||||
}
|
||||
|
||||
fn fmt_retry(&mut self, retry: &Retry) {
|
||||
match retry {
|
||||
Retry::Finite(n) => self.fmt_number(n),
|
||||
Retry::Infinite => self.fmt_number(-1),
|
||||
fn fmt_count(&mut self, count: Count) {
|
||||
match count {
|
||||
Count::Finite(n) => self.fmt_number(n),
|
||||
Count::Infinite => self.fmt_number(-1),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ use crate::parser::primitives::*;
|
||||
use crate::parser::string::*;
|
||||
use crate::parser::{expr, filename, filename_password, ParseResult};
|
||||
use crate::reader::Reader;
|
||||
use crate::typing::{Repeat, Retry};
|
||||
use crate::typing::Count;
|
||||
|
||||
/// Parse an option in an `[Options]` section.
|
||||
pub fn parse(reader: &mut Reader) -> ParseResult<EntryOption> {
|
||||
@ -208,7 +208,7 @@ fn option_proxy(reader: &mut Reader) -> ParseResult<OptionKind> {
|
||||
}
|
||||
|
||||
fn option_repeat(reader: &mut Reader) -> ParseResult<OptionKind> {
|
||||
let value = repeat_option(reader)?;
|
||||
let value = non_recover(count_option, reader)?;
|
||||
Ok(OptionKind::Repeat(value))
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ fn option_resolve(reader: &mut Reader) -> ParseResult<OptionKind> {
|
||||
}
|
||||
|
||||
fn option_retry(reader: &mut Reader) -> ParseResult<OptionKind> {
|
||||
let value = retry_option(reader)?;
|
||||
let value = non_recover(count_option, reader)?;
|
||||
Ok(OptionKind::Retry(value))
|
||||
}
|
||||
|
||||
@ -257,31 +257,16 @@ fn option_very_verbose(reader: &mut Reader) -> ParseResult<OptionKind> {
|
||||
Ok(OptionKind::VeryVerbose(value))
|
||||
}
|
||||
|
||||
fn repeat(reader: &mut Reader) -> ParseResult<Repeat> {
|
||||
fn count(reader: &mut Reader) -> ParseResult<Count> {
|
||||
let start = reader.cursor();
|
||||
let value = non_recover(integer, reader)?;
|
||||
if value == -1 {
|
||||
Ok(Repeat::Forever)
|
||||
Ok(Count::Infinite)
|
||||
} else if value >= 0 {
|
||||
Ok(Repeat::Count(value as usize))
|
||||
Ok(Count::Finite(value as usize))
|
||||
} else {
|
||||
let kind = ParseErrorKind::Expecting {
|
||||
value: "Expecting a repeat value".to_string(),
|
||||
};
|
||||
Err(ParseError::new(start.pos, false, kind))
|
||||
}
|
||||
}
|
||||
|
||||
fn retry(reader: &mut Reader) -> ParseResult<Retry> {
|
||||
let start = reader.cursor();
|
||||
let value = non_recover(integer, reader)?;
|
||||
if value == -1 {
|
||||
Ok(Retry::Infinite)
|
||||
} else if value >= 0 {
|
||||
Ok(Retry::Finite(value as usize))
|
||||
} else {
|
||||
let kind = ParseErrorKind::Expecting {
|
||||
value: "Expecting a retry value".to_string(),
|
||||
value: "Expecting a count value".to_string(),
|
||||
};
|
||||
Err(ParseError::new(start.pos, false, kind))
|
||||
}
|
||||
@ -321,27 +306,10 @@ fn natural_option(reader: &mut Reader) -> ParseResult<NaturalOption> {
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat_option(reader: &mut Reader) -> ParseResult<RepeatOption> {
|
||||
fn count_option(reader: &mut Reader) -> ParseResult<CountOption> {
|
||||
let start = reader.cursor();
|
||||
match repeat(reader) {
|
||||
Ok(v) => Ok(RepeatOption::Literal(v)),
|
||||
Err(_) => {
|
||||
reader.seek(start);
|
||||
let exp = expr::parse(reader).map_err(|e| {
|
||||
let kind = ParseErrorKind::Expecting {
|
||||
value: "integer".to_string(),
|
||||
};
|
||||
ParseError::new(e.pos, false, kind)
|
||||
})?;
|
||||
Ok(RepeatOption::Expression(exp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn retry_option(reader: &mut Reader) -> ParseResult<RetryOption> {
|
||||
let start = reader.cursor();
|
||||
match retry(reader) {
|
||||
Ok(v) => Ok(RetryOption::Literal(v)),
|
||||
match count(reader) {
|
||||
Ok(v) => Ok(CountOption::Literal(v)),
|
||||
Err(_) => {
|
||||
reader.seek(start);
|
||||
let exp = expr::parse(reader).map_err(|e| {
|
||||
@ -350,7 +318,7 @@ fn retry_option(reader: &mut Reader) -> ParseResult<RetryOption> {
|
||||
};
|
||||
ParseError::new(e.pos, false, kind)
|
||||
})?;
|
||||
Ok(RetryOption::Expression(exp))
|
||||
Ok(CountOption::Expression(exp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,43 +18,22 @@
|
||||
//! Hurl common types.
|
||||
use core::fmt;
|
||||
|
||||
/// Represents a repeat operation, either finite or infinite.
|
||||
/// Represents a count operation, either finite or infinite.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Repeat {
|
||||
Count(usize),
|
||||
Forever,
|
||||
}
|
||||
|
||||
impl Default for Repeat {
|
||||
fn default() -> Self {
|
||||
Repeat::Count(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Repeat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let value = match self {
|
||||
Repeat::Count(n) => *n as i64,
|
||||
Repeat::Forever => -1,
|
||||
};
|
||||
write!(f, "{}", value)
|
||||
}
|
||||
}
|
||||
/// Represents a retry operation (when an operation has failed), either finite or infinite.
|
||||
/// Contrary to [`Repeat`], [`Retry`] has a notion of retry only on operation failure, while
|
||||
/// [`Repeat`] is unconditional.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
|
||||
pub enum Retry {
|
||||
pub enum Count {
|
||||
Finite(usize),
|
||||
Infinite,
|
||||
}
|
||||
|
||||
impl fmt::Display for Retry {
|
||||
impl fmt::Display for Count {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let value = match self {
|
||||
Retry::Finite(n) => *n as i64,
|
||||
Retry::Infinite => -1,
|
||||
};
|
||||
write!(f, "{}", value)
|
||||
match self {
|
||||
Count::Finite(n) => {
|
||||
write!(f, "{n}")
|
||||
}
|
||||
Count::Infinite => {
|
||||
write!(f, "-1")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
use base64::engine::general_purpose;
|
||||
use base64::Engine;
|
||||
use hurl_core::ast::*;
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
use super::serialize_json::*;
|
||||
|
||||
@ -353,38 +353,20 @@ impl ToJson for NaturalOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for RepeatOption {
|
||||
impl ToJson for CountOption {
|
||||
fn to_json(&self) -> JValue {
|
||||
match self {
|
||||
RepeatOption::Literal(value) => value.to_json(),
|
||||
RepeatOption::Expression(expr) => expr.to_json(),
|
||||
CountOption::Literal(value) => value.to_json(),
|
||||
CountOption::Expression(expr) => expr.to_json(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for Repeat {
|
||||
impl ToJson for Count {
|
||||
fn to_json(&self) -> JValue {
|
||||
match self {
|
||||
Repeat::Count(n) => JValue::Number(n.to_string()),
|
||||
Repeat::Forever => JValue::Number("-1".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for RetryOption {
|
||||
fn to_json(&self) -> JValue {
|
||||
match self {
|
||||
RetryOption::Literal(value) => value.to_json(),
|
||||
RetryOption::Expression(expr) => expr.to_json(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for Retry {
|
||||
fn to_json(&self) -> JValue {
|
||||
match self {
|
||||
Retry::Finite(n) => JValue::Number(n.to_string()),
|
||||
Retry::Infinite => JValue::Number("-1".to_string()),
|
||||
Count::Finite(n) => JValue::Number(n.to_string()),
|
||||
Count::Infinite => JValue::Number("-1".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
use hurl_core::ast::*;
|
||||
use hurl_core::typing::{Repeat, Retry};
|
||||
use hurl_core::typing::Count;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Token {
|
||||
@ -935,38 +935,20 @@ impl Tokenizable for NaturalOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for RepeatOption {
|
||||
impl Tokenizable for CountOption {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
match self {
|
||||
RepeatOption::Literal(retry) => retry.tokenize(),
|
||||
RepeatOption::Expression(expr) => expr.tokenize(),
|
||||
CountOption::Literal(retry) => retry.tokenize(),
|
||||
CountOption::Expression(expr) => expr.tokenize(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for Repeat {
|
||||
impl Tokenizable for Count {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
match self {
|
||||
Repeat::Count(n) => vec![Token::Number(n.to_string())],
|
||||
Repeat::Forever => vec![Token::Number("-1".to_string())],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for RetryOption {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
match self {
|
||||
RetryOption::Literal(retry) => retry.tokenize(),
|
||||
RetryOption::Expression(expr) => expr.tokenize(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for Retry {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
match self {
|
||||
Retry::Finite(n) => vec![Token::Number(n.to_string())],
|
||||
Retry::Infinite => vec![Token::Number("-1".to_string())],
|
||||
Count::Finite(n) => vec![Token::Number(n.to_string())],
|
||||
Count::Infinite => vec![Token::Number("-1".to_string())],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user