Skip to main content

brooks_lib/dcdn/processors/
ps.rs

1// brooks, Copyright 2026, Will Hawkins
2//
3// This file is part of brooks.
4
5// This file is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18//! The Processing Stages Generic Metadata Processing Implementation
19
20use std::error;
21use std::fmt::{Debug, Display};
22use std::str::FromStr;
23
24use crate::cdni::gmd::spec::TypedGenericMetadata;
25use crate::cdni::ps::spec::{
26    TypedClientRequestStage, TypedClientResponseStage, TypedExpressionMatch, TypedHeader,
27    TypedHeaderTransform, TypedMatchGroup, TypedOriginRequestStage, TypedOriginResponseStage,
28    TypedProcessingStages, TypedRequestTransform, TypedResponseTransform, TypedStage,
29    TypedStageMetadata, TypedStageRules, TypedSyntheticResponse,
30};
31use crate::dcdn::imdi;
32use crate::dcdn::interpret::Stages::{
33    ClientRequest, ClientResponse, OriginRequest, OriginResponse,
34};
35use crate::dcdn::interpret::{
36    Error, MetadataInformationResultElement, MetadataInformationResultElements, Stages,
37};
38use crate::dcdn::processors::SimpleProcessorsInterpreterContext;
39use crate::environment::scope::Scopes;
40use crate::logging::LogMsgs;
41use crate::mel::analysis::Analyzed;
42use crate::mel::ast::Expr;
43use crate::mel::interpreter::error::{
44    InterpAssertion as MelInterpAssertion, InterpError as MelInterpError,
45    InterpLocatableError as MelInterpLocatableError,
46};
47use crate::mel::interpreter::interpret::MelInterpContext;
48use crate::mel::interpreter::values::{TypedValue, Value};
49use crate::mel::types::Type;
50use crate::processing::interpret::{self, Interpreter};
51use crate::verifying::ps::verify::PsVerificationKey;
52use crate::visitors::{PsVisitor, PsVisitorResult};
53use crate::{mel, prr};
54
55pub type PsInterpretResult =
56    Result<(PsInterpretValue, MetadataInformationResultElements), Box<PsInterpretError>>;
57
58#[derive(Debug, Clone)]
59pub enum PsInterpretAssertionFailures {
60    MissingAnalyzedExpression,
61    MissingInterpreterExpressionValue,
62    InvalidInterpreterMode,
63    MissingResult,
64}
65
66impl Display for PsInterpretAssertionFailures {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            PsInterpretAssertionFailures::MissingAnalyzedExpression => {
70                write!(f, "Missing information about an analyzed expression")
71            }
72            PsInterpretAssertionFailures::MissingInterpreterExpressionValue => {
73                write!(f, "Missing value from an interpreted expression")
74            }
75            PsInterpretAssertionFailures::InvalidInterpreterMode => {
76                write!(f, "Invalid interpreter mode")
77            }
78            PsInterpretAssertionFailures::MissingResult => write!(f, "Missing result"),
79        }
80    }
81}
82
83#[derive(Debug, Default)]
84pub enum PsInterpretError {
85    #[default]
86    NoError,
87    AssertionFailure(PsInterpretAssertionFailures),
88    MelInterpreterError(Box<MelInterpLocatableError>),
89    InvalidRequest,
90    InvalidUri(url::ParseError),
91    InvalidResponse(String),
92    WrongType(PsInterpretValueType, PsInterpretValueType),
93    WrongMatchGroupValueType(PsInterpretValueType),
94    ProcessableRequestResponseError(prr::Error),
95}
96
97impl error::Error for PsInterpretError {}
98
99impl Display for PsInterpretError {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        match self {
102            PsInterpretError::NoError => write!(f, "No Error"),
103            PsInterpretError::AssertionFailure(af) => {
104                write!(f, "Assertion failure: {af}")
105            }
106            PsInterpretError::MelInterpreterError(meli) => {
107                write!(f, "MEL Interpreter error: {}", meli)
108            }
109            PsInterpretError::InvalidRequest => write!(f, "Invalid HTTP request"),
110            PsInterpretError::InvalidUri(iuri) => write!(f, "Invalid URI: {iuri}"),
111            PsInterpretError::InvalidResponse(response) => {
112                write!(f, "Invalid Response: {response}")
113            }
114            PsInterpretError::WrongType(expected, actual) => {
115                write!(f, "Wrong type: expected: {expected} actual: {actual}",)
116            }
117            PsInterpretError::WrongMatchGroupValueType(actual) => {
118                write!(f, "Match group value should not have {actual} type")
119            }
120            PsInterpretError::ProcessableRequestResponseError(
121                processable_request_response_error,
122            ) => {
123                write!(
124                    f,
125                    "Error occurred when modifying the request/response: {processable_request_response_error}"
126                )
127            }
128        }
129    }
130}
131
132// CDNI Processing Stage Interpreter
133
134pub(crate) struct PsInterpreter<'a> {
135    pub rr: &'a mut dyn prr::Prr<Vec<u8>>,
136}
137
138impl<'a> PsInterpreter<'a> {
139    pub fn install_generic_visitors(&mut self) {}
140
141    fn evaluate_mel_expr(
142        &self,
143        mel_scopes: Scopes<TypedValue>,
144        expr: &Expr<Analyzed>,
145        expected: Type,
146    ) -> Result<TypedValue, PsInterpretError> {
147        let expr_context = MelInterpContext {
148            val: None,
149            scopes: mel_scopes,
150            log: LogMsgs::new(crate::logging::LogLevel::Trace),
151        };
152
153        let result_ctxt = mel::interpreter::interpret(expr, expr_context)
154            .map_err(PsInterpretError::MelInterpreterError)?;
155
156        let result_val = result_ctxt
157            .val
158            .as_ref()
159            .ok_or(PsInterpretError::AssertionFailure(
160                PsInterpretAssertionFailures::MissingInterpreterExpressionValue,
161            ))?;
162
163        if result_val.tpe == expected {
164            Ok(result_val.clone())
165        } else {
166            Err(PsInterpretError::MelInterpreterError(
167                MelInterpLocatableError {
168                    error: MelInterpError::Assertion(
169                        MelInterpAssertion::TypeMismatch(expected, result_val.tpe.clone()).into(),
170                    )
171                    .into(),
172                    context: result_ctxt,
173                    location: expr.location().clone(),
174                }
175                .into(),
176            ))
177        }
178    }
179
180    fn interpret_match_groups_in_stage(
181        &mut self,
182        mgs: &Vec<TypedMatchGroup<PsVerificationKey>>,
183        mut c: PsInterpretContext,
184    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
185        for mg in mgs {
186            c = self.visit_match_group(mg, c)?;
187            match c.result {
188                Some(PsInterpretValue::Terminate | PsInterpretValue::SyntheticResponse(_)) => {
189                    // This result stops processing.
190                    break;
191                }
192                Some(PsInterpretValue::MatchYes | PsInterpretValue::MatchNo) => {
193                    // This result continues processing.
194                    continue;
195                }
196                Some(r) => {
197                    return Err(PsInterpretError::WrongType(
198                        PsInterpretValueType::Terminate,
199                        r.into(),
200                    ));
201                }
202                None => {
203                    return Err(PsInterpretError::AssertionFailure(
204                        PsInterpretAssertionFailures::MissingResult,
205                    ));
206                }
207            }
208        }
209        if let Some(result) = c.result {
210            Ok(PsInterpretContext {
211                mode: c.mode,
212                result: Some(result.clone()),
213                metadata: c.metadata,
214                mel_scopes: c.mel_scopes,
215            })
216        } else {
217            Err(PsInterpretError::AssertionFailure(
218                PsInterpretAssertionFailures::MissingResult,
219            ))
220        }
221    }
222}
223
224#[derive(Debug, Clone, Default, PartialEq)]
225pub enum PsInterpretMode {
226    Request,
227    Response,
228    HeaderAdd,
229    HeaderReplace,
230    HeaderCalculate,
231    #[default]
232    None,
233}
234
235impl From<imdi::InterpretMode> for PsInterpretMode {
236    fn from(value: imdi::InterpretMode) -> Self {
237        match value {
238            imdi::InterpretMode::Request => PsInterpretMode::Request,
239            imdi::InterpretMode::Response => PsInterpretMode::Response,
240        }
241    }
242}
243
244#[derive(Debug, Clone)]
245pub enum PsInterpretValueType {
246    SyntheticResponse,
247    Terminate,
248    MatchResult,
249    Header,
250}
251
252impl Display for PsInterpretValueType {
253    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254        match &self {
255            PsInterpretValueType::SyntheticResponse => write!(f, "Synthetic response"),
256            PsInterpretValueType::Terminate => write!(f, "Terminate"),
257            PsInterpretValueType::MatchResult => write!(f, "Match result"),
258            PsInterpretValueType::Header => write!(f, "Header"),
259        }
260    }
261}
262
263#[derive(Debug, Clone)]
264pub enum PsInterpretValue {
265    SyntheticResponse(http::Response<Vec<u8>>),
266    Terminate,
267    MatchYes,
268    MatchNo,
269    Header(String, String),
270}
271
272impl From<PsInterpretValue> for PsInterpretValueType {
273    fn from(value: PsInterpretValue) -> Self {
274        match value {
275            PsInterpretValue::SyntheticResponse(_) => PsInterpretValueType::SyntheticResponse,
276            PsInterpretValue::Terminate => PsInterpretValueType::Terminate,
277            PsInterpretValue::MatchYes | PsInterpretValue::MatchNo => {
278                PsInterpretValueType::MatchResult
279            }
280            PsInterpretValue::Header(_, _) => PsInterpretValueType::Header,
281        }
282    }
283}
284
285impl From<bool> for PsInterpretValue {
286    fn from(value: bool) -> Self {
287        if value {
288            PsInterpretValue::MatchYes
289        } else {
290            PsInterpretValue::MatchNo
291        }
292    }
293}
294
295#[derive(Debug, Default)]
296pub(crate) struct PsInterpretContext {
297    pub mode: PsInterpretMode,
298    pub result: Option<PsInterpretValue>,
299    pub metadata: MetadataInformationResultElements,
300    pub mel_scopes: Scopes<TypedValue>,
301}
302
303impl PsInterpretContext {
304    fn update_mode(self, new_mode: PsInterpretMode) -> PsInterpretContext {
305        let mut nc = self;
306        nc.mode = new_mode;
307        nc
308    }
309    fn update_result(self, new_result: Option<PsInterpretValue>) -> PsInterpretContext {
310        let mut nc = self;
311        nc.result = new_result;
312        nc
313    }
314
315    fn update_metadata_elements(
316        self,
317        new_element: Box<dyn MetadataInformationResultElement>,
318    ) -> PsInterpretContext {
319        let mut nc = self;
320        nc.metadata.elements.push(new_element);
321        nc
322    }
323    fn replace_metadata_elements(
324        self,
325        new_elements: MetadataInformationResultElements,
326    ) -> PsInterpretContext {
327        let mut nc = self;
328        nc.metadata = new_elements;
329        nc
330    }
331}
332
333impl<'a> PsVisitor<PsVerificationKey, PsInterpretContext, PsInterpretContext, PsInterpretError>
334    for PsInterpreter<'a>
335{
336    fn visit_processing_stages(
337        &mut self,
338        _v: &TypedProcessingStages<PsVerificationKey>,
339        _c: PsInterpretContext,
340    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
341        todo!()
342    }
343
344    fn visit_stage_rules(
345        &mut self,
346        v: &TypedStageRules<PsVerificationKey>,
347        c: PsInterpretContext,
348    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
349        let doq = if let Some(mtch) = &v.value.mtch {
350            let expr = match &mtch.value.aug {
351                PsVerificationKey::Expr(expr) => expr,
352                _ => {
353                    return Err(PsInterpretError::AssertionFailure(
354                        PsInterpretAssertionFailures::MissingAnalyzedExpression,
355                    ));
356                }
357            };
358            let result = self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::Boolean)?;
359            match result {
360                TypedValue {
361                    tpe: Type::Boolean,
362                    value: Value::Boolean(v),
363                } => v,
364                _ => unreachable!(),
365            }
366        } else {
367            true
368        };
369
370        if doq {
371            self.visit_stage_metadata(&v.value.stage_metadata, c.update_result(Some(doq.into())))
372        } else {
373            Ok(c.update_result(Some(doq.into())))
374        }
375    }
376
377    fn visit_expression_match(
378        &mut self,
379        _v: &TypedExpressionMatch<PsVerificationKey>,
380        _c: PsInterpretContext,
381    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
382        todo!()
383    }
384
385    fn visit_stage_metadata(
386        &mut self,
387        v: &TypedStageMetadata<PsVerificationKey>,
388        mut c: PsInterpretContext,
389    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
390        if let Some(generic) = &v.value.generic {
391            for generic in generic {
392                c = self.visit_generic_metadata(generic, c)?;
393            }
394        }
395
396        match &c.mode {
397            PsInterpretMode::Request => {
398                if let Some(req_xform) = &v.value.request_xform {
399                    return self.visit_request_transform(req_xform, c);
400                }
401            }
402            PsInterpretMode::Response => {
403                if let Some(res_xform) = &v.value.response_xform {
404                    return self.visit_response_transform(res_xform, c);
405                }
406            }
407            _ => {
408                return Err(PsInterpretError::AssertionFailure(
409                    PsInterpretAssertionFailures::InvalidInterpreterMode,
410                ));
411            }
412        }
413        Ok(c)
414    }
415
416    fn visit_request_transform(
417        &mut self,
418        v: &TypedRequestTransform<PsVerificationKey>,
419        mut c: PsInterpretContext,
420    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
421        if let Some(header_xform) = &v.value.xform {
422            c = self.visit_header_transform(
423                header_xform,
424                PsInterpretContext {
425                    mode: PsInterpretMode::Request,
426                    metadata: c.metadata,
427                    result: c.result.clone(),
428                    mel_scopes: c.mel_scopes,
429                },
430            )?;
431        }
432
433        if let Some(new_uri) = &v.value.uri {
434            let new_uri = if let Some(uri_is_expr) = &v.value.uri_is_expr
435                && *uri_is_expr
436            {
437                let expr = match &v.value.aug {
438                    PsVerificationKey::Expr(expr) => expr,
439                    _ => {
440                        return Err(PsInterpretError::AssertionFailure(
441                            PsInterpretAssertionFailures::MissingAnalyzedExpression,
442                        ));
443                    }
444                };
445                let result = self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::String)?;
446                match result {
447                    TypedValue {
448                        tpe: Type::String,
449                        value: Value::String(s),
450                    } => url::Url::from_str(&s),
451                    _ => unreachable!(),
452                }
453            } else {
454                url::Url::from_str(&new_uri.clone())
455            }
456            .map_err(PsInterpretError::InvalidUri)?;
457
458            self.rr
459                .set_url(&new_uri)
460                .map_err(PsInterpretError::ProcessableRequestResponseError)?
461        }
462
463        Ok(c)
464    }
465
466    fn visit_response_transform(
467        &mut self,
468        v: &TypedResponseTransform<PsVerificationKey>,
469        mut c: PsInterpretContext,
470    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
471        if let Some(synthetic_response) = &v.value.synthetic {
472            return self.visit_synthetic_response(synthetic_response, c);
473        }
474
475        if let Some(header_xform) = &v.value.xform {
476            c = self
477                .visit_header_transform(header_xform, c.update_mode(PsInterpretMode::Response))?;
478        }
479
480        if let Some(new_response) = &v.value.response_status {
481            let new_response = if let Some(response_is_expr) = &v.value.response_status_expr
482                && *response_is_expr
483            {
484                let expr = match &v.value.aug {
485                    PsVerificationKey::Expr(expr) => expr,
486                    _ => {
487                        return Err(PsInterpretError::AssertionFailure(
488                            PsInterpretAssertionFailures::MissingAnalyzedExpression,
489                        ));
490                    }
491                };
492                let result = self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::Integer)?;
493                match result {
494                    TypedValue {
495                        tpe: Type::Integer,
496                        value: Value::Integer(i),
497                    } => Ok(i),
498                    _ => unreachable!(),
499                }
500            } else {
501                new_response.parse::<i64>()
502            }
503            .map_err(|e| PsInterpretError::InvalidResponse(e.to_string()))?;
504            let new_response = u16::try_from(new_response).map_err(|e| {
505                PsInterpretError::InvalidResponse(format!(
506                    "Could not convert {new_response} to unsigned 16-bit number: {e}"
507                ))
508            })?;
509            self.rr.set_status(&new_response).map_err(|_| {
510                PsInterpretError::ProcessableRequestResponseError(prr::Error::BadValue(
511                    prr::Value {
512                        tpe: prr::ValueType::Status,
513                        value: Some(new_response.to_string()),
514                    },
515                ))
516            })?;
517        }
518
519        Ok(c)
520    }
521
522    fn visit_generic_metadata(
523        &mut self,
524        _v: &TypedGenericMetadata<PsVerificationKey>,
525        _c: PsInterpretContext,
526    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
527        todo!()
528    }
529
530    fn visit_header_transform(
531        &mut self,
532        v: &TypedHeaderTransform<PsVerificationKey>,
533        mut c: PsInterpretContext,
534    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
535        if let Some(to_delete) = &v.value.delete {
536            for htr in to_delete {
537                self.rr
538                    .remove_header(htr)
539                    .map_err(PsInterpretError::ProcessableRequestResponseError)?
540            }
541        }
542
543        if let Some(to_add) = &v.value.add {
544            for htr in to_add {
545                c = self.visit_header(htr, c.update_mode(PsInterpretMode::HeaderAdd))?;
546            }
547        }
548
549        if let Some(to_replace) = &v.value.replace {
550            for htr in to_replace {
551                c = self.visit_header(htr, c.update_mode(PsInterpretMode::HeaderReplace))?;
552            }
553        }
554
555        Ok(c)
556    }
557
558    fn visit_header(
559        &mut self,
560        v: &TypedHeader<PsVerificationKey>,
561        c: PsInterpretContext,
562    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
563        let value = if let Some(expr) = &v.value.value_expr
564            && *expr
565        {
566            let expr = match &v.value.aug {
567                PsVerificationKey::Expr(expr) => expr,
568                _ => {
569                    return Err(PsInterpretError::AssertionFailure(
570                        PsInterpretAssertionFailures::MissingAnalyzedExpression,
571                    ));
572                }
573            };
574            let result = self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::String)?;
575            match result {
576                TypedValue {
577                    tpe: Type::String,
578                    value: Value::String(s),
579                } => s,
580                _ => unreachable!(),
581            }
582        } else {
583            v.value.value.clone()
584        };
585
586        match c.mode {
587            PsInterpretMode::HeaderAdd => {
588                self.rr
589                    .add_header(&v.value.name, &value)
590                    .map_err(PsInterpretError::ProcessableRequestResponseError)?;
591                Ok(c)
592            }
593            PsInterpretMode::HeaderReplace => {
594                self.rr
595                    .set_header_value(&v.value.name, &value)
596                    .map_err(PsInterpretError::ProcessableRequestResponseError)?;
597                Ok(c)
598            }
599            PsInterpretMode::HeaderCalculate => {
600                Ok(c.update_result(Some(PsInterpretValue::Header(v.value.name.clone(), value))))
601            }
602            _ => todo!(),
603        }
604    }
605
606    fn visit_synthetic_response(
607        &mut self,
608        v: &TypedSyntheticResponse<PsVerificationKey>,
609        mut c: PsInterpretContext,
610    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
611        let mut response = http::Response::builder();
612
613        if let Some(headers) = &v.value.headers {
614            for header in headers {
615                //let result = self.visit_header(header, c.update_mode(HeaderCalculate))?;
616
617                c = self.visit_header(header, c.update_mode(PsInterpretMode::HeaderCalculate))?;
618
619                match &c.result {
620                    Some(PsInterpretValue::Header(name, value)) => {
621                        response.headers_mut().unwrap().insert(
622                            http::HeaderName::from_bytes(name.as_bytes()).expect("Todo"),
623                            http::HeaderValue::from_str(value).expect("Todo"),
624                        );
625                    }
626                    Some(r) => {
627                        return Err(PsInterpretError::WrongType(
628                            PsInterpretValueType::Header,
629                            r.clone().into(),
630                        ));
631                    }
632                    None => {
633                        return Err(PsInterpretError::AssertionFailure(
634                            PsInterpretAssertionFailures::MissingAnalyzedExpression,
635                        ));
636                    }
637                }
638            }
639        }
640
641        response = response.status(if let Some(new_response) = &v.value.response_status {
642            if let Some(response_is_expr) = &v.value.response_status_expr
643                && *response_is_expr
644            {
645                let expr = match &v.value.aug {
646                    PsVerificationKey::ExprPair(Some(expr), _) => expr,
647                    _ => {
648                        return Err(PsInterpretError::AssertionFailure(
649                            PsInterpretAssertionFailures::MissingAnalyzedExpression,
650                        ));
651                    }
652                };
653                let result = self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::Integer)?;
654                match result {
655                    TypedValue {
656                        tpe: Type::Integer,
657                        value: Value::Integer(i),
658                    } => http::StatusCode::from_u16(i as u16),
659                    _ => unreachable!(),
660                }
661            } else {
662                new_response.parse::<http::StatusCode>()
663            }
664            .map_err(|e| PsInterpretError::InvalidResponse(e.to_string()))?
665        } else {
666            http::StatusCode::OK
667        });
668
669        let response = response
670            .body(if let Some(body) = &v.value.body {
671                if let Some(body_is_expr) = &v.value.body_expr
672                    && *body_is_expr
673                {
674                    let expr = match &v.value.aug {
675                        PsVerificationKey::ExprPair(_, Some(expr)) => expr,
676                        _ => {
677                            return Err(PsInterpretError::AssertionFailure(
678                                PsInterpretAssertionFailures::MissingAnalyzedExpression,
679                            ));
680                        }
681                    };
682                    let result =
683                        self.evaluate_mel_expr(c.mel_scopes.clone(), expr, Type::String)?;
684                    match result {
685                        TypedValue {
686                            tpe: Type::String,
687                            value: Value::String(s),
688                        } => s.into_bytes(),
689                        _ => unreachable!(),
690                    }
691                } else {
692                    body.to_owned().into_bytes()
693                }
694            } else {
695                "".to_string().into_bytes()
696            })
697            .expect("Could not create HTTP response");
698
699        Ok(c.update_result(Some(PsInterpretValue::SyntheticResponse(response))))
700    }
701
702    fn visit_match_group(
703        &mut self,
704        v: &TypedMatchGroup<PsVerificationKey>,
705        mut c: PsInterpretContext,
706    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
707        let else_ifs = v
708            .value
709            .else_ifs
710            .as_ref()
711            .map(|else_ifs| else_ifs.iter())
712            .unwrap_or([].iter());
713
714        let rules = [&v.value.if_rule].into_iter().chain(else_ifs);
715        for r in rules {
716            c = self.visit_stage_rules(r, c)?;
717            match &c.result {
718                Some(PsInterpretValue::MatchNo) => {
719                    continue; // do the next rule.
720                }
721                Some(_) => {
722                    break; // do _not_ do the next rule in any other case.
723                }
724                None => {
725                    return Err(PsInterpretError::AssertionFailure(
726                        PsInterpretAssertionFailures::MissingResult,
727                    ));
728                }
729            };
730        }
731        if let Some(result) = &c.result {
732            Ok(PsInterpretContext {
733                mode: c.mode,
734                result: Some(result.clone()),
735                metadata: c.metadata,
736                mel_scopes: c.mel_scopes,
737            })
738        } else {
739            Err(PsInterpretError::AssertionFailure(
740                PsInterpretAssertionFailures::MissingResult,
741            ))
742        }
743    }
744
745    fn visit_client_request_stage(
746        &mut self,
747        v: &TypedClientRequestStage<PsVerificationKey>,
748        c: PsInterpretContext,
749    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
750        self.interpret_match_groups_in_stage(&v.value.match_groups, c)
751    }
752
753    fn visit_origin_request_stage(
754        &mut self,
755        v: &TypedOriginRequestStage<PsVerificationKey>,
756        c: PsInterpretContext,
757    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
758        self.interpret_match_groups_in_stage(&v.value.match_groups, c)
759    }
760
761    fn visit_client_response_stage(
762        &mut self,
763        v: &TypedClientResponseStage<PsVerificationKey>,
764        c: PsInterpretContext,
765    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
766        self.interpret_match_groups_in_stage(&v.value.match_groups, c)
767    }
768
769    fn visit_origin_response_stage(
770        &mut self,
771        v: &TypedOriginResponseStage<PsVerificationKey>,
772        c: PsInterpretContext,
773    ) -> PsVisitorResult<PsInterpretContext, PsInterpretError> {
774        self.interpret_match_groups_in_stage(&v.value.match_groups, c)
775    }
776}
777
778/// TODO: Document
779pub fn interpret_stage(
780    ts: &TypedStage<PsVerificationKey>,
781    mel_scopes: &Scopes<TypedValue>,
782    reqres: &mut dyn prr::Prr<Vec<u8>>,
783    mode: PsInterpretMode,
784) -> PsInterpretResult {
785    let mut visitor = PsInterpreter { rr: reqres };
786
787    visitor.install_generic_visitors();
788
789    let context = PsInterpretContext {
790        mel_scopes: mel_scopes.clone(),
791        mode,
792        ..Default::default()
793    };
794
795    let result = match ts {
796        TypedStage::ClientRequest(typed_client_request_stage) => {
797            visitor.visit_client_request_stage(typed_client_request_stage, context)
798        }
799        TypedStage::ClientResponse(typed_client_response_stage) => {
800            visitor.visit_client_response_stage(typed_client_response_stage, context)
801        }
802        TypedStage::OriginRequest(typed_origin_request_stage) => {
803            visitor.visit_origin_request_stage(typed_origin_request_stage, context)
804        }
805        TypedStage::OriginResponse(typed_origin_response_stage) => {
806            visitor.visit_origin_response_stage(typed_origin_response_stage, context)
807        }
808    }?;
809
810    let md = result.metadata;
811    let result = result
812        .result
813        .ok_or(Box::new(PsInterpretError::AssertionFailure(
814            PsInterpretAssertionFailures::MissingResult,
815        )))?;
816    Ok((result, md))
817}
818
819#[derive(Debug)]
820pub(crate) enum EffectfulRequestActions {
821    DeleteHeader(String),
822    AddHeader(String, String),
823    ClearHeaders,
824    SetUri(String),
825    SetBody,
826    SetResponse(u16),
827}
828
829#[derive(Debug)]
830pub(crate) struct EffectfulProcessableRequestResponse {
831    log: Vec<EffectfulRequestActions>,
832    tpe: prr::PrrType,
833}
834
835impl EffectfulProcessableRequestResponse {
836    fn new_request() -> Self {
837        EffectfulProcessableRequestResponse {
838            log: Default::default(),
839            tpe: prr::PrrType::Request,
840        }
841    }
842
843    fn new_response() -> Self {
844        EffectfulProcessableRequestResponse {
845            log: Default::default(),
846            tpe: prr::PrrType::Response,
847        }
848    }
849}
850
851impl prr::Prr<Vec<u8>> for EffectfulProcessableRequestResponse {
852    fn headers(&self) -> Vec<(String, http::HeaderValue)> {
853        vec![]
854    }
855
856    fn set_header_value(&mut self, _header: &str, _value: &str) -> Result<(), prr::Error> {
857        Ok(())
858    }
859
860    fn clear_headers(&mut self) -> prr::Result<()> {
861        self.log.push(EffectfulRequestActions::ClearHeaders);
862        Ok(())
863    }
864
865    fn remove_header(&mut self, header: &str) -> Result<(), prr::Error> {
866        self.log
867            .push(EffectfulRequestActions::DeleteHeader(header.to_string()));
868        Ok(())
869    }
870
871    fn url(&self) -> Result<url::Url, prr::Error> {
872        Ok(url::Url::from_str("http://www.example.com/").expect("Could not make default URL"))
873    }
874
875    fn set_url(&mut self, url: &url::Url) -> Result<(), prr::Error> {
876        self.log
877            .push(EffectfulRequestActions::SetUri(url.to_string()));
878        Ok(())
879    }
880
881    fn set_status(&mut self, response: &u16) -> Result<(), prr::Error> {
882        self.log
883            .push(EffectfulRequestActions::SetResponse(*response));
884        Ok(())
885    }
886
887    fn add_header(&mut self, header: &str, value: &str) -> Result<(), prr::Error> {
888        self.log.push(EffectfulRequestActions::AddHeader(
889            header.to_string(),
890            value.to_string(),
891        ));
892        Ok(())
893    }
894
895    fn set_body(&mut self, _: &Vec<u8>) -> prr::Result<()> {
896        self.log.push(EffectfulRequestActions::SetBody);
897        Ok(())
898    }
899
900    fn get_body(&self) -> prr::Result<&Vec<u8>> {
901        todo!()
902    }
903
904    fn get_status(&self) -> prr::Result<http::StatusCode> {
905        todo!()
906    }
907
908    fn tpe(&self) -> prr::PrrType {
909        self.tpe.clone()
910    }
911
912    fn set_method(&mut self, _method: &http::Method) -> prr::Result<()> {
913        todo!()
914    }
915
916    fn get_method(&self) -> http::Method {
917        todo!()
918    }
919}
920
921impl
922    Interpreter<
923        SimpleProcessorsInterpreterContext<'_>,
924        (imdi::ResultValue, MetadataInformationResultElements),
925        Stages,
926        Error,
927    > for TypedStage<PsVerificationKey>
928{
929    fn interpret<'a>(
930        &self,
931        input: SimpleProcessorsInterpreterContext<'a>,
932    ) -> interpret::InterpretationResult<
933        SimpleProcessorsInterpreterContext<'a>,
934        (imdi::ResultValue, MetadataInformationResultElements),
935        Error,
936    > {
937        let (mut res, mut req) = (input.res, input.req);
938        let reqres = match input.mode {
939            imdi::InterpretMode::Request => &mut req,
940            imdi::InterpretMode::Response => {
941                if let Some(res) = &mut res {
942                    res
943                } else {
944                    return Err(Error::RuntimeError(
945                        Error::AssertionFailure("Missing request".into()).into(),
946                    )
947                    .into());
948                }
949            }
950        };
951
952        let mut visitor = PsInterpreter { rr: &mut **reqres };
953
954        visitor.install_generic_visitors();
955
956        let context = PsInterpretContext {
957            mode: input.mode.clone().into(),
958            mel_scopes: input.scopes.clone(),
959            ..Default::default()
960        };
961
962        let result = match self {
963            TypedStage::ClientRequest(typed_client_request_stage) => {
964                visitor.visit_client_request_stage(typed_client_request_stage, context)
965            }
966            TypedStage::ClientResponse(typed_client_response_stage) => {
967                visitor.visit_client_response_stage(typed_client_response_stage, context)
968            }
969            TypedStage::OriginRequest(typed_origin_request_stage) => {
970                visitor.visit_origin_request_stage(typed_origin_request_stage, context)
971            }
972            TypedStage::OriginResponse(typed_origin_response_stage) => {
973                visitor.visit_origin_response_stage(typed_origin_response_stage, context)
974            }
975        }
976        .map_err(|e| Error::RuntimeError(e.into()))?;
977
978        let md = result.metadata;
979        let result = result.result.ok_or(Error::RuntimeError(
980            PsInterpretError::AssertionFailure(PsInterpretAssertionFailures::MissingResult).into(),
981        ))?;
982
983        // If there was a synthetic result, then that should be the result. Otherwise,
984        // there is no result worth reporting.
985        let result = match result {
986            PsInterpretValue::SyntheticResponse(sr) => Some(sr),
987            _ => None,
988        };
989
990        let updated_context = SimpleProcessorsInterpreterContext {
991            scopes: input.scopes,
992            mode: input.mode,
993            runtime: input.runtime,
994            req,
995            res,
996        };
997        Ok((updated_context, (result, md)))
998    }
999
1000    fn at(&self, stage: Stages) -> bool {
1001        match &self {
1002            // The [Origin|Client]RequestStage metadata can contain request and response transforms.
1003            TypedStage::ClientRequest(_) => stage == ClientRequest || stage == ClientResponse,
1004            TypedStage::OriginRequest(_) => stage == OriginRequest || stage == OriginResponse,
1005            TypedStage::ClientResponse(_) => stage == ClientResponse,
1006            TypedStage::OriginResponse(_) => stage == OriginResponse,
1007        }
1008    }
1009}
1010
1011#[cfg(test)]
1012mod ps_interpreter_tests {
1013    use crate::{
1014        cdni::{
1015            ps::spec::{TypedGenericStage, TypedStage},
1016            tests::test_helpers::{
1017                client_request_stage, expression_match, match_group, request_transform,
1018                response_transform, stage_metadata, synthetic_response, typed_header,
1019                typed_stage_rule,
1020            },
1021        },
1022        dcdn::processors::ps::{
1023            EffectfulProcessableRequestResponse, EffectfulRequestActions, PsInterpretMode,
1024            PsInterpretValue, interpret_stage,
1025        },
1026        environment::scope::Scopes,
1027        mel::types::Type,
1028        tests::read_test_file,
1029        verifying::ps::verify::{PsVerifierContextValue, verifier, verify_ps_request_stage},
1030        visitors::PsVisitor,
1031    };
1032    use std::assert_matches;
1033    use std::path::Path;
1034
1035    #[test]
1036    fn test_interpret_client_request_stage() {
1037        let json = read_test_file(Path::new(
1038            "./tests/data/processing/client_request_stage/if.json",
1039        ));
1040
1041        let result = serde_json::from_str::<TypedGenericStage>(&json)
1042            .expect("Could not deserialize simple client request stage JSON");
1043
1044        let result = verify_ps_request_stage(&result, &Scopes::<Type>::default())
1045            .expect("Could not verify valid client request stage JSON");
1046
1047        let mut req = EffectfulProcessableRequestResponse::new_request();
1048        let result = interpret_stage(
1049            &result,
1050            &Scopes { scopes: vec![] },
1051            &mut req,
1052            PsInterpretMode::Request,
1053        )
1054        .expect("Could not interpret a valid client request");
1055
1056        assert_eq!(req.log.len(), 2);
1057        assert_matches!(req.log[0], EffectfulRequestActions::DeleteHeader(_));
1058        assert_matches!(req.log[1], EffectfulRequestActions::AddHeader(_, _));
1059        assert_matches!(result.0, PsInterpretValue::MatchYes);
1060    }
1061
1062    #[test]
1063    fn test_interpret_client_request_stage_request_response_header_transform() {
1064        let json = read_test_file(Path::new(
1065            "./tests/data/processing/client_request_stage/request_response_header_transform.json",
1066        ));
1067
1068        let result = serde_json::from_str::<TypedGenericStage>(&json)
1069            .expect("Could not deserialize simple client request stage JSON");
1070
1071        let result = verify_ps_request_stage(&result, &Scopes::<Type>::default())
1072            .expect("Could not verify valid client request stage JSON");
1073        let mut req = EffectfulProcessableRequestResponse::new_request();
1074        let result = interpret_stage(
1075            &result,
1076            &Scopes { scopes: vec![] },
1077            &mut req,
1078            PsInterpretMode::Request,
1079        )
1080        .expect("Could not interpret a valid client request");
1081
1082        assert_eq!(req.log.len(), 2);
1083        assert_matches!(req.log[0], EffectfulRequestActions::DeleteHeader(_));
1084        assert_matches!(req.log[1], EffectfulRequestActions::AddHeader(_, _));
1085        assert_matches!(result.0, PsInterpretValue::MatchYes);
1086    }
1087
1088    #[test]
1089    fn test_interpret_client_request_stage_request_uri_transform() {
1090        let mut request_xform_stage = stage_metadata();
1091
1092        let request_xform_match = expression_match("true");
1093        let request_xform = request_transform(
1094            None,
1095            Some("\"http://\" . \"example.com\"".to_string()),
1096            Some(true),
1097        );
1098        request_xform_stage.value.request_xform = Some(request_xform);
1099
1100        let request_xform_mg = match_group(
1101            typed_stage_rule(Some(request_xform_match), request_xform_stage),
1102            None,
1103        );
1104
1105        let crs = client_request_stage(vec![request_xform_mg]);
1106
1107        let (mut verifier, context) = verifier();
1108
1109        let result = verifier
1110            .visit_client_request_stage(&crs, context)
1111            .expect("Could not verify valid client request")
1112            .value
1113            .expect("Could not get value from verified client request");
1114
1115        let value = match result {
1116            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1117                typed_client_request_stage
1118            }
1119            _ => todo!(),
1120        };
1121        let mut req = EffectfulProcessableRequestResponse::new_request();
1122        let result = interpret_stage(
1123            &TypedStage::ClientRequest(value),
1124            &Scopes { scopes: vec![] },
1125            &mut req,
1126            PsInterpretMode::Request,
1127        )
1128        .expect("Could not interpret a valid client request");
1129
1130        assert_eq!(req.log.len(), 1);
1131        assert_matches!(&req.log[0], EffectfulRequestActions::SetUri(r) if r == "http://example.com/");
1132        assert_matches!(result.0, PsInterpretValue::MatchYes);
1133    }
1134
1135    #[test]
1136    fn test_interpret_client_request_stage_request_uri_transform_if() {
1137        let mut request_xform_false_stage = stage_metadata();
1138        let mut request_xform_true_stage = stage_metadata();
1139
1140        let request_xform_false_match = expression_match("true");
1141        let request_xform_false = request_transform(
1142            None,
1143            Some("\"http://\" . \"example.com\"".to_string()),
1144            Some(true),
1145        );
1146        request_xform_false_stage.value.request_xform = Some(request_xform_false);
1147
1148        let request_xform_true_match = expression_match("true");
1149        let request_xform_true = request_transform(
1150            None,
1151            Some("\"http://\" . \"example2.com\"".to_string()),
1152            Some(true),
1153        );
1154        request_xform_true_stage.value.request_xform = Some(request_xform_true);
1155
1156        let mg = match_group(
1157            typed_stage_rule(Some(request_xform_false_match), request_xform_false_stage),
1158            Some(vec![typed_stage_rule(
1159                Some(request_xform_true_match),
1160                request_xform_true_stage,
1161            )]),
1162        );
1163        let crs = client_request_stage(vec![mg]);
1164
1165        let (mut verifier, context) = verifier();
1166
1167        let result = verifier
1168            .visit_client_request_stage(&crs, context)
1169            .expect("Could not verify valid client request")
1170            .value
1171            .expect("Could not get value from verified client request");
1172
1173        let value = match result {
1174            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1175                typed_client_request_stage
1176            }
1177            _ => todo!(),
1178        };
1179        let mut req = EffectfulProcessableRequestResponse::new_request();
1180        let result = interpret_stage(
1181            &TypedStage::ClientRequest(value),
1182            &Scopes { scopes: vec![] },
1183            &mut req,
1184            PsInterpretMode::Request,
1185        )
1186        .expect("Could not interpret a valid client request");
1187
1188        assert_eq!(req.log.len(), 1);
1189        assert_matches!(&req.log[0], EffectfulRequestActions::SetUri(r) if r == "http://example.com/");
1190        assert_matches!(result.0, PsInterpretValue::MatchYes);
1191    }
1192
1193    #[test]
1194    fn test_interpret_client_request_stage_request_uri_transform_else() {
1195        let mut request_xform_false_stage = stage_metadata();
1196        let mut request_xform_false_false_stage = stage_metadata();
1197        let mut request_xform_true_stage = stage_metadata();
1198
1199        let request_xform_false_match = expression_match("false");
1200        let request_xform_false = request_transform(
1201            None,
1202            Some("\"http://\" . \"example.com\"".to_string()),
1203            Some(true),
1204        );
1205        request_xform_false_stage.value.request_xform = Some(request_xform_false);
1206
1207        let request_xform_false_false_match = expression_match("true");
1208        let request_xform_false_false = request_transform(
1209            None,
1210            Some("\"http://\" . \"example1.com\"".to_string()),
1211            Some(true),
1212        );
1213        request_xform_false_false_stage.value.request_xform = Some(request_xform_false_false);
1214
1215        let request_xform_true_match = expression_match("true");
1216        let request_xform_true = request_transform(
1217            None,
1218            Some("\"http://\" . \"example2.com\"".to_string()),
1219            Some(true),
1220        );
1221
1222        request_xform_true_stage.value.request_xform = Some(request_xform_true);
1223
1224        let mg = match_group(
1225            typed_stage_rule(Some(request_xform_false_match), request_xform_false_stage),
1226            Some(vec![
1227                typed_stage_rule(
1228                    Some(request_xform_false_false_match),
1229                    request_xform_false_false_stage,
1230                ),
1231                typed_stage_rule(Some(request_xform_true_match), request_xform_true_stage),
1232            ]),
1233        );
1234        let crs = client_request_stage(vec![mg]);
1235
1236        let (mut verifier, context) = verifier();
1237
1238        let result = verifier
1239            .visit_client_request_stage(&crs, context)
1240            .expect("Could not verify valid client request")
1241            .value
1242            .expect("Could not get value from verified client request");
1243
1244        let value = match result {
1245            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1246                typed_client_request_stage
1247            }
1248            _ => todo!(),
1249        };
1250        let mut req = EffectfulProcessableRequestResponse::new_request();
1251        let result = interpret_stage(
1252            &TypedStage::ClientRequest(value),
1253            &Scopes { scopes: vec![] },
1254            &mut req,
1255            PsInterpretMode::Request,
1256        )
1257        .expect("Could not interpret a valid client request");
1258
1259        assert_eq!(req.log.len(), 1);
1260        assert_matches!(&req.log[0], EffectfulRequestActions::SetUri(r) if r == "http://example1.com/");
1261        assert_matches!(result.0, PsInterpretValue::MatchYes);
1262    }
1263
1264    fn test_interpret_client_request_stage_request_uri_transform_else_if() {
1265        let mut request_xform_false_stage = stage_metadata();
1266        let mut request_xform_false_false_stage = stage_metadata();
1267        let mut request_xform_true_stage = stage_metadata();
1268
1269        let request_xform_false_match = expression_match("false");
1270        let request_xform_false = request_transform(
1271            None,
1272            Some("\"http://\" . \"example.com\"".to_string()),
1273            Some(true),
1274        );
1275        request_xform_false_stage.value.request_xform = Some(request_xform_false);
1276
1277        let request_xform_false_false_match = expression_match("false");
1278        let request_xform_false_false = request_transform(
1279            None,
1280            Some("\"http://\" . \"example1.com\"".to_string()),
1281            Some(true),
1282        );
1283        request_xform_false_false_stage.value.request_xform = Some(request_xform_false_false);
1284
1285        let request_xform_true_match = expression_match("true");
1286        let request_xform_true = request_transform(
1287            None,
1288            Some("\"http://\" . \"example2.com\"".to_string()),
1289            Some(true),
1290        );
1291
1292        request_xform_true_stage.value.request_xform = Some(request_xform_true);
1293
1294        let mg = match_group(
1295            typed_stage_rule(Some(request_xform_false_match), request_xform_false_stage),
1296            Some(vec![
1297                typed_stage_rule(
1298                    Some(request_xform_false_false_match),
1299                    request_xform_false_false_stage,
1300                ),
1301                typed_stage_rule(Some(request_xform_true_match), request_xform_true_stage),
1302            ]),
1303        );
1304        let crs = client_request_stage(vec![mg]);
1305
1306        let (mut verifier, context) = verifier();
1307
1308        let result = verifier
1309            .visit_client_request_stage(&crs, context)
1310            .expect("Could not verify valid client request")
1311            .value
1312            .expect("Could not get value from verified client request");
1313
1314        let value = match result {
1315            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1316                typed_client_request_stage
1317            }
1318            _ => todo!(),
1319        };
1320        let mut req = EffectfulProcessableRequestResponse::new_request();
1321        let result = interpret_stage(
1322            &TypedStage::ClientRequest(value),
1323            &Scopes { scopes: vec![] },
1324            &mut req,
1325            PsInterpretMode::Request,
1326        )
1327        .expect("Could not interpret a valid client request");
1328
1329        assert_eq!(req.log.len(), 1);
1330        assert_matches!(&req.log[0], EffectfulRequestActions::SetUri(r) if r == "http://example2.com/");
1331        assert_matches!(result.0, PsInterpretValue::MatchYes);
1332    }
1333
1334    #[test]
1335    fn test_interpret_client_request_stage_response_status_transform() {
1336        let mut response_xform_stage = stage_metadata();
1337
1338        let response_xform_match = expression_match("true");
1339        let response_xform = response_transform(None, Some("5 + 4".to_string()), Some(true), None);
1340        response_xform_stage.value.response_xform = Some(response_xform);
1341
1342        let response_xform_mg = match_group(
1343            typed_stage_rule(Some(response_xform_match), response_xform_stage),
1344            None,
1345        );
1346
1347        let crs = client_request_stage(vec![response_xform_mg]);
1348
1349        let (mut verifier, context) = verifier();
1350
1351        let result = verifier
1352            .visit_client_request_stage(&crs, context)
1353            .expect("Could not verify valid client request")
1354            .value
1355            .expect("Could not get value from verified client request");
1356
1357        let value = match result {
1358            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1359                typed_client_request_stage
1360            }
1361            _ => todo!(),
1362        };
1363        let mut req = EffectfulProcessableRequestResponse::new_request();
1364        interpret_stage(
1365            &TypedStage::ClientRequest(value),
1366            &Scopes { scopes: vec![] },
1367            &mut req,
1368            PsInterpretMode::Response,
1369        )
1370        .expect("Could not interpret a valid client request");
1371
1372        assert_eq!(req.log.len(), 1);
1373        assert_matches!(&req.log[0], EffectfulRequestActions::SetResponse(9));
1374    }
1375
1376    #[test]
1377    fn test_interpret_client_request_stage_response_status_transform_if() {
1378        let mut response_xform_false_stage = stage_metadata();
1379        let mut response_xform_true_stage = stage_metadata();
1380
1381        let response_xform_false_match = expression_match("true");
1382        let response_xform_false =
1383            response_transform(None, Some("5 + 4".to_string()), Some(true), None);
1384        response_xform_false_stage.value.response_xform = Some(response_xform_false);
1385
1386        let response_xform_true_match = expression_match("true");
1387        let response_xform_true =
1388            response_transform(None, Some("5 + 5".to_string()), Some(true), None);
1389        response_xform_true_stage.value.response_xform = Some(response_xform_true);
1390
1391        let mg = match_group(
1392            typed_stage_rule(Some(response_xform_false_match), response_xform_false_stage),
1393            Some(vec![typed_stage_rule(
1394                Some(response_xform_true_match),
1395                response_xform_true_stage,
1396            )]),
1397        );
1398        let crs = client_request_stage(vec![mg]);
1399
1400        let (mut verifier, context) = verifier();
1401
1402        let result = verifier
1403            .visit_client_request_stage(&crs, context)
1404            .expect("Could not verify valid client request")
1405            .value
1406            .expect("Could not get value from verified client request");
1407
1408        let value = match result {
1409            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1410                typed_client_request_stage
1411            }
1412            _ => todo!(),
1413        };
1414        let mut req = EffectfulProcessableRequestResponse::new_request();
1415        let result = interpret_stage(
1416            &TypedStage::ClientRequest(value),
1417            &Scopes { scopes: vec![] },
1418            &mut req,
1419            PsInterpretMode::Response,
1420        )
1421        .expect("Could not interpret a valid client request");
1422
1423        assert_eq!(req.log.len(), 1);
1424        assert_matches!(&req.log[0], EffectfulRequestActions::SetResponse(9));
1425        assert_matches!(result.0, PsInterpretValue::MatchYes);
1426    }
1427
1428    #[test]
1429    fn test_interpret_client_request_stage_response_status_transform_else() {
1430        let mut response_xform_false_stage = stage_metadata();
1431        let mut response_xform_false_false_stage = stage_metadata();
1432        let mut response_xform_true_stage = stage_metadata();
1433
1434        let response_xform_false_match = expression_match("false");
1435        let response_xform_false =
1436            response_transform(None, Some("5 + 4".to_string()), Some(true), None);
1437        response_xform_false_stage.value.response_xform = Some(response_xform_false);
1438
1439        let response_xform_false_false_match = expression_match("true");
1440        let response_xform_false_false =
1441            response_transform(None, Some("5 + 5".to_string()), Some(true), None);
1442        response_xform_false_false_stage.value.response_xform = Some(response_xform_false_false);
1443
1444        let response_xform_true_match = expression_match("true");
1445        let response_xform_true =
1446            response_transform(None, Some("5 + 6".to_string()), Some(true), None);
1447
1448        response_xform_true_stage.value.response_xform = Some(response_xform_true);
1449
1450        let mg = match_group(
1451            typed_stage_rule(Some(response_xform_false_match), response_xform_false_stage),
1452            Some(vec![
1453                typed_stage_rule(
1454                    Some(response_xform_false_false_match),
1455                    response_xform_false_false_stage,
1456                ),
1457                typed_stage_rule(Some(response_xform_true_match), response_xform_true_stage),
1458            ]),
1459        );
1460        let crs = client_request_stage(vec![mg]);
1461
1462        let (mut verifier, context) = verifier();
1463
1464        let result = verifier
1465            .visit_client_request_stage(&crs, context)
1466            .expect("Could not verify valid client request")
1467            .value
1468            .expect("Could not get value from verified client request");
1469
1470        let value = match result {
1471            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1472                typed_client_request_stage
1473            }
1474            _ => todo!(),
1475        };
1476        let mut req = EffectfulProcessableRequestResponse::new_request();
1477        let result = interpret_stage(
1478            &TypedStage::ClientRequest(value),
1479            &Scopes { scopes: vec![] },
1480            &mut req,
1481            PsInterpretMode::Response,
1482        )
1483        .expect("Could not interpret a valid client request");
1484
1485        assert_eq!(req.log.len(), 1);
1486        assert_matches!(&req.log[0], EffectfulRequestActions::SetResponse(10));
1487        assert_matches!(result.0, PsInterpretValue::MatchYes);
1488    }
1489
1490    fn test_interpret_client_request_stage_response_status_transform_else_if() {
1491        let mut response_xform_false_stage = stage_metadata();
1492        let mut response_xform_false_false_stage = stage_metadata();
1493        let mut response_xform_true_stage = stage_metadata();
1494
1495        let response_xform_false_match = expression_match("false");
1496        let response_xform_false =
1497            response_transform(None, Some("5 + 4".to_string()), Some(true), None);
1498        response_xform_false_stage.value.response_xform = Some(response_xform_false);
1499
1500        let response_xform_false_false_match = expression_match("false");
1501        let response_xform_false_false =
1502            response_transform(None, Some("5 + 5".to_string()), Some(true), None);
1503        response_xform_false_false_stage.value.response_xform = Some(response_xform_false_false);
1504
1505        let response_xform_true_match = expression_match("true");
1506        let response_xform_true =
1507            response_transform(None, Some("5 + 6".to_string()), Some(true), None);
1508
1509        response_xform_true_stage.value.response_xform = Some(response_xform_true);
1510
1511        let mg = match_group(
1512            typed_stage_rule(Some(response_xform_false_match), response_xform_false_stage),
1513            Some(vec![
1514                typed_stage_rule(
1515                    Some(response_xform_false_false_match),
1516                    response_xform_false_false_stage,
1517                ),
1518                typed_stage_rule(Some(response_xform_true_match), response_xform_true_stage),
1519            ]),
1520        );
1521        let crs = client_request_stage(vec![mg]);
1522
1523        let (mut verifier, context) = verifier();
1524
1525        let result = verifier
1526            .visit_client_request_stage(&crs, context)
1527            .expect("Could not verify valid client request")
1528            .value
1529            .expect("Could not get value from verified client request");
1530
1531        let value = match result {
1532            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1533                typed_client_request_stage
1534            }
1535            _ => todo!(),
1536        };
1537        let mut req = EffectfulProcessableRequestResponse::new_request();
1538        let result = interpret_stage(
1539            &TypedStage::ClientRequest(value),
1540            &Scopes { scopes: vec![] },
1541            &mut req,
1542            PsInterpretMode::Response,
1543        )
1544        .expect("Could not interpret a valid client request");
1545
1546        assert_eq!(req.log.len(), 1);
1547        assert_matches!(&req.log[0], EffectfulRequestActions::SetResponse(11));
1548        assert_matches!(result.0, PsInterpretValue::MatchYes);
1549    }
1550
1551    #[test]
1552    fn test_interpret_client_request_stage_response_synthetic() {
1553        let mut response_xform_true_stage = stage_metadata();
1554
1555        let response_xform_true_match = expression_match("true");
1556        let response_xform_true = response_transform(
1557            None,
1558            None,
1559            None,
1560            Some(synthetic_response(
1561                Some(vec![
1562                    typed_header("X-custom1", "Custom value 1", None),
1563                    typed_header("X-custom2", "Custom value 2", None),
1564                ]),
1565                Some("400 + 4".to_string()),
1566                Some(true),
1567                Some("\"This \" . \"is \" . \"a \" . \"test.\"".to_string()),
1568                Some(true),
1569            )),
1570        );
1571        response_xform_true_stage.value.response_xform = Some(response_xform_true);
1572
1573        let mg = match_group(
1574            typed_stage_rule(Some(response_xform_true_match), response_xform_true_stage),
1575            None,
1576        );
1577        let crs = client_request_stage(vec![mg]);
1578
1579        let (mut verifier, context) = verifier();
1580
1581        let result = verifier
1582            .visit_client_request_stage(&crs, context)
1583            .expect("Could not verify valid client request")
1584            .value
1585            .expect("Could not get value from verified client request");
1586
1587        let value = match result {
1588            PsVerifierContextValue::ClientRequestStage(typed_client_request_stage) => {
1589                typed_client_request_stage
1590            }
1591            _ => todo!(),
1592        };
1593        let mut req = EffectfulProcessableRequestResponse::new_request();
1594        let result = interpret_stage(
1595            &TypedStage::ClientRequest(value),
1596            &Scopes { scopes: vec![] },
1597            &mut req,
1598            PsInterpretMode::Response,
1599        )
1600        .expect("Could not interpret a valid client request");
1601
1602        assert_eq!(req.log.len(), 0);
1603        assert_matches!(&result.0, PsInterpretValue::SyntheticResponse(r)
1604            if r.status() == 404 && r.body() == &"This is a test.".to_string().into_bytes() && r.headers().len() == 2);
1605    }
1606}