Skip to main content

playwright_rs/protocol/
file_payload.rs

1// FilePayload protocol type
2//
3// Represents a file to be uploaded with explicit name, MIME type, and buffer.
4//
5// See: https://playwright.dev/docs/api/class-locator#locator-set-input-files
6
7/// FilePayload represents a file for advanced file uploads.
8///
9/// Allows explicit control over filename, MIME type, and file contents
10/// when uploading files to input elements.
11///
12/// # Example
13///
14/// ```ignore
15/// # use playwright_rs::protocol::FilePayload;
16/// let file = FilePayload::builder()
17///     .name("document.pdf".to_string())
18///     .mime_type("application/pdf".to_string())
19///     .buffer(vec![/* PDF bytes */])
20///     .build();
21/// ```
22///
23/// See: <https://playwright.dev/docs/api/class-locator#locator-set-input-files>
24#[derive(Debug, Clone)]
25pub struct FilePayload {
26    /// File name
27    pub name: String,
28    /// MIME type
29    pub mime_type: String,
30    /// File contents as bytes
31    pub buffer: Vec<u8>,
32}
33
34use crate::error::Result;
35use mime_guess::from_path;
36use std::fs;
37use std::path::Path;
38
39impl FilePayload {
40    /// Creates a new builder for FilePayload
41    pub fn builder() -> FilePayloadBuilder {
42        FilePayloadBuilder::default()
43    }
44
45    /// Creates a FilePayload from a file path.
46    ///
47    /// Automatically detects the MIME type based on the file extension.
48    /// Reads the file into memory.
49    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self> {
50        let path = path.as_ref();
51        let name = path
52            .file_name()
53            .ok_or_else(|| crate::Error::InvalidPath(format!("Path {:?} has no filename", path)))?
54            .to_string_lossy()
55            .into_owned();
56
57        let mime_type = from_path(path).first_or_octet_stream().to_string();
58        let buffer = fs::read(path)?;
59
60        Ok(Self {
61            name,
62            mime_type,
63            buffer,
64        })
65    }
66
67    /// Creates a FilePayload from a file path with an explicit MIME type.
68    pub fn from_file<P: AsRef<Path>>(path: P, mime_type: &str) -> Result<Self> {
69        let path = path.as_ref();
70        let name = path
71            .file_name()
72            .ok_or_else(|| crate::Error::InvalidPath(format!("Path {:?} has no filename", path)))?
73            .to_string_lossy()
74            .into_owned();
75
76        let buffer = fs::read(path)?;
77
78        Ok(Self {
79            name,
80            mime_type: mime_type.to_string(),
81            buffer,
82        })
83    }
84}
85
86/// Builder for FilePayload
87#[derive(Debug, Clone, Default)]
88pub struct FilePayloadBuilder {
89    name: Option<String>,
90    mime_type: Option<String>,
91    buffer: Option<Vec<u8>>,
92}
93
94impl FilePayloadBuilder {
95    /// Sets the file name
96    pub fn name(mut self, name: String) -> Self {
97        self.name = Some(name);
98        self
99    }
100
101    /// Sets the MIME type
102    pub fn mime_type(mut self, mime_type: String) -> Self {
103        self.mime_type = Some(mime_type);
104        self
105    }
106
107    /// Sets the file buffer (contents as bytes)
108    pub fn buffer(mut self, buffer: Vec<u8>) -> Self {
109        self.buffer = Some(buffer);
110        self
111    }
112
113    /// Builds the FilePayload
114    ///
115    /// # Panics
116    ///
117    /// Panics if any required field (name, mime_type, buffer) is missing
118    pub fn build(self) -> FilePayload {
119        FilePayload {
120            name: self.name.expect("name is required for FilePayload"),
121            mime_type: self
122                .mime_type
123                .expect("mime_type is required for FilePayload"),
124            buffer: self.buffer.expect("buffer is required for FilePayload"),
125        }
126    }
127}