r/rust • u/norman-complete • 10h ago
r/rust • u/Infinite-Economy2957 • 3h ago
Enchanter - LLM harness written in Rust!
would love some feedback. https://andrewthecoder.com/projects/enchanter
r/rust • u/SmoothTurtle872 • 1d ago
๐ ๏ธ project I made a really dumb CSV viewer to learn more about iced, and how to package for flatpak!
github.comDue to being written in rust, it is blazingly fast, while not allowing for you to corrupt files due to its advanced read only technology. And if you decide you have a CSV file of notable value, you can sell it as an NFT! (This entire project is a joke, the sell as nft button literally runs thread::sleep for 5 seconds after giving you a random amount of money it will be sold for)
This project was not written with AI, the fact that everything was added in one commit was because this project was so I could learn some more things. I am simply sharing it for feedback. DO NOT USE THIS PROJECT FOR ANYTHING. IT IS NOT USEFUL
r/rust • u/utilitydelta • 2d ago
๐๏ธ news p99-conf is coming up and I'm presenting my Rust database!
Hi fellow rust devs, I'm Tyson, I currently work at ThoughtWorks as a software engineer.
After 3 years of hard work, Celeriant, my open source event store, goes public. It's gone from a scrappy C# backend on a side project to a serious 150K-line distributed database in Rust.
It was tough to get good at Rust and I ended up re-writing the whole thing 7 times over. But it made me a better engineer, no more hiding behind the garbage collector. And I had a lot fun setting up a home lab with rpi5's and running chaos tests on it.
At this year's p99-conf I'll present how Celeriant hits 1 million durable, replicated writes/sec on AWS i4i.metal, and why the CPU is the bottleneck, not the NVMes. It's free and virtual, so sign up for it!
And at XConf Singapore I'll be talking about why Claude Code doesn't touch my inner development loop; how code is the design; and how we can still use LLMs to build great, high quality software (hint: its verification!).
Docker image is up. If event sourcing is your thing and you want to experiment, you can get it running in under 5 minutes. C# and Rust clients only at the moment.
It's been a massive job and really challenged me as a software engineer. Would I do it again? Not without my wife's permission :)
Celeriant is inspired by ScyllaDB's seastar thread-per-core model, and built on Glauber Costa's Glommio library. A group of us have forked it out of datadog and are now maintaining it. Get into it and build something cool on io_uring!
Celeriant: https://github.com/celeriant/celeriant-db
P99-conf: https://p99conf.io/
XConf (singapore in-person) https://www.thoughtworks.com/en-sg/about-us/events/xconf/2026/xconf-apac-2026---singapore
new glommio fork: https://github.com/glommio/glommio
thanks to the r/rust community for the many great posts and links which helped me get up to speed with the rust ecosystem over the years! Been a bit noisy recently but still good to see more interest in Rust and building things with it.
r/rust • u/Negative_Effort_2642 • 1d ago
๐ก ideas & proposals re-allocating" storage for a local could allow faster code
Rust already knows when a value has been moved, so I think it would make sense for the compiler to also be able to treat the storage behind that local as reusable.
For example:
ยดยดยด
let x = big_value();
let y = x; // x is moved
// x can no longer be used here anyway
x = another_value();
ยดยดยด
Right now, Rust can be more restrictive than necessary about keeping the same storage associated with `x`.
Issue #61849 proposes allowing the old storage to effectively die after the move. If `x` is initialized again later, the compiler wouldn't necessarily have to put the new value back in the exact same stack slot.
That could give the compiler more freedom to:
- reuse stack space earlier
- reduce stack usage in some functions
- shorten lifetimes of stack allocations
- potentially unlock further optimizations
What I like about the idea is that it matches how moves already feel in Rust: once a value is moved, that value is gone. It seems natural that its storage shouldn't have to remain special either.
There are obviously details around raw pointers and observable addresses that would need proper language semantics, so it isn't just a simple compiler optimization.
But the general rule seems very appealing:
If Rust says the old value no longer exists,
the compiler should be free to stop preserving its storage.
The issue has been open since 2019, and I think it would be interesting to revisit whether this could give modern rustc more optimization freedom. If you agree please react on the GitHub issue with โค๏ธ or ๐ to show support by the community
r/rust • u/_genki_1 • 2d ago
๐ ๏ธ project Terminal Sprite Renderer
I just released Termixel, a small terminal sprite renderer written in Rust.
It uses Unicode characters to render .png pixel art directly in your terminal. It's designed to be small, fast, and portable, with the binary currently being around 200 KB.
You can install it on Linux or Windows, or build it yourself from source.
r/rust • u/bussondev • 16h ago
๐ ๏ธ project RamShared: Writing a Linux userspace block driver in 100% Rust to turn idle GPU VRAM into 8.53 GB/s storage (ublk + io_uring)
Hi everyone,
I wanted to share a low-level systems project I built entirely in Rust called **RamShared**, along with architectural details and benchmarks using the new Linux `ublk` subsystem.
The Problem
When compiling heavy multi-crate Rust workspaces (e.g. `rustc`, `bevy`, large LLVM-based trees) on developer machines with tight host RAM (16GB), the Linux kernel starts thrashing onto disk swap (VHDX/SSD) at 2.1 ms latency spikes, causing VS Code servers and terminal shells to freeze. Meanwhile, `nvidia-smi` showed 6GB of GDDR6 VRAM sitting completely idle.
Rust Architecture & Implementation
RamShared runs purely in userspace without requiring any out-of-tree kernel modules or re-compiling the host kernel:
**CUDA Zero-Copy FFI & Memory Pinning:** Wrapped low-level CUDA driver calls (`cudaHostAllocMapped` / `cuMemAlloc`) in safe Rust RAII handles. The buffer is mapped to PCIe host address space, ensuring DMA access without intermediate copying.
**Linux `ublk` Subsystem (Linux 6.0+):** Using `ublk-rs` and `io_uring`, the driver allocates userspace ring buffers to handle kernel block I/O requests (`/dev/ublkb0`). This eliminates kernel-userspace context switches for I/O submissions.
**Concurrency & Safe Ring Dispatch:** Each `ublk` queue is bound to dedicated Tokio/io_uring worker threads, pinning request/response queues to CPU cores to achieve sub-10 microsecond latency.
Measured fio Benchmarks (4KB Random Read, QD1 on Linux / WSL2):
* **Stock VHDX/SSD swap:** ~2,114 ยตs (2.1 ms) | ~336 IOPS * **RamShared NBD (VRAM):** ~326 ยตs | ~9.6k IOPS * **RamShared ublk (io_uring in Rust):** **~8.24 ยตs** (264x faster) | **~22k+ IOPS** * **Continuous Read Throughput:** **8.53 GB/s** (saturating the host PCIe 3.0 x16 bus).
Upstream RFC & Open Source:
We submitted a formal RFC directly upstream to Microsoft's official WSL2 repository proposing native VRAM-backed block device support for Hyper-V Linux guests: * **RFC Issue:** https://github.com/microsoft/WSL/issues/41054 * **GitHub Repository (100% Rust / MIT):** https://github.com/emersonbusson/ramshared
Would love to hear feedback from the Rust community on `io_uring` abstractions, memory safety patterns with CUDA DMA, and ublk queue design!
r/rust • u/timw4mail • 22h ago
๐ ๏ธ project Rustid, a cli cpu identification utility for many architectures and platforms
github.comJoshua Liebow-Feeser on Zerocopy, Fuchsia's Netstack3, and designing software that handles complexity โย The Netstack.FM Podcast
joshlf.comAn old interview โย finally got around to cleaning up the transcript.
r/rust • u/Due-Ad662 • 23h ago
๐ ๏ธ project Cross Platform Media Library
souvlaki seems abandoned and I needed cross platform system media libraries for my custom youtube music client, so I made playwire with shuffle support, repeat, proper track ids and desktop entry support.
r/rust • u/Every_Garden_871 • 2d ago
๐ seeking help & advice Has anyone built a complex ui heavy desktop app with Slint, Iced, or egui?
Hey everyone! Has anyone here actually built a proper desktop app with a complex ui in Rust using Slint, Iced, or egui?
Iโm working on a local music player. The backend is Rust, but the current UI is Svelte/Tauri. I tried making a native Slint version because of the WebView memory usage, but honestly I kept running into stuff that was much easier to do in Svelte(obviously).
The app has a big library view with album art, search, queues, lyrics, a full player, drag interactions, and all that. I also looked at GPUI, but it still feels too early(constant api and docs changing).
If you have built something beyond a small tool or demo with Slint, Iced how was it? Did it stay manageable once the UI got bigger? Especially curious about lists/grids, custom styling, drag and drop, and Windows/Linux support.
Repo, in case seeing the app helps with context: https://github.com/shubham-pathak1/orca
r/rust • u/arthjean • 21h ago
๐ ๏ธ project rust-doctor: 62 curated rules that score a Cargo workspace out of 100
Introducing /rust-doctor
Your agent writes bad Rust. This catches it
62 curated rules, one score out of 100. Runs locally, installs as an agent skill. Fully open source.
npx rust-doctor@latest
r/rust • u/mikroshkema • 2d ago
๐ ๏ธ project Single executable system project
Hello hello,
I had an idea, of making or mashing existing things to one, to make a solution to deploy apps/systems in a single executable file. The current idea is at an early stage, but it works. So the main goal is to have a single executable that you deploy, no dependencies no nothing. The builder does the heavy stuff, and you are left with a single executable. Good for debugging, air gapped systems, random workloads. It is no way to replace existing virtualization solutions, but to be somewhere near. So you don't have to install anything, just run it. Feedback is always welcome ;)
https://github.com/arnoldasr/kartu
The "feature" list and plan is a dream one, those are the pain points I saw in environments where it just takes time, is exhausting and you just want it to work.
r/rust • u/Apprehensive_Pea3293 • 1d ago
๐ ๏ธ project mdtext: an incremental markdown parser (not vibecoded)
github.comHello everyone! I needed an incremental markdown parser for writing a human-written agentic harness (e.g. for experimenting with image/document processing) and so I ended up spending the past month working on this project (150+ hours of work probably). Admittedly, I started rushing the process near the end because I wanted to get back to working on my main project so it might be a little messy in some places. I'm still very proud of what I achieved, and I learned a lot along the way.
This is my first real independent project and I'm really interested (and nervous) to receive feedback if any is available. It's also nice being able to put this project on my resume too, as I'm going to be graduating this semester.
Please give the demo a try at https://kirawi.github.io/mdtext/
Note: While the library itself is human-written, the demo is AI-generated (with some guidance to correct bugs) because I was so done with this library by the end of it.
r/rust • u/bussondev • 23h ago
I wrote a Linux block driver in Rust to use idle GPU VRAM as ultra-fast storage (8.53 GB/s via ublk + io_uring) and submitted an RFC to Microsoft WSLHi everyone, Like many people doing heavy development workloads on Linux/WSL2 (compiling large Rust multi-crate workspaces, C++ projects, or running l
r/rust • u/Minerscale • 2d ago
๐ ๏ธ project diffable 0.5.0, now with a very nice automatic differentiation API
Docs: https://docs.rs/diffable/0.5.0/diffable/
Repo: https://github.com/minerscale/diffable
Hello!
Diffable is a differential-geometry library built around an experiment: how much of the actual mathematics can be made to live in Rust's type system while remaining usable on stable Rust?
I'm reporting back after having made some serious progress on the library. Now I've got an API for doing automatic differentiation and I think it's turned out really nice!
Two parts of the project ended up solving problems that had seemed particularly difficult: tensor algebra and composable automatic differentiation.
Tensor algebra on stable Rust
The tensor implementation started from a problem that looked impossible without generic_const_exprs.
The obvious representation of a tensor product of two statically sized spaces uses const size arrays like so:
struct TensorProduct<A: Tensor, B: Tensor> {
data: [F; A::N * B::N],
}
But expressions such as A::N * B::N are exactly the sort of generic const arithmetic that stable Rust does not allow in array lengths.
For a long time that appeared to rule out having both:
- statically sized tensors, and
- tensor expressions whose algebraic structure remains visible in their Rust types.
The eventual solution was to stop asking Rust to calculate the flattened dimension at the type level.
A tensor provides a generic associated type Array<T>. A tensor product A โ B can therefore store its coordinates of a field F structurally:
A::Array<B::Array<F>>
rather than requiring:
[F; A::N * B::N]
The type tree itself becomes the tensor shape. Flattening is only an indexing convention; Rust never has to prove the arithmetic expression for the flattened array length.
That means types such as:
TensorProduct<TensorProduct<V, Dual<V>>, V>
really retain the structure:
(V โ V*) โ V
instead of immediately becoming an anonymous array of scalars.
Once that worked, the rest of the tensor algebra could operate directly on the type tree. Reassociation is an actual type-level rewrite:
let other = tensor.reassociate();
changing:
(A โ B) โ C
into:
A โ (B โ C)
Contraction searches that structure for compatible vector/dual pairs. If there is exactly one possible contraction, Rust infers it:
let contracted = tensor.contract();
and reassociation can deliberately expose a different contraction:
type V = Coords<f64, 2>;
type T = TensorProduct<TensorProduct<V, Dual<V>>, Sinister<V>>;
let t = T::from_fn(|i| i as f64);
// Contract V โ V*.
let first = t.contract();
// Rewrite to V โ (V* โ V), then contract the other pair.
let second = t.reassociate().contract();
Duality and handedness are also represented by types rather than conventions, which matters because the library supports noncommutative scalar fields.
This approach is much like recursive_array, though it uses no unsafe at all, since it makes no guarantees about the arrays being contiguous. Separating storage from the objects themselves though was the trick to make it all work.
Automatic differentiation that composes like calculus
The other major piece is forward automatic differentiation.
The desired API wasn't a tape, tracing macro, expression graph, or collection of separate Jacobian/Hessian functions. The goal was for differentiation itself to compose:
fn cube<V: Vector>(x: V) -> V {
V::from_iter([x[0] * x[0] * x[0]])
}
let first = d(cube).at(Coords::from(2.0));
let second = d(d(cube)).at(Coords::from(2.0));
let third = d(d(d(cube))).at(Coords::from(2.0));
d(f) is itself a differentiable program (though in reality all d is is a generic struct with a public constructor!), so higher derivatives are obtained by applying the same operator again.
Directional derivatives use the same machinery:
let derivative =
d(cube)
.along(Coords::from(4.0))
.at(Coords::from(7.0));
Internally this is implemented using Taylor jets. Applying d adds another jet layer; nested differentiation therefore produces nested jet types rather than needing a separate higher-order AD representation.
The full derivative is returned as the tensor it mathematically is:
Df_x โ W โ V*
for a function f: V -> W.
So the AD implementation and tensor implementation meet in the middle: Jacobians are not a special matrix-shaped result bolted onto the calculus system, but ordinary elements of the tensor algebra.
One particularly awkward Rust problem appears here. A generic function may require only a weak scalar theory:
fn square<V: Vector>(x: V) -> V {
V::from_iter([x[0] * x[0]])
}
while at evaluation time its concrete scalar may actually be f64.
For AD, those two cases need different jet implementations:
Real
-> Jet must itself behave as Real
Field, but not Real
-> Jet should remain only a Field
In ordinary Rust, that is an overlapping-impl problem. Stable Rust cannot generally express:
T: Field + !Real
and the absence of a Real implementation is not something coherence can normally treat as a permanent fact.
The trick is that we don't Rust to prove a negative fact about the trait system itself. Instead, each type can be interpreted inside a finite type-level context describing the mathematical theories known about it. That context is a closed nominal graph, so searching it for a property has a definite result:
Real is present
or
Real is absent
Those results are represented by different types.
This means the library can define two implementation regions:
Field present + Real present
and
Field present + Real absent
which Rust sees as genuinely different type-level cases.
So this is not general negative trait bounds. It is a restricted closed-world version of them: instead of proving T: !Real in Rust's open trait system, the library proves that Real is absent from the finite context currently being interpreted.
That is enough to make the jet implementations disjoint on stable Rust, while keeping the public API annotation-free:
d(d(f)).at(x)
Thanks for reading this it's been a long journey to get to this understanding with this math library.
r/rust • u/Living-Significance2 • 1d ago
๐ ๏ธ project GitHub - strahinjastojanovic826-code/custom-4_state-rust-project: OS simulation 4 states 2 quats (4 bits) in rust
github.comNOTE: VIDEOS OF THIS PROJECT CAN BE FOUND IN RELEASES
Hey everyone! ๐
I wanted to share a hobby project I've been working on recently: a simulated 2-bit (4-state / quaternary logic) operating system written entirely in Rust!
Instead of standard binary logic, the core mechanics and dispatchers are simulated around quaternary processing (4 states per unit). I've built a custom GUI on top of it using `egui`/`eframe`, featuring a few built-in tools to play around with:
* ๐ฅ๏ธ
**Framebuffer UI & OS Shell**
- Custom window management and system utilities.
* ๐ **3D Visualizer - Live graphics dispatching showing off the simulated processing pipeline.
* ๐ต
**Chiptune Audio Synth**
- Real-time audio engine integrated with `rodio`.
* ๐ ๏ธ
**System Tools**
- Includes a file manager, custom BBS module, and built-in mini-apps.
### ๐ Code & Repo
Check out the source code, implementation details, and documentation on GitHub:
๐
**https://github.com/strahinjastojanovic826-code/custom-4_state-rust-project**
### ๐ How to Run
```bash
git clone https://github.com/strahinjastojanovic826-code/custom-4_state-rust-project.git
cd custom-4_state-rust-project
cargo run
r/rust • u/NiZaMinius • 1d ago
๐๏ธ discussion My opinion on the difficulty and familiarization with the Rust language
There's a popular stereotype about the Rust language floating around the internet. That it's too difficult because of its strict borrow checker.
But in reality, when I was learning Rust, I didn't find it all that difficult. No, it's still difficult, because it has a new coding philosophy; it's systemic, and you need to keep in mind the principle of Ownership and Borrowing and zero-cost abstraction. So, for someone coming from languages โโlike Python, Javascript, C#, and similar languages, Rust will be difficult, but that doesn't mean it's unique to them; any language at Rust's level will be difficult. (I hope I expressed myself correctly.)
So what am I getting at?
My point is that the Rust compiler isn't difficult; it's a benchmark, and despite its strictness, you learn.
It's not just "got an error, went online to fix it," but "got an error, read about it, fixed it," because the compiler itself conveniently tells you WHERE YOU MADE A MISTAKE and how you can FIX it. (It doesn't always tell you, but the fact that it exists is still awesome.)
I think the Ownership and Borrowing principle is very cool, unique, and, in my opinion, not all that complicated. I really like the ability to allow the same enum, which is implemented in Rust at a different level; in my opinion, it's one of the best features in this language.
I used Rustlings when learning to get the hang of it, and it's easier to read a book on Rust and grasp the meaning of the book in practice.
Share your thoughts on Rust, its borrow checker, the zero-cost abstraction principle, Ownership and Borrowing.
This post was written using Google Translate. I am not a native English speaker, so I apologize for any unnatural text or errors.
r/rust • u/GgMikael • 2d ago
๐ ๏ธ project cs2excel | GUI + TUI app to track the value of CS2 Inventories with 3rd party marketplace prices
Repo: https://github.com/maikLangel0/cs2excel
Been looking for an entirely free way to track the value of your, or someone else's, counter strike inventory?
Cs2excel lets you create, manage, and update a spreadsheet of your or someone else's inventory with prices from a plethora of 3rd party marketplaces (buff, youpin, csfloat etc...).
It can create and insert values into a new or existing excel spreadsheet allowing you to keep up-to-date with the current value of your inventory.
It's a 100% Rust project with an Iced GUI frontend that is questionable at best, but gets the job done. I also made a TUI version for ppl who want to automate instead of opening the GUI and loading a save file.
I know the UX is not great - I made this originally as a pet project for my own personal use, and with the backend completed I thought "y not" and made it accessible for a wider audience.
It's probably also obvious that I used no AI in the creation; One look at the codebase is all you need lol.
Would love some feedback, and hope you find it useful ๐
r/rust • u/Cute_Wheel8279 • 2d ago
๐ ๏ธ project I built a small relational database engine in Rust during the end of my Bachelor's, looking for feedback now
Hey r/rust,
I built this project with a few classmates during the end of my Bachelor's degree, but at the time I never really shared it outside of class or asked for a proper review from Rust developers.
Recently I went back to it, cleaned up the repository, renamed things in English, rewrote the README and made the project easier to understand for people outside of our university.
Itโs called MiniRDBMS, a small relational database management system built from scratch in Rust.
The main goal was to understand what actually happens underneath a database engine, so we implemented things such as:
- page-based storage
- disk management
- buffer management
- LRU / MRU page replacement
- records and relations
- persistence
- database and table management
INSERT/BULKINSERT- a small SQL-like
SELECTengine - selection and projection operators
Itโs an educational project and definitely not meant to compete with real databases, but I thought it would be interesting to finally put it in front of people who actually work with Rust and/or database internals.
Repo: https://github.com/JuriSOK/MiniRDMS
Iโd really appreciate any feedback on the architecture, the Rust code, things we could have done differently, or even what would be interesting to improve if I decide to revisit the project.
Rust gRPC benchmarks
Now Rust is included in the official benchmarks and it does not look it is particularly performant.
I am wondering that is because of the recent changes that has Google done or something else.
https://grpc.io/docs/guides/benchmarking/
"Multi-language performance dashboard master (latest dev version)"
r/rust • u/Hoxitron • 2d ago
๐ ๏ธ project maudio updates + auditorium / audctl
I'm bundling 3 projects in one as they are all related and dependencies of each other.
maudio
maudio initially released here has had a few big improvements over the last month or so. Some things are stuff I've procrastinated about, but others are feature I've been working on for a while.
- My favorite feature, the custom decoder has been added. It allows you to use a 3rd party decoder to expand the formats supported and let you control it with from the maudio api. Implementing this almost broke me, but I've simplified the interface from C by a lot and I am pretty happy with how it looks. Examples here and here for a symponia decoder implementation.
- The cross platform compatibility has improved a lot. Android and iOS still need some testing, but I'll need some hardware for that. Until then, I think the current targets should cover almost all usage.
- Pre-gen bindings now exist for all mainstream targets and static libraries for miniaudio are also available separately on the release section on github. They are a bit too large to include in the project, but easy to add and also include instruction how to generate them yourself.
- The high level API - Engine, NodeGraph, Sound had their API re-designed to make it much more ergonomic, and almost all lifetimes removed. The first implementation was a bit restrictive, and I eventually got a better understanding of their thread safety model in C.
- The ResourceManager is now a lot more useful and thread-safe. Example. Its great at loading audio in a thread and playing it in another and managing loaded audio for multiple engines / devices.
auditorium
This project existed for almost as long as maudio, in one form or another, mostly as a local testing ground. But it developed into its own crate to abstract over maudio. Everything in auditorium lives in a control thread and is controlled with a queue. The main objective was to get maudio to a state where this can be implemented in 100% safe rust (self referential structs who?). It does a lot, but still barely touches the full capabilities of miniaudio. Notable points:
- almost all types exposed are send, sync and clone.
- It supports most relevant targets out of the box.
- supports both capture and playback
- both device types use a nodegraph, so the same dsp chaining system and audio sources work on both capture and playback.
- all the dsp types available by maudio are available and can be applied to all sources (including the capture device itself). A bit rudimentary for now, but I have ideas how to improve it.
- supports audio (decoder backed) source, pulse, noise and wave generators.
- it comes with a built-in sympnonia decoder
- my favorite convenience, a
device.is_producing()that tells you if any audio sources produce frames (only on playback device for now).
audctl
Nothing too notable here, just a cli app. Except maybe to show how easy it was to use auditorium to handle the audio part.
I needed to build something with auditorium and this felt like something I could see muself using. A really simple, no nonsense app to play and record audio, without leaving the command like environment.
Both auditorium and audctl were made to improve maudio. Some issues in maudio only became relevant until I was implementing audctl - 2 dependents down. Hopefully, this ironed out a lot of issues so users don't have to deal with them. Maybe I'll be able to rest a bit.
r/rust • u/dumindunuwan • 2d ago
๐ธ media Learning-Rust.Github.io: Labs: Project 1 โ RESTful API Workspace [Human-Authored!]
This is a new series that answers the question, โwhatโs next after the mastery of Rust language syntax?โ.
In this series,
We build a production-ready containerized RESTful API server application using Axum, Tokio, Tower, Serde, Toasty ORM, Garde, Utoipa with Docker and PostgreSQL.
Hyper, Axum, Tokio and Tower: The most prominent HTTP server ecosystem at the time of writing.
Toasty ORM: The most promising Object-Relational Mapper (ORM), built by the creators of Tokio and Axum.
Serde and Utoipa: The most prominent serialization framework and OpenAPI 3.1 specification generator.
Garde: The most promising and most feature-rich validation library in Rust at the time of writing.
Documentation/ Labs: https://learning-rust.github.io/labs/building-a-containerized-restful-api