ferrijs_std/buffer/
file.rs1use crate::utils::time;
4use rquickjs::{
5 atom::PredefinedAtom, class::Trace, function::Opt, ArrayBuffer, Coerced, Ctx, Exception, Result,
6 Value,
7};
8
9use super::blob::Blob;
10
11#[rquickjs::class]
12#[derive(Trace, Clone, rquickjs::JsLifetime)]
13pub struct File<'js> {
14 blob: Blob<'js>,
15 filename: String,
16 last_modified: i64,
17}
18
19#[rquickjs::methods]
20impl<'js> File<'js> {
21 #[qjs(constructor)]
22 fn new(
23 ctx: Ctx<'js>,
24 data: Value<'js>,
25 filename: Coerced<String>,
26 options: Opt<Value<'js>>,
27 ) -> Result<Self> {
28 let mut last_modified = time::now_millis();
29
30 if let Some(ref opts) = options.0 {
31 if opts.is_bool() || opts.is_float() || opts.is_int() || opts.is_string() {
32 return Err(Exception::throw_type(&ctx, "Invalid options"));
33 }
34
35 if let Some(v) = opts.as_object() {
36 if let Some(x) = v.get::<_, Option<Coerced<i64>>>("lastModified")? {
37 last_modified = x.0;
38 }
39 }
40 }
41
42 let blob = Blob::from_parts(ctx, Opt(Some(data)), options)?;
43
44 Ok(Self {
45 blob,
46 filename: filename.0,
47 last_modified,
48 })
49 }
50
51 #[qjs(get)]
52 pub fn size(&self) -> usize {
53 self.blob.size()
54 }
55
56 #[qjs(get)]
57 pub fn name(&self) -> String {
58 self.filename.clone()
59 }
60
61 #[qjs(get, rename = "type")]
62 pub fn mime_type(&self) -> String {
63 self.blob.mime_type()
64 }
65
66 #[qjs(get, rename = "lastModified")]
67 pub fn last_modified(&self) -> i64 {
68 self.last_modified
69 }
70
71 pub fn slice(
72 &self,
73 ctx: Ctx<'js>,
74 start: Opt<isize>,
75 end: Opt<isize>,
76 content_type: Opt<Value<'js>>,
77 ) -> Result<Blob<'js>> {
78 self.blob.slice_blob(&ctx, start.0, end.0, content_type.0)
79 }
80
81 pub async fn text(&self) -> String {
82 self.blob.text().await
83 }
84
85 #[qjs(rename = "arrayBuffer")]
86 pub async fn array_buffer(&self, ctx: Ctx<'js>) -> Result<ArrayBuffer<'js>> {
87 self.blob.array_buffer(ctx).await
88 }
89
90 pub async fn bytes(&self, ctx: Ctx<'js>) -> Result<Value<'js>> {
91 self.blob.bytes(ctx).await
92 }
93
94 pub fn stream(&self, ctx: Ctx<'js>) -> Result<Value<'js>> {
95 self.blob.stream(ctx)
96 }
97
98 #[qjs(prop, rename = PredefinedAtom::SymbolToStringTag, configurable)]
99 pub fn to_string_tag() -> &'static str {
100 stringify!(File)
101 }
102}
103
104impl<'js> File<'js> {
105 pub fn from_bytes(
106 ctx: &Ctx<'js>,
107 data: Vec<u8>,
108 filename: String,
109 mime_type: Option<String>,
110 ) -> Result<Self> {
111 let blob = Blob::from_bytes(ctx, data, mime_type.clone())?;
117
118 Ok(Self {
119 blob,
120 filename,
121 last_modified: time::now_millis(),
122 })
123 }
124
125 pub fn get_blob(&self) -> Blob<'js> {
126 self.blob.clone()
127 }
128
129 pub fn set_filename(&mut self, filename: String) {
130 self.filename = filename;
131 }
132}