Skip to content
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
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [LambdaBuffers to Haskell](haskell.md)
- [LambdaBuffers to Purescript](purescript.md)
- [LambdaBuffers for Plutarch](plutarch.md)
- [LambdaBuffers for Rust](rust.md)
- [Design](design.md)
- [API](api.md)
- [LambdaBuffers Frontend (.lbf) syntax](syntax.md)
Expand Down
5 changes: 5 additions & 0 deletions docs/examples/lb-pkgs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"crate": [
"Document"
]
}
123 changes: 123 additions & 0 deletions docs/rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# LambdaBuffers to Rust

Let's take a look at how LambdaBuffers modules map into Rust modules and how
LambdaBuffers type definitions map into Rust type definitions.

We'll use the `lbf-prelude-to-rust` CLI tool which is just a convenient wrapper over
the raw `lbf` CLI. We can get this tool by either loading the LambdaBuffers Nix
environment that comes packaged with all the CLI tools:

```shell
$ nix develop github:mlabs-haskell/lambda-buffers#lb
$ lbf<tab>
lbf lbf-plutus-to-purescript lbf-prelude-to-haskell lbf-prelude-to-rust
lbf-plutus-to-haskell lbf-plutus-to-rust lbf-prelude-to-purescript
```

Or we can simply just refer directly to the `lbf-prelude-to-rust` CLI by `nix run
github:mlabs-haskell/lambda-buffers#lbf-prelude-to-rust`.

In this chapter, we're going to use the latter option.

Let's now use `lbf-prelude-to-rust` to process the [Document.lbf](https://github.com/mlabs-haskell/lambda-buffers/tree/main/docs/examples/Document.lbf) schema.

```purescript
module Document

-- Importing types
import Prelude (Text, List, Set, Bytes)

-- Author
sum Author = Ivan | Jovan | Savo

-- Reviewer
sum Reviewer = Bob | Alice

-- Document
record Document a = {
author : Author,
reviewers : Set Reviewer,
content : Chapter a
}

-- Chapter
record Chapter a = {
content : a,
subChapters : List (Chapter a)
}

-- Some actual content
sum RichContent = Image Bytes | Gif Bytes | Text Text

-- Rich document
prod RichDocument = (Document RichContent)
```

```shell
$ nix run github:mlabs-haskell/lambda-buffers#lbf-prelude-to-rust -- Document.lbf
$ find autogen/
autogen/
autogen/LambdaBuffers
autogen/LambdaBuffers/Document.hs
autogen/build.json
```

As we can see the `autogen` directory has been created that contains the generated Rust modules.
Note the `autogen/build.json` file as it contains all the necessary Cargo dependencies the generated module needs in order to be properly compiled by Rust.

The outputted Rust module in `autogen/document.rs`:

```rust
#![no_implicit_prelude]
#![allow(warnings)]
extern crate lbf_prelude;
extern crate std;


#[derive(std::fmt::Debug, std::clone::Clone)]
pub enum Author{Ivan, Jovan, Savo}

#[derive(std::fmt::Debug, std::clone::Clone)]
pub struct Chapter<A>{pub content: A,
pub sub_chapters: std::boxed::Box<lbf_prelude::prelude::List<Chapter<A>>>}

#[derive(std::fmt::Debug, std::clone::Clone)]
pub struct Document<A>{pub author: Author,
pub reviewers: lbf_prelude::prelude::Set<Reviewer>,
pub content: Chapter<A>}

#[derive(std::fmt::Debug, std::clone::Clone)]
pub enum Reviewer{Bob, Alice}

#[derive(std::fmt::Debug, std::clone::Clone)]
pub enum RichContent{Image(lbf_prelude::prelude::Bytes),
Gif(lbf_prelude::prelude::Bytes),
Text(lbf_prelude::prelude::Text)}

#[derive(std::fmt::Debug, std::clone::Clone)]
pub struct RichDocument(pub Document<RichContent>);

```

## Sum types

The types `Author`, `Reviewer`, and `RichContent` have been declared as sum types in the LambdaBuffers schema using the `sum` keyword.

As we can see, nothing too surprising here, all the `sum` types become `enum`
in Rust.

## Product types

The type `RichDocument` have been declared as a product type in the
LambdaBuffers schema using the `prod` keyword.

They become Rust tuple `struct` (or named tuple)

## Record types

The types `Document` and `Chapter` have been declared as record types in the
LambdaBuffers schema using the `record` keyword.

Like with product types, they become Rust `struct` with named fields.

All types and their fields are public, allowing to manipulate them without accessors.
5 changes: 4 additions & 1 deletion lambda-buffers-frontend/build.nix
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@
gen = "${config.packages.lbg-rust}/bin/lbg-rust";
gen-classes = ["Prelude.Eq" "Prelude.Json"];
gen-dir = "autogen";
gen-opts = ["--config=${config.packages.codegen-configs}/rust-prelude-base.json"];
gen-opts = [
"--packages lb-pkgs.json"
"--config=${config.packages.codegen-configs}/rust-prelude-base.json"];
work-dir = ".work";
}} "$@";
'';
Expand All @@ -211,6 +213,7 @@
gen-classes = ["Prelude.Eq" "Prelude.Json" "Plutus.V1.PlutusData" ];
gen-dir = "autogen";
gen-opts = [
"--packages lb-pkgs.json"
"--config=${config.packages.codegen-configs}/rust-prelude-base.json"
"--config=${config.packages.codegen-configs}/rust-plutus-pla.json"
];
Expand Down