Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a function to get the exact size of a PublicFile and PrivateFile #405

Merged
merged 5 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion wnfs-common/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{
de::{DeserializeOwned, Error as DeError},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{collections::BTreeMap, convert::TryInto, fmt::Display};
use std::{collections::BTreeMap, fmt::Display};

//--------------------------------------------------------------------------------------------------
// Type Definitions
Expand Down
2 changes: 0 additions & 2 deletions wnfs-common/src/storable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ macro_rules! impl_storable_from_serde {
};
}

pub use impl_storable_from_serde;

//--------------------------------------------------------------------------------------------------
// Type Definitions
//--------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion wnfs-hamt/src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ where
}

for Pair { key, value } in &other_values {
if main_map.get(key).is_none() {
if !main_map.contains_key(key) {
changes.push(KeyValueChange {
r#type: ChangeType::Remove,
key: key.clone(),
Expand Down
11 changes: 5 additions & 6 deletions wnfs-hamt/src/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ use wnfs_common::{
//--------------------------------------------------------------------------------------------------

/// Merges a node with another with the help of a resolver function.
pub async fn merge<K: CondSync, V: CondSync, H, F, B: BlockStore>(
pub async fn merge<K, V, H>(
main_link: Link<Arc<Node<K, V, H>>>,
other_link: Link<Arc<Node<K, V, H>>>,
f: F,
store: &B,
f: impl Fn(&V, &V) -> Result<V>,
store: &impl BlockStore,
) -> Result<Arc<Node<K, V, H>>>
where
F: Fn(&V, &V) -> Result<V>,
K: Storable + Eq + Clone + Hash + AsRef<[u8]>,
V: Storable + Eq + Clone,
K: Storable + Eq + Clone + CondSync + Hash + AsRef<[u8]>,
V: Storable + Eq + Clone + CondSync,
K::Serializable: Serialize + DeserializeOwned,
V::Serializable: Serialize + DeserializeOwned,
H: Hasher + CondSync,
Expand Down
5 changes: 3 additions & 2 deletions wnfs-hamt/src/strategies/kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ use wnfs_common::{
// Functions
//--------------------------------------------------------------------------------------------------

pub fn generate_kvs<K: Debug + Clone, V: Debug + Clone>(
pub fn generate_kvs<K, V>(
key: impl Strategy<Value = K>,
value: impl Strategy<Value = V>,
size: impl Into<SizeRange>,
) -> impl Strategy<Value = Vec<(K, V)>>
where
K: Eq + Hash,
K: Debug + Clone + Eq + Hash,
V: Debug + Clone,
{
vec((key, value), size).prop_map(|vec| {
vec.into_iter()
Expand Down
6 changes: 3 additions & 3 deletions wnfs-hamt/src/strategies/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ where
/// println!("{:?}", node);
/// }
/// ```
pub async fn node_from_operations<K: CondSync, V: CondSync>(
pub async fn node_from_operations<K, V>(
operations: &Operations<K, V>,
store: &impl BlockStore,
) -> Result<Arc<Node<K, V>>>
where
K: Storable + Clone + Debug + AsRef<[u8]>,
V: Storable + Clone + Debug,
K: Storable + Clone + Debug + CondSync + AsRef<[u8]>,
V: Storable + Clone + Debug + CondSync,
K::Serializable: Serialize + DeserializeOwned,
V::Serializable: Serialize + DeserializeOwned,
{
Expand Down
17 changes: 17 additions & 0 deletions wnfs-wasm/src/fs/private/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ impl PrivateFile {
self.read_at(value!(0).into(), None, forest, store)
}

/// Gets the exact content size without fetching all content blocks.
#[wasm_bindgen(js_name = "getSize")]
pub fn get_size(&self, forest: &PrivateForest, store: BlockStore) -> JsResult<Promise> {
let file = Rc::clone(&self.0);
let store = ForeignBlockStore(store);
let forest = Rc::clone(&forest.0);

Ok(future_to_promise(async move {
let size = file
.size(&forest, &store)
.await
.map_err(error("Cannot determine file size"))?;

Ok(value!(size as usize))
}))
}

/// Gets the metadata of this file.
pub fn metadata(&self) -> JsResult<JsValue> {
JsMetadata(self.0.get_metadata()).try_into()
Expand Down
16 changes: 16 additions & 0 deletions wnfs-wasm/src/fs/public/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,22 @@ impl PublicFile {
self.read_at(value!(0).into(), None, store)
}

/// Gets the exact content size without fetching all content blocks.
#[wasm_bindgen(js_name = "getSize")]
pub fn get_size(&self, store: BlockStore) -> JsResult<Promise> {
let file = Rc::clone(&self.0);
let store = ForeignBlockStore(store);

Ok(future_to_promise(async move {
let size = file
.size(&store)
.await
.map_err(error("Cannot determine file size"))?;

Ok(value!(size as usize))
}))
}

/// Gets the metadata of this file.
pub fn metadata(&self) -> JsResult<JsValue> {
JsMetadata(self.0.get_metadata()).try_into()
Expand Down
25 changes: 25 additions & 0 deletions wnfs-wasm/tests/private.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,31 @@ test.describe("PrivateFile", () => {
expect(new Uint8Array(Object.values(content))).toEqual(new Uint8Array([2, 3, 4]));
});

test("getSize returns the exact content size", async ({ page }) => {
const size = await page.evaluate(async () => {
const {
wnfs: { PrivateFile, PrivateForest },
mock: { MemoryBlockStore, Rng },
} = await window.setup();

const rng = new Rng();
const initialForest = new PrivateForest(rng);
const store = new MemoryBlockStore();
var [file, forest] = await PrivateFile.withContent(
initialForest.emptyName(),
new Date(),
new Uint8Array(2 * 1024 * 1024),
initialForest,
store,
rng,
);

return await file.getSize(forest, store);
});

expect(size).toEqual(2 * 1024 * 1024);
});

test("A PrivateDirectory has the correct metadata", async ({ page }) => {
const result = await page.evaluate(async () => {
const {
Expand Down
77 changes: 36 additions & 41 deletions wnfs-wasm/tests/public.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ test.describe("PublicDirectory", () => {
expect(result).toBeDefined();
});

test("lookupNode cannot fetch file not added to directory", async ({
page,
}) => {
test("lookupNode cannot fetch file not added to directory", async ({ page }) => {
const result = await page.evaluate(async () => {
const {
wnfs: { PublicDirectory },
Expand Down Expand Up @@ -65,18 +63,12 @@ test.describe("PublicDirectory", () => {
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

let result0 = await rootDir.getNode(
["pictures", "cats", "tabby.png"],
store
);
let result0 = await rootDir.getNode(["pictures", "cats", "tabby.png"], store);

let result1 = await rootDir.getNode(
["pictures", "dogs", "bingo.png"],
store
);
let result1 = await rootDir.getNode(["pictures", "dogs", "bingo.png"], store);

return [result0, result1];
});
Expand All @@ -102,7 +94,7 @@ test.describe("PublicDirectory", () => {
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

await rootDir.getNode(["pictures", "cats", "tabby.png"], store);
Expand Down Expand Up @@ -130,7 +122,7 @@ test.describe("PublicDirectory", () => {
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

const result = await rootDir.ls(["pictures"], store);
Expand Down Expand Up @@ -158,14 +150,14 @@ test.describe("PublicDirectory", () => {
["pictures", "dogs", "billie.jpeg"],
sampleCID,
time,
store
store,
);

var { rootDir } = await rootDir.write(
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

var { rootDir } = await rootDir.rm(["pictures", "cats"], store);
Expand All @@ -190,18 +182,13 @@ test.describe("PublicDirectory", () => {
const store = new MemoryBlockStore();
const root = new PublicDirectory(time);

var { rootDir } = await root.write(
["pictures", "cats", "luna.jpeg"],
sampleCID,
time,
store
);
var { rootDir } = await root.write(["pictures", "cats", "luna.jpeg"], sampleCID, time, store);

var { rootDir } = await rootDir.write(
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

var { rootDir } = await rootDir.mkdir(["images"], time, store);
Expand All @@ -210,7 +197,7 @@ test.describe("PublicDirectory", () => {
["pictures", "cats"],
["images", "cats"],
time,
store
store,
);

const imagesContent = await rootDir.ls(["images"], store);
Expand All @@ -236,28 +223,18 @@ test.describe("PublicDirectory", () => {
const store = new MemoryBlockStore();
const root = new PublicDirectory(time);

var { rootDir } = await root.write(
["pictures", "cats", "luna.jpeg"],
sampleCID,
time,
store
);
var { rootDir } = await root.write(["pictures", "cats", "luna.jpeg"], sampleCID, time, store);

var { rootDir } = await rootDir.write(
["pictures", "cats", "tabby.png"],
sampleCID,
time,
store
store,
);

var { rootDir } = await rootDir.mkdir(["images"], time, store);

var { rootDir } = await rootDir.cp(
["pictures", "cats"],
["images", "cats"],
time,
store
);
var { rootDir } = await rootDir.cp(["pictures", "cats"], ["images", "cats"], time, store);

const imagesContent = await rootDir.ls(["images"], store);

Expand Down Expand Up @@ -314,10 +291,7 @@ test.describe("PublicDirectory", () => {
const readBack = await file2.getContent(store);
const partialRead = await file2.readAt(7, 5, store);

return [
new TextDecoder().decode(readBack),
new TextDecoder().decode(partialRead)
];
return [new TextDecoder().decode(readBack), new TextDecoder().decode(partialRead)];
});

expect(result[0]).toEqual("Hello, World!");
Expand Down Expand Up @@ -370,4 +344,25 @@ test.describe("PublicDirectory", () => {
expect(result).not.toBeUndefined();
expect(result).toEqual("bafkr4ihkr4ld3m4gqkjf4reryxsy2s5tkbxprqkow6fin2iiyvreuzzab4");
});

test("A PublicFile has a content size", async ({ page }) => {
const result = await page.evaluate(async () => {
const {
wnfs: { PublicFile },
mock: { MemoryBlockStore },
} = await window.setup();

const store = new MemoryBlockStore();
const time = new Date();
const file = new PublicFile(time);

const longString = "x".repeat(5 * 1024 * 1024);
const content = new TextEncoder().encode(longString);
const file2 = await file.setContent(time, content, store);

return await file2.getSize(store);
});

expect(result).toEqual(5 * 1024 * 1024);
});
});
Loading
Loading