1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 07:14:47 -05:00

feat(unstable): add Deno.ftruncate and ftruncateSync (#6243)

This commit is contained in:
Casper Beyer 2020-06-20 21:46:10 +08:00 committed by GitHub
parent bdf2d26ba1
commit 86f92e04c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 139 additions and 0 deletions

View file

@ -12,6 +12,7 @@ export { applySourceMap, formatDiagnostics } from "./ops/errors.ts";
export { signal, signals, Signal, SignalStream } from "./signals.ts";
export { setRaw } from "./ops/tty.ts";
export { utimeSync, utime } from "./ops/fs/utime.ts";
export { ftruncateSync, ftruncate } from "./ops/fs/truncate.ts";
export { ShutdownMode, shutdown } from "./net.ts";
export { listen, listenDatagram, connect } from "./net_unstable.ts";
export { startTls } from "./tls.ts";

View file

@ -1248,4 +1248,43 @@ declare namespace Deno {
/** **UNSTABLE**: The URL of the file that was originally executed from the command-line. */
export const mainModule: string;
/** Synchronously truncates or extends the specified file stream, to reach the
* specified `len`. If `len` is not specified then the entire file contents
* are truncated.
*
* ```ts
* // truncate the entire file
* const file = Deno.open("my_file.txt", { read: true, write: true, truncate: true, create: true });
* Deno.ftruncateSync(file.rid);
*
* // truncate part of the file
* const file = Deno.open("my_file.txt", { read: true, write: true, create: true });
* Deno.write(file.rid, new TextEncoder().encode("Hello World"));
* Deno.ftruncateSync(file.rid, 7);
* const data = new Uint8Array(32);
* Deno.readSync(file.rid, data);
* console.log(new TextDecoder().decode(data)); // Hello W
* ```
*/
export function ftruncateSync(rid: number, len?: number): void;
/** Truncates or extends the specified file stream, to reach the specified `len`. If
* `len` is not specified then the entire file contents are truncated.
*
* ```ts
* // truncate the entire file
* const file = Deno.open("my_file.txt", { read: true, write: true, create: true });
* await Deno.ftruncate(file.rid);
*
* // truncate part of the file
* const file = Deno.open("my_file.txt", { read: true, write: true, create: true });
* await Deno.write(file.rid, new TextEncoder().encode("Hello World"));
* await Deno.ftruncate(file.rid, 7);
* const data = new Uint8Array(32);
* await Deno.read(file.rid, data);
* console.log(new TextDecoder().decode(data)); // Hello W
* ```
*/
export function ftruncate(rid: number, len?: number): Promise<void>;
}

View file

@ -13,6 +13,14 @@ function coerceLen(len?: number): number {
return len;
}
export function ftruncateSync(rid: number, len?: number): void {
sendSync("op_ftruncate", { rid, len: coerceLen(len) });
}
export async function ftruncate(rid: number, len?: number): Promise<void> {
await sendAsync("op_ftruncate", { rid, len: coerceLen(len) });
}
export function truncateSync(path: string, len?: number): void {
sendSync("op_truncate", { path, len: coerceLen(len) });
}

View file

@ -36,6 +36,7 @@ pub fn init(i: &mut CoreIsolate, s: &State) {
i.register_op("op_link", s.stateful_json_op(op_link));
i.register_op("op_symlink", s.stateful_json_op(op_symlink));
i.register_op("op_read_link", s.stateful_json_op(op_read_link));
i.register_op("op_ftruncate", s.stateful_json_op2(op_ftruncate));
i.register_op("op_truncate", s.stateful_json_op(op_truncate));
i.register_op("op_make_temp_dir", s.stateful_json_op(op_make_temp_dir));
i.register_op("op_make_temp_file", s.stateful_json_op(op_make_temp_file));
@ -783,6 +784,52 @@ fn op_read_link(
})
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FtruncateArgs {
promise_id: Option<u64>,
rid: i32,
len: i32,
}
fn op_ftruncate(
isolate_state: &mut CoreIsolateState,
state: &State,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<JsonOp, OpError> {
state.check_unstable("Deno.ftruncate");
let args: FtruncateArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let len = args.len as u64;
let resource_table = isolate_state.resource_table.clone();
let is_sync = args.promise_id.is_none();
if is_sync {
let mut resource_table = resource_table.borrow_mut();
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.set_len(len).map_err(OpError::from),
Err(_) => Err(OpError::type_error(
"cannot truncate this type of resource".to_string(),
)),
})?;
Ok(JsonOp::Sync(json!({})))
} else {
let fut = async move {
let mut resource_table = resource_table.borrow_mut();
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.set_len(len).map_err(OpError::from),
Err(_) => Err(OpError::type_error(
"cannot truncate this type of resource".to_string(),
)),
})?;
Ok(json!({}))
};
Ok(JsonOp::Async(fut.boxed_local()))
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct TruncateArgs {

View file

@ -1,6 +1,50 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { unitTest, assertEquals, assert } from "./test_util.ts";
unitTest(
{ perms: { read: true, write: true } },
function ftruncateSyncSuccess(): void {
const filename = Deno.makeTempDirSync() + "/test_ftruncateSync.txt";
const file = Deno.openSync(filename, {
create: true,
read: true,
write: true,
});
Deno.ftruncateSync(file.rid, 20);
assertEquals(Deno.readFileSync(filename).byteLength, 20);
Deno.ftruncateSync(file.rid, 5);
assertEquals(Deno.readFileSync(filename).byteLength, 5);
Deno.ftruncateSync(file.rid, -5);
assertEquals(Deno.readFileSync(filename).byteLength, 0);
Deno.close(file.rid);
Deno.removeSync(filename);
}
);
unitTest(
{ perms: { read: true, write: true } },
async function ftruncateSuccess(): Promise<void> {
const filename = Deno.makeTempDirSync() + "/test_ftruncate.txt";
const file = await Deno.open(filename, {
create: true,
read: true,
write: true,
});
await Deno.ftruncate(file.rid, 20);
assertEquals((await Deno.readFile(filename)).byteLength, 20);
await Deno.ftruncate(file.rid, 5);
assertEquals((await Deno.readFile(filename)).byteLength, 5);
await Deno.ftruncate(file.rid, -5);
assertEquals((await Deno.readFile(filename)).byteLength, 0);
Deno.close(file.rid);
await Deno.remove(filename);
}
);
unitTest(
{ perms: { read: true, write: true } },
function truncateSyncSuccess(): void {