use std::fmt;
use crate::types::{SourceString, ToSource};
use super::option::EntryOption;
use super::primitive::{
Bytes, I64, KeyValue, LineTerminator, Placeholder, SourceInfo, Template, Whitespace,
};
use super::section::{Assert, Capture, Cookie, MultipartParam, RegexValue, Section, SectionValue};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HurlFile {
pub entries: Vec<Entry>,
pub line_terminators: Vec<LineTerminator>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Entry {
pub request: Request,
pub response: Option<Response>,
}
impl Entry {
pub fn source_info(&self) -> SourceInfo {
self.request.space0.source_info
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Request {
pub line_terminators: Vec<LineTerminator>,
pub space0: Whitespace,
pub method: Method,
pub space1: Whitespace,
pub url: Template,
pub line_terminator0: LineTerminator,
pub headers: Vec<KeyValue>,
pub sections: Vec<Section>,
pub body: Option<Body>,
pub source_info: SourceInfo,
}
impl Request {
pub fn querystring_params(&self) -> &[KeyValue] {
for section in &self.sections {
if let SectionValue::QueryParams(params, _) = §ion.value {
return params;
}
}
&[]
}
pub fn form_params(&self) -> &[KeyValue] {
for section in &self.sections {
if let SectionValue::FormParams(params, _) = §ion.value {
return params;
}
}
&[]
}
pub fn multipart_form_data(&self) -> &[MultipartParam] {
for section in &self.sections {
if let SectionValue::MultipartFormData(params, _) = §ion.value {
return params;
}
}
&[]
}
pub fn cookies(&self) -> &[Cookie] {
for section in &self.sections {
if let SectionValue::Cookies(cookies) = §ion.value {
return cookies;
}
}
&[]
}
pub fn basic_auth(&self) -> Option<&KeyValue> {
for section in &self.sections {
if let SectionValue::BasicAuth(kv) = §ion.value {
return kv.as_ref();
}
}
None
}
pub fn options(&self) -> &[EntryOption] {
for section in &self.sections {
if let SectionValue::Options(options) = §ion.value {
return options;
}
}
&[]
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Response {
pub line_terminators: Vec<LineTerminator>,
pub version: Version,
pub space0: Whitespace,
pub status: Status,
pub space1: Whitespace,
pub line_terminator0: LineTerminator,
pub headers: Vec<KeyValue>,
pub sections: Vec<Section>,
pub body: Option<Body>,
pub source_info: SourceInfo,
}
impl Response {
pub fn captures(&self) -> &[Capture] {
for section in self.sections.iter() {
if let SectionValue::Captures(captures) = §ion.value {
return captures;
}
}
&[]
}
pub fn asserts(&self) -> &[Assert] {
for section in self.sections.iter() {
if let SectionValue::Asserts(asserts) = §ion.value {
return asserts;
}
}
&[]
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Method(String);
impl Method {
pub fn new(method: &str) -> Method {
Method(method.to_string())
}
}
impl fmt::Display for Method {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl ToSource for Method {
fn to_source(&self) -> SourceString {
self.0.to_source()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Version {
pub value: VersionValue,
pub source_info: SourceInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum VersionValue {
Version1,
Version11,
Version2,
Version3,
VersionAny,
}
impl fmt::Display for VersionValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
VersionValue::Version1 => "HTTP/1.0",
VersionValue::Version11 => "HTTP/1.1",
VersionValue::Version2 => "HTTP/2",
VersionValue::Version3 => "HTTP/3",
VersionValue::VersionAny => "HTTP",
};
write!(f, "{s}")
}
}
impl ToSource for VersionValue {
fn to_source(&self) -> SourceString {
self.to_string().to_source()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Status {
pub value: StatusValue,
pub source_info: SourceInfo,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StatusValue {
Any,
Specific(u64),
}
impl fmt::Display for StatusValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
StatusValue::Any => write!(f, "*"),
StatusValue::Specific(v) => write!(f, "{v}"),
}
}
}
impl ToSource for StatusValue {
fn to_source(&self) -> SourceString {
self.to_string().to_source()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Body {
pub line_terminators: Vec<LineTerminator>,
pub space0: Whitespace,
pub value: Bytes,
pub line_terminator0: LineTerminator,
}
pub fn is_variable_reserved(name: &str) -> bool {
["getEnv", "newDate", "newUuid"].contains(&name)
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Filter {
pub source_info: SourceInfo,
pub value: FilterValue,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FilterValue {
Base64Decode,
Base64Encode,
Base64UrlSafeDecode,
Base64UrlSafeEncode,
CharsetDecode {
space0: Whitespace,
encoding: Template,
},
Count,
DaysAfterNow,
DaysBeforeNow,
Decode {
space0: Whitespace,
encoding: Template,
},
First,
Format {
space0: Whitespace,
fmt: Template,
},
DateFormat {
space0: Whitespace,
fmt: Template,
},
HtmlEscape,
HtmlUnescape,
JsonPath {
space0: Whitespace,
expr: Template,
},
Last,
Location,
Nth {
space0: Whitespace,
n: IntegerValue,
},
Regex {
space0: Whitespace,
value: RegexValue,
},
Replace {
space0: Whitespace,
old_value: Template,
space1: Whitespace,
new_value: Template,
},
ReplaceRegex {
space0: Whitespace,
pattern: RegexValue,
space1: Whitespace,
new_value: Template,
},
Split {
space0: Whitespace,
sep: Template,
},
ToDate {
space0: Whitespace,
fmt: Template,
},
ToFloat,
ToHex,
ToInt,
ToString,
UrlDecode,
UrlEncode,
UrlQueryParam {
space0: Whitespace,
param: Template,
},
Utf8Decode,
Utf8Encode,
XPath {
space0: Whitespace,
expr: Template,
},
}
impl FilterValue {
pub fn identifier(&self) -> &'static str {
match self {
FilterValue::Base64Decode => "base64Decode",
FilterValue::Base64Encode => "base64Encode",
FilterValue::Base64UrlSafeDecode => "base64UrlSafeDecode",
FilterValue::Base64UrlSafeEncode => "base64UrlSafeEncode",
FilterValue::CharsetDecode { .. } => "charsetDecode",
FilterValue::Count => "count",
FilterValue::DaysAfterNow => "daysAfterNow",
FilterValue::DaysBeforeNow => "daysBeforeNow",
FilterValue::Decode { .. } => "decode",
FilterValue::First => "first",
FilterValue::Format { .. } => "format",
FilterValue::DateFormat { .. } => "dateFormat",
FilterValue::HtmlEscape => "htmlEscape",
FilterValue::HtmlUnescape => "htmlUnescape",
FilterValue::JsonPath { .. } => "jsonpath",
FilterValue::Last => "last",
FilterValue::Location => "location",
FilterValue::Nth { .. } => "nth",
FilterValue::Regex { .. } => "regex",
FilterValue::Replace { .. } => "replace",
FilterValue::ReplaceRegex { .. } => "replaceRegex",
FilterValue::Split { .. } => "split",
FilterValue::ToDate { .. } => "toDate",
FilterValue::ToFloat => "toFloat",
FilterValue::ToHex => "toHex",
FilterValue::ToInt => "toInt",
FilterValue::ToString => "toString",
FilterValue::UrlDecode => "urlDecode",
FilterValue::UrlEncode => "urlEncode",
FilterValue::UrlQueryParam { .. } => "urlQueryParam",
FilterValue::Utf8Decode => "utf8Decode",
FilterValue::Utf8Encode => "utf8Encode",
FilterValue::XPath { .. } => "xpath",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum IntegerValue {
Literal(I64),
Placeholder(Placeholder),
}
impl fmt::Display for IntegerValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
IntegerValue::Literal(v) => write!(f, "{v}"),
IntegerValue::Placeholder(v) => write!(f, "{v}"),
}
}
}