esi/
document.rs

1use std::collections::VecDeque;
2
3use crate::{PendingFragmentContent, Result};
4use fastly::Request;
5use quick_xml::Writer;
6
7/// Represents a fragment of a document that can be fetched and processed.
8///
9/// A `Fragment` contains the necessary information to make a request for a part of a document,
10/// handle potential errors, and retrieve the content asynchronously.
11///
12/// # Fields
13///
14/// * `request` - Metadata of the request.
15/// * `alt` - An optional alternate request to send if the original request fails.
16/// * `continue_on_error` - Whether to continue processing on error.
17/// * `pending_content` - The pending fragment response, which can be polled to retrieve the content.
18pub struct Fragment {
19    // Metadata of the request
20    pub(crate) request: Request,
21    // An optional alternate request to send if the original request fails
22    pub(crate) alt: Option<Result<Request>>,
23    // Whether to continue on error
24    pub(crate) continue_on_error: bool,
25    // The pending fragment response, which can be polled to retrieve the content
26    pub(crate) pending_content: PendingFragmentContent,
27}
28
29/// `Task` is combining raw data and an include fragment for both `attempt` and `except` arms
30/// the result is written to `output`.
31///
32/// # Fields:
33///
34/// * `queue` - A queue of elements to process.
35/// * `output` - The writer to write the processed data to.
36/// * `status` - The status of the fetch operation.
37pub struct Task {
38    pub queue: VecDeque<Element>,
39    pub output: Writer<Vec<u8>>,
40    pub status: FetchState,
41}
42
43impl Default for Task {
44    fn default() -> Self {
45        Self {
46            queue: VecDeque::new(),
47            output: Writer::new(Vec::new()),
48            status: FetchState::default(),
49        }
50    }
51}
52
53impl Task {
54    pub fn new() -> Self {
55        Self::default()
56    }
57}
58
59/// A section of the pending response, either raw XML data or a pending fragment request.
60/// * `Raw` - Raw XML data.
61/// * `Include` - A pending fragment request.
62/// * `Try` - A try block with an attempt and except task.
63///
64pub enum Element {
65    Raw(Vec<u8>),
66    Include(Box<Fragment>),
67    Try {
68        except_task: Box<Task>,
69        attempt_task: Box<Task>,
70    },
71}
72
73/// The state of a fetch operation.
74/// * `Failed` - The request failed with the given status code.
75/// * `Pending` - The request is still pending.
76/// * `Succeeded` - The request succeeded.
77///
78pub enum FetchState {
79    Failed(Request, u16),
80    Pending,
81    Succeeded,
82}
83impl Clone for FetchState {
84    fn clone(&self) -> Self {
85        match self {
86            Self::Failed(req, res) => Self::Failed(req.clone_without_body(), *res),
87            Self::Pending => Self::Pending,
88            Self::Succeeded => Self::Succeeded,
89        }
90    }
91}
92impl Default for FetchState {
93    fn default() -> Self {
94        Self::Pending
95    }
96}
97
98impl std::fmt::Debug for Element {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        match self {
101            Self::Raw(_) => write!(f, "Raw"),
102            Self::Include(fragment) if fragment.alt.is_some() => {
103                write!(f, "Include Fragment(with alt)")
104            }
105            Self::Include(_) => write!(f, "Include Fragment"),
106            Self::Try {
107                attempt_task,
108                except_task,
109            } => write!(
110                f,
111                "Try - Attempt: {:?}, Except: {:?}",
112                attempt_task.queue, except_task.queue
113            ),
114        }
115    }
116}