mirror of
https://github.com/Drop-OSS/droplet.git
synced 2025-11-12 15:52:47 +10:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe43f79062 | |||
| 30b9c4a1cc | |||
| 42f770aed9 |
@ -22,7 +22,7 @@ time-macros = "0.2.22"
|
||||
time = "0.3.41"
|
||||
webpki = "0.22.4"
|
||||
ring = "0.17.14"
|
||||
tokio = { version = "1.45.1", features = ["fs"] }
|
||||
tokio = { version = "1.45.1", features = ["fs", "io-util"] }
|
||||
tokio-util = { version = "0.7.15", features = ["codec"] }
|
||||
|
||||
[dependencies.x509-parser]
|
||||
|
||||
@ -28,11 +28,11 @@ test("read file", async (t) => {
|
||||
if (fs.existsSync(dirName)) fs.rmSync(dirName, { recursive: true });
|
||||
fs.mkdirSync(dirName, { recursive: true });
|
||||
|
||||
const testString = "g'day what's up my koala bros\n".repeat(10000);
|
||||
const testString = "g'day what's up my koala bros\n".repeat(1000);
|
||||
|
||||
fs.writeFileSync("./.test2/TESTFILE", testString);
|
||||
fs.writeFileSync(dirName + "/TESTFILE", testString);
|
||||
|
||||
const stream = droplet.readFile("./.test2", "TESTFILE");
|
||||
const stream = droplet.readFile(dirName, "TESTFILE");
|
||||
|
||||
let finalString = "";
|
||||
|
||||
@ -44,3 +44,28 @@ test("read file", async (t) => {
|
||||
t.assert(finalString == testString, "file strings don't match");
|
||||
fs.rmSync(dirName, { recursive: true });
|
||||
});
|
||||
|
||||
|
||||
test("read file offset", async (t) => {
|
||||
const dirName = "./.test3";
|
||||
if (fs.existsSync(dirName)) fs.rmSync(dirName, { recursive: true });
|
||||
fs.mkdirSync(dirName, { recursive: true });
|
||||
|
||||
const testString = "0123456789";
|
||||
|
||||
fs.writeFileSync(dirName + "/TESTFILE", testString);
|
||||
|
||||
const stream = droplet.readFile(dirName, "TESTFILE", 1, 4);
|
||||
|
||||
let finalString = "";
|
||||
|
||||
for await (const chunk of stream) {
|
||||
// Do something with each 'chunk'
|
||||
finalString += String.fromCharCode.apply(null, chunk);
|
||||
}
|
||||
|
||||
const expectedString = testString.slice(1, 5);
|
||||
|
||||
t.assert(finalString == expectedString, "file strings don't match");
|
||||
fs.rmSync(dirName, { recursive: true });
|
||||
});
|
||||
|
||||
2
index.d.ts
vendored
2
index.d.ts
vendored
@ -12,7 +12,7 @@ export declare function hasBackendForPath(path: string): boolean
|
||||
|
||||
export declare function listFiles(path: string): Array<string>
|
||||
|
||||
export declare function readFile(path: string, subPath: string): ReadableStream<Buffer> | null
|
||||
export declare function readFile(path: string, subPath: string, start?: number | undefined | null, end?: number | undefined | null): ReadableStream<Buffer> | null
|
||||
|
||||
export declare function signNonce(privateKey: string, nonce: string): string
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@drop-oss/droplet",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.1",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"napi": {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::{
|
||||
fs::{self, metadata, File},
|
||||
io::{self, BufReader, ErrorKind, Read},
|
||||
io::{self, BufReader, ErrorKind, Read, Seek},
|
||||
path::{Path, PathBuf},
|
||||
task::Poll,
|
||||
};
|
||||
@ -11,6 +11,7 @@ use napi::{
|
||||
bindgen_prelude::*,
|
||||
tokio_stream::{Stream, StreamExt},
|
||||
};
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeekExt, Take};
|
||||
use tokio_util::{
|
||||
bytes::BytesMut,
|
||||
codec::{BytesCodec, FramedRead},
|
||||
@ -134,6 +135,8 @@ pub fn read_file(
|
||||
path: String,
|
||||
sub_path: String,
|
||||
env: &Env,
|
||||
start: Option<u32>,
|
||||
end: Option<u32>
|
||||
) -> Option<ReadableStream<'static, BufferSlice<'static>>> {
|
||||
let path = Path::new(&path);
|
||||
let backend = create_backend_for_path(path).unwrap();
|
||||
@ -142,14 +145,27 @@ pub fn read_file(
|
||||
permission: 0, // Shouldn't matter
|
||||
};
|
||||
// Use `?` operator for cleaner error propagation from `Option`
|
||||
let reader = backend.reader(&version_file)?;
|
||||
let mut reader = backend.reader(&version_file)?;
|
||||
|
||||
// Can't do this in tokio because it requires a .await, which we can't do here
|
||||
if let Some(start) = start {
|
||||
reader.seek(io::SeekFrom::Start(start as u64)).unwrap();
|
||||
}
|
||||
|
||||
// Convert std::fs::File to tokio::fs::File for async operations
|
||||
let reader = tokio::fs::File::from_std(reader);
|
||||
|
||||
|
||||
let boxed_reader: Box<dyn AsyncRead + Send + Unpin> = match end {
|
||||
Some(end_val) => Box::new(reader.take(end_val as u64)),
|
||||
None => Box::new(reader),
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Create a FramedRead stream with BytesCodec for chunking
|
||||
|
||||
let stream = FramedRead::new(reader, BytesCodec::new())
|
||||
let stream = FramedRead::new(boxed_reader, BytesCodec::new())
|
||||
// Use StreamExt::map to transform each Result item
|
||||
.map(|result_item| {
|
||||
result_item
|
||||
|
||||
Reference in New Issue
Block a user