Hi,
I'm motivated to implement an SNMP-Library for Roc, but I'm unable to find a platform which lets me send and recieve UDP-packets. Is there already any platform or just an API for UDP? It's hard to find good pointers to platforms and their API. So thanks in advance for any help or pointers for this matter :)
I've never heard of anyone implementing either of these for Roc. I'm pretty sure we don't have them yet. In fact I never heard of SNMP at all! Maybe you could say a bit more about what kind of apps you want to build?
Basic-cli has Tcp implemented so you could fork that and add Udp in a similar way.
Brian Carroll said:
I've never heard of anyone implementing either of these for Roc. I'm pretty sure we don't have them yet. In fact I never heard of SNMP at all! Maybe you could say a bit more about what kind of apps you want to build?
In my workplace, we have a lot of low level hardware (routers, switches,...) that I need to monitor. Usually, they are locked down to only respond to ICMP and SNMP. So I'm forced to use that protocol, it's not the best but it does the job.
Until now, I used some python or perl libraries to write simple scripts that gather metrics via snmp.
I wrote my bachelor thesis using elm and learned to love the functional style.
Since elm is not suited at all for these tasks, roc is a natural replacement for it.
OK cool. Well people have done low level programming with Roc before, and this sounds totally feasible, but nobody's done it yet. I think Anton's suggestion is the right place to start! The basic-cli platform is for writing command line scripts, and it sounds like you've written this kind of script with other languages before so it should fit.
Do keep us updated and keep asking questions!
Anton said:
Basic-cli has Tcp implemented so you could fork that and add Udp in a similar way.
That's a good start! If I'm not mistaken, I would have to add the send/recieve method declaration (!= implementation) inEffect but where would I then implement the according Rust code?
Rust TCP code is here
The Rust function linked as roc_fx_tcpConnect
implements the effect called tcpConnect
in Roc
Brian Carroll said:
Rust TCP code is here
Perfect! I'll go ahead and keep you updated ;) Thank you so much :)
The roc_fx_
name prefix is added by the compiler. This convention is part of how effects work in Roc. It's not very well documented unfortunately but hopefully you will be able to follow the patterns.
There is also a tcp_glue.rs file saying that it was generated via roc glue. Whats up with that? The cli says "Generate glue code between a platform's Roc API and its host language". Will it be automatically called upon build of basic-cli or do I have to do so manually? Is there more documentation on that?
The Rust code needs to know how to read and write the Roc data structures, so we autogenerate Rust type definitions for them, and we call this "glue code".
The roc glue
command generates this glue code. You need to provide it with the platform main.roc file and another Roc file specific to the language you are generating for. It currently only works well with Rust - there's a RustGlue.roc somewhere in the repo.
I personally don't know the basic-cli platform well enough to know what build script it's run from. I'd start looking in the CI scripts and Cargo build.rs file.
Brian Carroll said:
The Rust code needs to know how to read and write the Roc data structures, so we autogenerate Rust type definitions for them, and we call this "glue code".
Theroc glue
command generates this glue code. You need to provide it with the platform main.roc file and another Roc file specific to the language you are generating for. It currently only works well with Rust - there's a RustGlue.roc somewhere in the repo.
I personally don't know the basic-cli platform well enough to know what build script it's run from. I'd start looking in the CI scripts and Cargo build.rs file.
Allright, so there is no standard way of doing it platformwise and I have to dig into the CI to see if/where its called. But is it called on a per platform basis or on a per module basis, does roc glue
automagically find, what it has to generate or do I have to supply arguments?
The CLI says it wants:
roc glue <GLUE_SPEC> <GLUE_DIR> [ROC_FILE]
I would assume that ( in the case of basic-cli):
GLUE_DIR
is platform/src
ROC_FILE
is platform/Effect.roc
but what (the hell) is a GLUE_SPEC
;)?
Edit: Answered here
Glue is not generated in CI or using the build.rs, all glue files have been generated with roc glue ...
and added to the repo
GLUE_SPEC may be this file but I don't have much glue experience either.
For basic-cli I have a PR that hasn't merged yet, that cleans up glue for the whole platform to be generated from the one script. You can check that out for inspiration on how you could use glue to generate the types you need for these new effects.
Glue is still a work in progress and there are quite a few known issues that you need to work around, but for the most part it is very helpful, moreso than manually writing the glue code.
Can you share a link to the PR?
https://github.com/roc-lang/basic-cli/pull/135
:wave: -- also came here interested in a UDP implementation. @Jerome Bergmann -- did you have any luck with this?
Aaron Strick said:
:wave: -- also came here interested in a UDP implementation. Jerome Bergmann -- did you have any luck with this?
No, I spent a couple of hours poking around in the source code and then my personal life carried me away. If you have any success, I'm still interested. TBH, I forgot this thread until your question slided into my mails. Maybe I will give it at shot in the near future. Anyways, good luck, hope we'll get this sooner than later ;)
OK - I started poking around last night and I made some progress. I did the following:
basic-cli
basic-cli
- I can run a roc program that reflects those changesUdp
and InternalUdp
packages that basically just copy/paste the respective Tcp modulessrc/lib.rs
UdpSocket
docs so I could actually implement itBut I stopped there for night 1-
I'm hoping that by adding the appropriate functions in lib.rs
it will Just Work:tm: -- but I have a sense that I will need to do something around "generating glue" -- but I don't know.
Perhaps someone could weigh in here. (But also, I won't be able to dive back for the next few days... and at that point, I'll know better if I run into a hiccup.
Made some progress here:
Tcp
modules so that they actually had a few Udp specific functions.But... unfortunately I got kind of stuck here.
I first received errors that were somewhat expected -- that my types didn't actually exist in rust.
error[E0433]: failed to resolve: could not find `BindResult` in `roc_app`
--> src/lib.rs:951:22
|
951 | roc_app::BindResult::Bound(ptr)
| ^^^^^^^^^^
| |
| could not find `BindResult` in `roc_app`
This makes sense!
I had a feeling I'd have to generate some glue. So I ran the ./glue.sh
script that is in the repo.
This resulted in a big diff incrates/roc_app/*
.
On the surface, the diff looked good (ie, I saw my new types reflected)
However! I could not get the example to run, receiving a wholly unexpected group of errors that looked like this:
--> /Users/strickinato/code/basic-cli/crates/roc_app/src/x86_64.rs:326:39
|
326 | const _SIZE_CHECK_union_ReadErr: () = assert!(core::mem::size_of::<union_ReadErr>() == 40);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: core::mem::size_of::<union_ReadErr>() == 40', /Users/strickinato/code/basic-cli/crates/roc_app/src/x86_64.rs:326:39
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
This is where I'm stuck. And I am wondering:
Here is a draft PR with my starting initial code and the example:
https://github.com/roc-lang/basic-cli/pull/212/files
I've also checked in the problematic generated glue code:
(commit)
If anyone has an ideas to unblock, happy to keep trucking.
If your types are simple enough it's much easier to hand roll them.
If your type is more complicated, I think the best strategy is to make a "fake" platform that just uses that single type, and then run glue on it and copy-paste the generate Rust out and clean it up a bit manually.
If you can avoid re-generating glue for the whole of basic cli then that would be best, as I usually go through and fixup the glue generated code manually.
If you use a fake platform you can generate glue into a random/temp directory
Interesting! OK -- By "hand roll"
I am pretty sure you mean to just type out (or copy/paste/edit) the types in crates/roc_app/<arch>.rs
That I think I can do
Also, I have a release of the glue platform files so you don't have to have the roc repository cloned locally. You can copy just the RustGlue.roc
spec and replace the platform with pf: platform "https://github.com/lukewilliamboswell/roc/releases/download/test/olBfrjtI-HycorWJMxdy7Dl2pcbbBoJy4mnSrDtRrlI.tar.br",
Yes, though I would advise putting your handrolled types in platform/src/lib.rs
for now
The roc_app
crate is generated by glue, so you might lose the types if someone re-generates glue over the top of it
:pray: - OK - that makes sense.
I find using roc glue RustGlue.roc glue-tmp/ dummy-platform.roc
and using the generated types much quicker than writing by hand, and if you have only one type in the mainForHost
in the dummy-platform.roc
then there isn't too much to sift through
I don't really have reps setting up platforms yet -- so I'll probably start with the hand roll option. I should be able to dive into that more quickly
Thanks for your help :smile:
Last updated: Jul 05 2025 at 12:14 UTC