Skip to content

Commit

Permalink
Merge pull request #111 from NLnetLabs/modules
Browse files Browse the repository at this point in the history
Modules
  • Loading branch information
tertsdiepraam authored Feb 27, 2025
2 parents 34717c3 + 2c7ad3c commit 0edcec3
Show file tree
Hide file tree
Showing 46 changed files with 3,648 additions and 2,046 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
rust: [1.80.0, stable, beta, nightly]
rust: [1.81.0, stable, beta, nightly]

# Test with no features, default features ("") and all features.
# Ordered fewest features to most features.
Expand Down
17 changes: 8 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ categories.workspace = true
[dependencies]
ariadne = "0.5.0"
clap = { version = "4.4.6", features = ["derive"] }
env_logger = "0.10"
log = "0.4"
logos = "0.14.0"
env_logger = "0.11"
icu = { version = "1.5.0", features = ["compiled_data"] }
inetnum = "0.1.0"
symbol_table = { version = "0.3.0", features = ["global"] }
string-interner = "0.17.0"
roto-macros = { workspace = true, version = "0.4.0" }
log = "0.4"
roto-macros = { workspace = true }
symbol_table = { version = "0.4.0", features = ["global"] }

[dependencies.cranelift]
version = "0.113.0"
Expand All @@ -38,7 +37,7 @@ rev = "1af294ea2d6c18c5a8fa9b4f272398b7c98e0c48"
[dev-dependencies]
bytes = "1"
routecore = { version = "0.5", features = ["bgp", "bmp", "serde"] }
tabled = { version = "0.17.0", default-features = false, features = ["std"] }
tabled = { version = "0.18.0", default-features = false, features = ["std"] }

[profile.profiling]
inherits = "release"
Expand All @@ -54,7 +53,7 @@ version = "0.4.1-dev"
edition = "2021"
authors = ["NLnet Labs <[email protected]>"]
license = "BSD-3-Clause"
rust-version = "1.80"
rust-version = "1.81"
description = "strongly-typed, compiled language for Rotonda"
documentation = "https://docs.rs/roto/"
repository = "https://github.com/NLnetLabs/roto/"
Expand All @@ -64,7 +63,7 @@ categories = ["network-programming"]
readme = "README.md"

[workspace.dependencies]
roto-macros = { path = "macros", version = "0.4.0" }
roto-macros = { path = "macros", version = "0.4.1-dev" }
proc-macro2 = "1.0.86"
quote = "1.0.37"
syn = { version = "2.0.77", features = ["full"] }
7 changes: 7 additions & 0 deletions examples/addr_range.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
filtermap within_range(range: AddrRange, ip: IpAddr) {
if range.contains(ip) && ip.is_ipv4() {
accept ip
} else {
reject
}
}
49 changes: 49 additions & 0 deletions examples/addr_range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::{net::IpAddr, path::Path};

use roto::{roto_method, FileTree, Runtime, Val, Verdict};

#[derive(Clone)]
struct AddrRange {
min: IpAddr,
max: IpAddr,
}

fn main() {
let path = Path::new("./examples/addr_range.roto");

// Create a runtime
let mut runtime = Runtime::new();

// Register the AddrRange type into Roto with a docstring
runtime
.register_clone_type::<AddrRange>("A range of IP addresses")
.unwrap();

// Register the contains method with a docstring
#[roto_method(runtime, AddrRange)]
fn contains(range: &AddrRange, addr: &IpAddr) -> bool {
range.min <= *addr && *addr <= range.max
}

// Compile the program with our runtime
let mut program = FileTree::read(path).compile(runtime).unwrap();

// Extract the function
let function = program
.get_function::<(), (Val<AddrRange>, IpAddr), Verdict<IpAddr, ()>>(
"within_range",
)
.unwrap();

let range = AddrRange {
min: "10.10.10.10".parse().unwrap(),
max: "10.10.10.12".parse().unwrap(),
};

// Run the function
let in_range = "10.10.10.11".parse().unwrap();
println!("{:?}", function.call(&mut (), Val(range.clone()), in_range));

let out_of_range = "20.20.20.20".parse().unwrap();
println!("{:?}", function.call(&mut (), Val(range), out_of_range));
}
18 changes: 18 additions & 0 deletions examples/modules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::path::Path;

use roto::{FileTree, Runtime};

fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let runtime = Runtime::new();
let mut compiled = FileTree::directory(Path::new("examples/modules"))
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let f = compiled.get_function::<(), (i32,), i32>("main").unwrap();

let x = f.call(&mut (), 4i32);
println!("main(4) = {x}");
Ok(())
}
8 changes: 8 additions & 0 deletions examples/modules/foo.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function bar(x: i32) -> i32 {
import pkg.double;
let a = super.double(x);
let b = pkg.double(a);
let c = double(b);
c
}

8 changes: 8 additions & 0 deletions examples/modules/pkg.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function main(x: i32) -> i32 {
import foo.bar;
bar(bar(x))
}

function double(x: i32) -> i32 {
2 * x
}
21 changes: 8 additions & 13 deletions examples/presentation.roto
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
filter-map rib-in-pre(
filtermap rib_in_pre(
output: Log,
route: Route,
) {
define {
my_prefix = 100.40.0.0/17;
}

apply {
if route.prefix_matches(my_prefix) {
output.log_custom(10, 100);
reject
} else {
output.log_prefix(my_prefix);
accept
}
let my_prefix = 100.40.0.0/17;
if route.prefix_matches(my_prefix) {
output.log_custom(10, 100);
reject
} else {
output.log_prefix(my_prefix);
accept
}
}
11 changes: 6 additions & 5 deletions examples/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type Log = *mut OutputStream<Output>;
type Func = TypedFunc<(), (Val<Log>, Val<RotondaRoute>), Verdict<(), ()>>;

fn main() -> Result<(), Box<dyn Error>> {
let mut rt = roto::Runtime::basic()?;
let mut rt = roto::Runtime::new();

// Registering types and their methods

Expand Down Expand Up @@ -122,11 +122,12 @@ fn main() -> Result<(), Box<dyn Error>> {
stream.push(Output::Custom(id, local));
}

let mut compiled = roto::read_files(["examples/presentation.roto"])?
.compile(rt, usize::BITS / 8)
.inspect_err(|e| eprintln!("{e}"))?;
let mut compiled =
roto::FileTree::single_file("examples/presentation.roto")
.compile(rt)
.inspect_err(|e| eprintln!("{e}"))?;

let function = compiled.get_function("rib-in-pre").unwrap();
let function = compiled.get_function("rib_in_pre").unwrap();

run_with_prefix(&function, "8.8.8.0/24")?;
run_with_prefix(&function, "100.40.0.0/17")?;
Expand Down
12 changes: 5 additions & 7 deletions examples/runtime.roto
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
filter-map main(bla: Bla) {
apply {
if bla.x() > 10 {
accept 2 * bla.x()
} else {
reject
}
filtermap main(bla: Bla) {
if bla.x() > 10 {
accept 2 * bla.x()
} else {
reject
}
}
8 changes: 4 additions & 4 deletions examples/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use roto::{read_files, Runtime, Val, Verdict};
use roto::{FileTree, Runtime, Val, Verdict};
use roto_macros::roto_method;

#[derive(Clone, Copy)]
Expand All @@ -9,7 +9,7 @@ struct Bla {
fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let mut runtime = Runtime::basic().unwrap();
let mut runtime = Runtime::new();

runtime
.register_copy_type::<Bla>("Some random type")
Expand All @@ -20,8 +20,8 @@ fn main() -> Result<(), roto::RotoReport> {
unsafe { &*bla }.x
}

let mut compiled = read_files(["examples/runtime.roto"])?
.compile(runtime, usize::BITS / 8)
let mut compiled = FileTree::single_file("examples/runtime.roto")
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let func = compiled
Expand Down
2 changes: 1 addition & 1 deletion examples/simple.roto
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function is_zero(x: IpAddr) -> bool {
x == 0.0.0.0
}

filter-map main(x: IpAddr) {
filtermap main(x: IpAddr) {
if is_zero(x) {
accept
} else {
Expand Down
17 changes: 4 additions & 13 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
use std::{env::args, net::IpAddr};

use roto::{read_files, Context, Runtime, Verdict};
use roto::{FileTree, Runtime, Verdict};

fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let mut runtime = Runtime::basic().unwrap();

// Adding a context is not necessary but done here for testing purposes
#[derive(Context)]
struct Ctx {
/// This is the foo usize
pub foo: u32,
}

runtime.register_context_type::<Ctx>().unwrap();
let runtime = Runtime::new();

let mut arguments = args();
let _program_name = arguments.next().unwrap();
Expand All @@ -25,8 +16,8 @@ fn main() -> Result<(), roto::RotoReport> {
return Ok(());
}

let mut compiled = read_files(["examples/simple.roto"])?
.compile(runtime, usize::BITS / 8)
let mut compiled = FileTree::single_file("examples/simple.roto")
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let func = compiled
Expand Down
34 changes: 31 additions & 3 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
.collect();

let generics = sig.generics;
let inputs = sig.inputs.clone().into_iter();
let ret = match sig.output {
syn::ReturnType::Default => quote!(()),
syn::ReturnType::Type(_, t) => quote!(#t),
Expand All @@ -266,15 +265,44 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
})
.collect();

let mut transformed_params = Vec::new();
let mut transformed_args = Vec::new();

for (t, a) in input_types.iter().zip(&args) {
match &**t {
syn::Type::Reference(syn::TypeReference {
and_token: _,
lifetime,
mutability,
elem,
}) => {
if lifetime.is_some() {
panic!("lifetime not allowed")
};
if mutability.is_some() {
transformed_params.push(quote!(#a: *mut #elem));
transformed_args.push(quote!(unsafe { &mut *#a }));
} else {
transformed_params.push(quote!(#a: *const #elem));
transformed_args.push(quote!(unsafe { &*#a }));
}
}
_ => {
transformed_params.push(quote!(#a: #t));
transformed_args.push(quote!(#a));
}
}
}

let underscored_types = input_types.iter().map(|_| quote!(_));
let arg_types = quote!(_, #(#underscored_types,)*);

let function = quote! {
#(#attrs)*
#vis extern "C" fn #ident #generics ( out: *mut #ret, #(#inputs,)* ) {
#vis extern "C" fn #ident #generics ( out: *mut #ret, #(#transformed_params,)* ) {
#item

unsafe { std::ptr::write(out, #ident(#(#args),*)) };
unsafe { std::ptr::write(out, #ident(#(#transformed_args),*)) };
}
};

Expand Down
Loading

0 comments on commit 0edcec3

Please sign in to comment.