figshare-rs 0.1.1

Rust client for Figshare article workflows, public article lookup, and file uploads/downloads.
Documentation

figshare-rs

CI codecov crates.io docs.rs License

Async Rust client for core Figshare workflows.

It provides a typed API built around FigshareClient for public article reads, exact DOI lookup, latest-version resolution, private article updates, hosted uploads, publication, and public or private file downloads, with typed models, metadata and query builders, and higher-level workflow helpers. Use FigshareClient::anonymous for public reads and FIGSHARE_TOKEN for authenticated account workflows.

The shared cross-client traits from client-uploader-traits are re-exported as figshare_rs::client_uploader_traits. Import figshare_rs::client_uploader_traits::prelude::* when you want to write generic code against the aligned client-rs trait surface.

[!WARNING] For regular free figshare.com accounts, Figshare currently offers a 20GB total storage quota and a 20GB maximum individual file size, not 20GB per document: https://help.figshare.com/article/figshare-account-limits https://info.figshare.com/user-guide/file-size-limits-and-storage/

I created this crate thinking that the 20GB limit was per document rather than total account storage. If you are looking for a general-purpose personal archival workflow, I suggest using zenodo-rs instead.

This crate still exists because Figshare is used by institutions and publishers, and the API client can still be useful in those environments.

Examples

use figshare_rs::{
    ArticleOrder, ArticleQuery, Auth, DefinedType, Endpoint, FigshareClient, OrderDirection,
};

let client = FigshareClient::builder(Auth::anonymous())
    .endpoint(Endpoint::Custom("http://localhost:8080/v2/".parse()?))
    .build()?;
let query = ArticleQuery::builder()
    .item_type(DefinedType::Dataset)
    .order(ArticleOrder::PublishedDate)
    .order_direction(OrderDirection::Desc)
    .limit(3)
    .build();

assert_eq!(client.endpoint().base_url()?.as_str(), "http://localhost:8080/v2/");
assert_eq!(query.item_type, Some(DefinedType::Dataset));
assert_eq!(query.limit, Some(3));
assert_eq!(query.order, Some(ArticleOrder::PublishedDate));
# Ok::<(), Box<dyn std::error::Error>>(())

Build publication inputs locally:

use figshare_rs::{ArticleMetadata, DefinedType, UploadSource, UploadSpec};

let metadata = ArticleMetadata::builder()
    .title("Example dataset")
    .defined_type(DefinedType::Dataset)
    .description("Example upload from Rust")
    .author_named("Doe, Jane")
    .tag("example")
    .build()?;
let upload = UploadSpec::from_reader(
    "artifact.tar.gz",
    std::io::Cursor::new(vec![1_u8, 2, 3, 4]),
    4,
);

assert_eq!(metadata.title, "Example dataset");
assert_eq!(metadata.defined_type, DefinedType::Dataset);
assert_eq!(metadata.tags, vec!["example".to_owned()]);
match upload.source {
    UploadSource::Reader { content_length, .. } => assert_eq!(content_length, 4),
    UploadSource::Path(_) => unreachable!("expected reader-backed upload"),
}
# Ok::<(), figshare_rs::ArticleMetadataBuildError>(())