List public items (public API) of Rust library crates. Enables diffing public API between releases.

Overview

cargo wrapper for this library

You probably want the cargo wrapper to this library. See https://github.com/Enselic/cargo-public-items.

public_items

List public items (the public API) of a Rust library crate by analyzing the rustdoc JSON of the crate.

Usage

Again, you probably want to use the convenient cargo public-items wrapper. But if you don't want to use the cargo wrapper, you do as follows:

# Install the tool that comes with this package
cargo install public_items

# Generate rustdoc JSON for your Rust library
RUSTDOCFLAGS='-Z unstable-options --output-format json' cargo +nightly doc --lib --no-deps

# List all items in the public API of the Rust library using the tool
public_items ./target/doc/your_library.json

Example

Using the tool on its own library:

% RUSTDOCFLAGS='-Z unstable-options --output-format json' cargo +nightly doc --lib --no-deps
% public_items ./target/doc/public_items.json
public_items
public_items::Error
public_items::Error::SerdeJsonError
public_items::Error::fmt
public_items::Error::from
public_items::Error::source
public_items::Result
public_items::from_rustdoc_json_str

Tip: By writing the public API to a file for two different versions of your library, you can diff your public API across versions.

Target audience

Maintainers of Rust libraries that want to keep track of changes to their public API.

Limitations

Currently:

  • The type of items are not shown. So a struct field and and struct method is listed as Struct::field and Struct::method. And tuple structs will just be represented with Struct::0, Struct::1, etc. Since Rust does not support method overloading, this is not that big of an issue in practice.
Comments
  • Created flat tokens as additional output

    Created flat tokens as additional output

    Here I created a flat simple token based output, this can be used for syntax colouring and better change diffs. In some cases the output is not very nice yet, especially generics. And sometimes the ID comes peeking out, in structs in enum variants. The code organisation/API is of course open for discussion.

    opened by douweschulte 11
  • Replace bat- and syntect-based tests with in-repo test crate

    Replace bat- and syntect-based tests with in-repo test crate

    And build rustdoc JSON inside of cargo test instead of using pre-built rustdoc JSON that we version in git. This has several advantages:

    • It becomes much easier to add regression tests since we have a test-crate we can add a public item to

    • The git repo becomes smaller since it is not filled with large amounts of raw rustdoc JSON.

    • We remove the need to be in possession of bat and syntect source code (to update the rustdoc JSON)

    • We improve code coverage of the library code by quite a bit in relevant files. See below:

    Code coverage sample before this commit:

    Filename                         Regions Covered
    --------------------------------------------------
    intermediate_public_item.rs      78.53%
    item_iterator.rs                 92.86%
    

    after this commit:

    Filename                         Regions Covered
    --------------------------------------------------
    intermediate_public_item.rs      84.29%
    item_iterator.rs                 94.29%
    

    The down-side is that we lose the benefit of testing against actual, non-trivial, real-world public APIs. But I think we can compensate for that.

    opened by Enselic 4
  • Move `public-api` code to `cargo-public-api` repo

    Move `public-api` code to `cargo-public-api` repo

    I have become more and more convinced that it would be beneficial to turn public-api and cargo-public-api into a mono-repo. Only on the repo level though. It still make a lot of sense for public-api and cargo-public-api to remain two distinct crates.

    So all code would live in https://github.com/Enselic/cargo-public-api. And long-term possibly in https://github.com/cargo-public-api/cargo-public-api.

    Pros

    Easier development flow

    There would only be a single project and git repo to manage in VS Code (or your IDE of choice).

    And the default setup can be that cargo-public-api uses the local version of public-api. Right now that is an extra step, which makes development slightly less convenient than it could be.

    Ability to re-use code for testing

    The public-api repo has a very useful comprehensive_api test crate, for example. cargo-public-api would get access to that crate too.

    Less duplicate efforts to make commits

    There are many examples in the past where I essentially make the same commit to both projects, but separately. It would have been a lot more convenient to only have to make a single commit. TODO: Add examples

    Easier to sync releases

    Whenever we make a public-api release, we practically always also want to make a cargo-public-api release. Because we want to set the public-api dependency of cargo-public-api to the latest version, to ensure that users gets the latest and greatest functionality.

    Having everything in the same repo makes it easier to sync releases.

    It is however very possible that we in the future want to make only cargo-public-api releases, without bumping public-api. But a mono-repo does not prevent us from doing that.

    Cons

    I can't really think of any big cons. Losing some github stars, maybe? The project is still in the very early stages, so I think we can tolerate that :) Of course; the public-api repo will point towards the cargo-public-api repo.

    Current status

    This is still an idea. Before a final decision, we at the very least need a prototype commit to see how a mono-repo would look like. That is the next step for me.

    @douweschulte Naturally, I would also love your feedback on this. (But as usual, there is no stress or urgency. I think this will be the last time I explicitly mention that :)

    opened by Enselic 2
  • Gracefully handle `ErrorKind::BrokenPipe` (`public-api ... | head -n 1`)

    Gracefully handle `ErrorKind::BrokenPipe` (`public-api ... | head -n 1`)

    So that we don't get an error when doing something like this:

    % RUSTDOCFLAGS='-Z unstable-options --output-format json' cargo +nightly doc  --manifest-path tests/crates/comprehensive_api/Cargo.toml --lib --no-deps
    % ./target/debug/public-api tests/crates/comprehensive_api/target/doc/comprehensive_api.json | head -n 1
    pub async fn comprehensive_api::functions::async_fn() -> impl Future<Output = ()>
    Error: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }
    
    opened by Enselic 2
  • Higher-Rank Trait Bounds (HRTB) not properly rendered

    Higher-Rank Trait Bounds (HRTB) not properly rendered

    Comparing the rustdoc HTML output of https://github.com/rust-lang/rust/blob/master/src/test/rustdoc/higher-ranked-trait-bounds.rs with the output of public-api, there are differences. To see them, first generate rustdoc HTML output for that file:

    % ~/.rustup/toolchains/nightly-2022-03-31-aarch64-apple-darwin/bin/rustdoc ~/src/rust/src/test/rustdoc/higher-ranked-trait-bounds.rs -Z unstable-options --output-format html -o /tmp/hrtb
    

    and then look at e.g. open /tmp/hrtb/foo/fn.test3.html which looks like this:

    pub fn test3<F>() 
    where
        F: for<'a, 'b> Fn(&'a u8, &'b u8), 
    

    and then generate output with public-api:

    % ~/.rustup/toolchains/nightly-2022-03-31-aarch64-apple-darwin/bin/rustdoc ~/src/rust/src/test/rustdoc/higher-ranked-trait-bounds.rs -Z unstable-options --output-format json -o /tmp/hrtb
    % public-api /tmp/hrtb/foo.json 
    pub fn foo::Foo::bar<T>() where T: Trait<'a>
    pub fn foo::test1<T>() where &'a T: Iterator
    pub fn foo::test2<T>() where &'a T: Trait<'b>
    pub fn foo::test3<F>() where F: Fn(&'a u8, &'b u8)<'a, 'b>
    pub mod foo
    pub struct field foo::Bar::bar: &'a Trait<'b> + Unpin
    pub struct field foo::Bar::baz: &'a Unpin + Trait<'b><'b>
    pub struct field foo::Foo::some_func: fn(&'c i32) -> i32
    pub struct field foo::Foo::some_trait: &'a Trait<'b>
    pub struct foo::Bar<'a>
    pub struct foo::Foo<'a>
    pub trait foo::B<'x>
    pub trait foo::Trait<'x>
    

    Normalizing whitespace and linewlines and aligning, we have this vs that:

    pub fn      test3<F>() where F: for<'a, 'b> Fn(&'a u8, &'b u8), 
    pub fn foo::test3<F>() where F:             Fn(&'a u8, &'b u8)<'a, 'b>
    

    There is a FIXME related to HRTB in rust-lang/rust/src/librustdoc/json/conversions.rs, so not sure we can fix them all, but it looks like we can fix the particular example I brought up.

    For reference HRTB, didn't work properly in rustdoc HTML either for quite a while (see https://github.com/rust-lang/rust/issues/78482), but was fixed quite recently, which also added the FIXME (see https://github.com/rust-lang/rust/pull/84814).

    To fix HRTBs in rustdoc HTML, the DynTrait object was introduced in the above PR. So fixing all HRTB problems might be related to fixing https://github.com/Enselic/cargo-public-api/issues/40, in case it requires upstream changes.

    limitation waiting-on-upstream 
    opened by Enselic 2
  • Rename project to `public-api`

    Rename project to `public-api`

    See discussion in https://github.com/Enselic/cargo-public-items/issues/17

    But let's wait with renaming public_items until at least https://github.com/Enselic/public_items/pull/53 has been merged, because otherwise there will be massive amounts of merge conflicts

    opened by Enselic 2
  • `const fn`s missing `const`

    `const fn`s missing `const`

    Should be pretty easy to add because the JSON for a function has the necessary info:

                    "header": {
                        "const": false,
                        "unsafe": false,
                        "async": true,
                        "abi": "Rust"
                    }
    
    limitation 
    opened by Enselic 2
  • Remove TokenStream to simplify API and implementation

    Remove TokenStream to simplify API and implementation

    I am a big fan of keeping things as simple as possible. This makes it easier for others to use and contribute to this library.

    One thing that IMHO would simplify things is to remove TokenStream from both the public API and the implementation. This significantly simplifies the API, without making the implementation more unergonomic to work with. It arguably becomes easier to work with since everyone knows how to work with Vecs.

    I also took this opportunity to hide PublicItem::tokens behind a getter, to make the API more future-proof.

    Here is how this commit impacts the public API:

    % cargo public-api --diff-git-checkouts origin/main remove-tokenstream
    Removed items from the public API
    =================================
    -pub fn public_api::tokens::TokenStream::clone(&self) -> TokenStream
    -pub fn public_api::tokens::TokenStream::cmp(&self, other: &TokenStream) -> $crate::cmp::Ordering
    -pub fn public_api::tokens::TokenStream::default() -> TokenStream
    -pub fn public_api::tokens::TokenStream::eq(&self, other: &TokenStream) -> bool
    -pub fn public_api::tokens::TokenStream::extend(&mut self, tokens: impl Into<Self>)
    -pub fn public_api::tokens::TokenStream::fmt(&self, f: &mut $crate::fmt::Formatter<'_>) -> $crate::fmt::Result
    -pub fn public_api::tokens::TokenStream::fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
    -pub fn public_api::tokens::TokenStream::from(token: Token) -> Self
    -pub fn public_api::tokens::TokenStream::from(tokens: &[Token]) -> Self
    -pub fn public_api::tokens::TokenStream::from(tokens: Vec<Token>) -> Self
    -pub fn public_api::tokens::TokenStream::is_empty(&self) -> bool
    -pub fn public_api::tokens::TokenStream::len(&self) -> usize
    -pub fn public_api::tokens::TokenStream::ne(&self, other: &TokenStream) -> bool
    -pub fn public_api::tokens::TokenStream::partial_cmp(&self, other: &TokenStream) -> $crate::option::Option<$crate::cmp::Ordering>
    -pub fn public_api::tokens::TokenStream::tokens(&self) -> impl Iterator<Item = &Token> + '_
    -pub fn public_api::tokens::TokenStream::tokens_len(&self) -> usize
    -pub struct field public_api::PublicItem::tokens: TokenStream
    -pub struct field public_api::tokens::TokenStream::tokens: Vec<Token>
    -pub struct public_api::tokens::TokenStream
    
    Changed items in the public API
    ===============================
    (none)
    
    Added items to the public API
    =============================
    +pub fn public_api::PublicItem::tokens(&self) -> impl Iterator<Item = &Token>
    

    Here is how this impacts cargo-public-api: https://github.com/Enselic/cargo-public-api/pull/27

    opened by Enselic 1
  • `#[proc_macro_attribute]` not displayed as `#[name]`

    `#[proc_macro_attribute]` not displayed as `#[name]`

    Step-by-step

    1. cargo doc --manifest-path ./tests/crates/comprehensive_api_proc_macro/Cargo.toml && open ./target/doc/comprehensive_api_proc_macro/attr.simple_proc_macro_attribute.html
    2. Notice that the item is represented as #[simple_proc_macro_attribute]
    3. Look in ./tests/expected_output/comprehensive_api_proc_macro.txt

    Expected

    There is a line

    pub proc macro comprehensive_api_proc_macro::#[simple_proc_macro_attribute]
    

    Actual

    There is a line

    pub proc macro comprehensive_api_proc_macro::simple_proc_macro_attribute!
    

    because that is how the library represents that item. We should represent it the same as cargo doc.

    limitation 
    opened by Enselic 1
  • Support GATs (Generic Associated Types)

    Support GATs (Generic Associated Types)

    See https://github.com/aDotInTheVoid/rustdoc-types/issues/6

    It is beneficial to wait with bumping rustdoc-types to v0.8.0 until we implement support for GATs (or until we need to bump for other reasons), because a reader based on rustdoc-types v0.7.0 can still read output produced by rustdoc-types v0.8.0 (nightly-2022-03-04 and onwards), since the only difference is the addition of JSON fields.

    It might also make sense to wait with supporting this until GAT lands in stable.

    enhancement waiting-on-stable 
    opened by Enselic 1
  • Allow to omit blanket implementations

    Allow to omit blanket implementations

    It should be possible to opt-in to omit blanket implementations. It is usually not interesting be shown e.g. the below items for every struct in a crate:

    pub fn public_items::PublicItem::borrow(&self) -> &T
    pub fn public_items::PublicItem::borrow_mut(&mut self) -> &mut T
    pub fn public_items::PublicItem::from(t: T) -> T
    pub fn public_items::PublicItem::into(self) -> U
    pub fn public_items::PublicItem::try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
    pub fn public_items::PublicItem::try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
    pub fn public_items::PublicItem::type_id(&self) -> TypeId
    

    Seems like we can use Impl::blanket_impl to know if an impl is a blanket impl.

    opened by Enselic 1
Releases(v0.11.0)
  • v0.11.0(May 22, 2022)

    What's Changed

    • Cargo.toml: Make it easier to use a local version of rustdoc-types by @Enselic in https://github.com/Enselic/public-api/pull/89
    • Properly render HRTBs for GenericBound::TraitBound by @Enselic in https://github.com/Enselic/public-api/pull/90
    • Properly render HRTBs for FunctionPointer by @Enselic in https://github.com/Enselic/public-api/pull/91
    • CI.yml: Instead of -D, use --deny for clarity by @Enselic in https://github.com/Enselic/public-api/pull/93
    • Gracefully handle ErrorKind::BrokenPipe (public-api ... | head -n 1) by @Enselic in https://github.com/Enselic/public-api/pull/94
    • Render HRTBs for WherePredicate::BoundPredicate by @Enselic in https://github.com/Enselic/public-api/pull/92

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.10.2...v0.11.0

    Source code(tar.gz)
    Source code(zip)
  • v0.10.2(Apr 26, 2022)

    What's Changed

    • CI/CD: Fix GitHub Releases being named v"0.10.1" by @Enselic in https://github.com/Enselic/public-api/pull/86
    • CI.yml: Indent steps to follow canonical style by @Enselic in https://github.com/Enselic/public-api/pull/87

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.10.1...v0.10.2

    Source code(tar.gz)
    Source code(zip)
  • v0.10.1(Apr 26, 2022)

    What's Changed

    • CI/CD: Create GitHub Releases with auto-generated release notes by @Enselic in https://github.com/Enselic/public-api/pull/85

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.10.0...v0.10.1

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Apr 26, 2022)

    What's Changed

    • Remove TokenStream to simplify API and implementation by @Enselic in https://github.com/Enselic/public-api/pull/81
    • Add infrastructure to allow dry-running making a release by @Enselic in https://github.com/Enselic/public-api/pull/82

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.9.3...v0.10.0

    Source code(tar.gz)
    Source code(zip)
  • v0.9.3(Apr 26, 2022)

    What's Changed

    • Support const fn by @Enselic in https://github.com/Enselic/public-api/pull/79
    • CI: Ensure Cargo.lock is up to date by using --locked by @Enselic in https://github.com/Enselic/public-api/pull/80

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.9.2...v0.9.3

    Source code(tar.gz)
    Source code(zip)
  • v0.9.2(Apr 26, 2022)

    What's Changed

    • render_path(): Make Token::Type part of the path by @Enselic in https://github.com/Enselic/public-api/pull/78

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.9.1...v0.9.2

    Source code(tar.gz)
    Source code(zip)
  • v0.9.1(Apr 26, 2022)

    What's Changed

    • render: Add helpers for symbols by @Enselic in https://github.com/Enselic/public-api/pull/72
    • render_generic_param_def(): Use proper token for name by @Enselic in https://github.com/Enselic/public-api/pull/73
    • comprehensive_api: Add more cases like async and unsafe fns by @Enselic in https://github.com/Enselic/public-api/pull/74
    • Render function pointers by @Enselic in https://github.com/Enselic/public-api/pull/75
    • CI: Remove code coverage by @Enselic in https://github.com/Enselic/public-api/pull/76
    • doc/development.md: Give code coverage tips by @Enselic in https://github.com/Enselic/public-api/pull/77

    Full Changelog: https://github.com/Enselic/public-api/compare/v0.9.0...v0.9.1

    Source code(tar.gz)
    Source code(zip)
Owner
Martin Nordholts
Co-maintaining and improving bat. A cat(1) clone with syntax highlighting and more.
Martin Nordholts
The api for interacting with `libinput_macros.nro`, along with the releases of the plugin.

Input Macros Plugin and API This plugin and related API implements a mechanism of assigning a complex series of button inputs and stick positions to a

null 5 Aug 24, 2023
Derive conversion traits when items are structurally similar.

structural-convert Derive conversion traits when items are structurally similar. Inspired by serde and struct-convert crates. Features One to one fiel

Julius Lungys 3 Feb 22, 2024
Rust lib for fetching official protoc (Protocol Buffer compiler) releases

protoc-fetcher Rust library for fetching official Protocol Buffer compiler (protoc) releases, pegged to a specific version. protoc-fetcher downloads a

Arcanyx Technical Wizardry LLC 2 Sep 5, 2022
A library for transcoding between bytes in Astro Notation Format and Native Rust data types.

Rust Astro Notation A library for transcoding between hexadecimal strings in Astro Notation Format and Native Rust data types. Usage In your Cargo.tom

Stelar Software 1 Feb 4, 2022
The Fast Vector Similarity Library is designed to provide efficient computation of various similarity measures between vectors.

Fast Vector Similarity Library Introduction The Fast Vector Similarity Library is designed to provide efficient computation of various similarity meas

Jeff Emanuel 243 Sep 6, 2023
UNIC: Unicode and Internationalization Crates for Rust

UNIC: Unicode and Internationalization Crates for Rust https://github.com/open-i18n/rust-unic UNIC is a project to develop components for the Rust pro

open-i18n — Open Internationalization Initiative 219 Nov 12, 2022
Rust crates with map and set with interval keys (ranges x..y).

This crates implements map and set with interval keys (ranges x..y). IntervalMap is implemented using red-black binary tree, where each node contains

Timofey Prodanov 8 Aug 23, 2022
Game development practices with Rust programming language. I want to use different crates for this.

Hazır Oyun Motorlarını Kullanarak Rust Dili Yardımıyla Oyunlar Geliştirmek Rust programlama dilinde oyun geliştirmek için popüler birkaç hazır çatıyı

Burak Selim Senyurt 16 Dec 27, 2022
A collection of crates to make minecraft development (client, server) with rust possible.

rust-craft rust-craft is a collection of crates to make minecraft development (client, server) with rust possible. Motivation There's no better way of

João Victor 15 Mar 23, 2023
Public aircraft & flightroute api Built in Rust for Docker, using PostgreSQL & Redis

api.adsbdb.com public aircraft & flightroute api Built in Rust for Docker, using PostgreSQL & Redis See typescript branch for original typescript vers

Jack Wills 66 Dec 22, 2022
A procedural macro for configuring constant values across crates

toml-cfg Rough ideas: Crates can declare variables that can be overridden Anything const, e.g. usize, strings, etc. (Only) The "root crate" can overri

James Munns 43 Dec 24, 2022
A community curated list of Rust Language streamers

Awesome Rust Streaming This is a community curated list of livestreams about the programming language Rust. Don't see a stream that you like? Feel fre

James Munns 587 Dec 26, 2022
List of Rust books

Rust Books Books Starter Books Advanced Books Resources Books Starter Books The Rust Programming Language Free Welcome! This book will teach you about

Spiros Gerokostas 2.2k Jan 9, 2023
A curated list of Rust code and resources.

Awesome Rust A curated list of Rust code and resources. If you want to contribute, please read this. Table of contents Applications Audio and Music Cr

null 31.2k Dec 30, 2022
Portable linked-list allocator designed for baremetal systems

Palloc Portable linked-list allocator for embedded / baremetal systems. Using the crate Include this in the [dependencies] section of Cargo.toml pallo

Pietro 3 Jan 11, 2022
A simple programming language for something between C and Rust.

inuc inuc is a systems programming language that is something between C and Rust. Features : [] Strong , static typing (type inference not a priority

Sagnik Chatterjee 1 Feb 7, 2022
A fast rendezvous in rust where data can optionally be swapped between the two threads.

rendezvous_swap A rendezvous is an execution barrier between a pair of threads, but this crate also provides the option of swapping data at the synchr

Erik 5 Mar 17, 2023
memchr vs stringzilla - up to 7x throughput difference between two SIMD-accelerated substring search libraries in Rust

memchr vs stringzilla Rust Substring Search Benchmarks Substring search is one of the most common operations in text processing, and one of the slowes

Ash Vardanian 38 Mar 5, 2024
Converts between country names, ISO 3166-1 codes and flag emojis.

country-emoji Converts between country names, ISO 3166-1 codes and flag emojis. Usage use country_emoji::{flag, code, name, countries}; flag("CL") /

Leo Dutra 4 Oct 25, 2022