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}