Open LogicAndTrick opened 8 years ago
Wow, that's cool :) May be you should post it to some Rust-related mailing lists / communities, to attract more peer review? I don't know a thing about Rust myself ;)
After working with the language a bit, I've come to realise how difficult of a task this would be. Rust is certainly an interesting language to work with, but it comes with a huge list of new challenges that don't exist in other languages. I don't see myself being able to overcome them, so I'm going to quit.
There's a whole stack of architecture questions that are easy to answer in other languages, but actually very complex in Rust. The design of code generated by KS follows the easy patterns because that's how pretty much every other language works. But Rust is unique in many areas.
Rust has what they call a foreign function interface which lets you interact with C libraries, perhaps that's a more reasonable approach for Rust. But for now, I'm going to close this because I'm not able to make any more progress.
(I enjoyed experimenting with Rust: it sort of feels like a modern approach to C. The memory safety syntax is very complex for beginners, but the rest of language is quite simple and expressive. The tools are a pleasure to use as well. Would definitely recommend anyone to spend a weekend with it if they've ever been curious about it.)
Maybe someone would return to Rust implementation in future, so I thought it might be interesting to document your findings or at least map out possible obstacles on the path. What does the language lack that impedes KS implementation? Something about the type system? Memory management? Strict compile-time checks? Lack of "everything is an expression"? Something else?
The main pain point I discovered is around the references to io
, root
, and parent
in each object. If they could be removed somehow, I think I could probably get everything else going. From what I've found online, root/parent/self references require some pretty complex type chains, and the generated code would probably be pretty crazy as well. I don't see myself ever becoming proficient enough in Rust to be able to get that going correctly, and even if you could do it, the result would probably not be something that anybody would want to actually use.
If instance methods required these three pointers to be passed as arguments, then it might be more possible. For example:
// hard to do
fn get_calculated_instance(self) { ... }
// probably easier, but consumer must pass root/parent manually
fn get_calculated_instance(self, io: Stream, parent: Struct, root: Struct) { ... }
From what it seems, Rust is best approached by creating an architecture that specifically fits Rust's "memory safety first" style. Trying to modify an existing architecture so that it works in Rust is very difficult.
That's kind of strange. I guess that Rust has something that resembles an object (i.e. bundle of data + methods) and I don't see any difference in storing some "useful" data, i.e. attributes / instances vs storing a reference (pointer?) to io
object that should be used for structure parsing, or parent
, or root
.
But that said, I know almost nothing about Rust, so I can only make theories.
I'm reorganizing all "new language support" issues, adding relevant tag. I'll reopen this one, as a few people asked for Rust support again, and it's better to keep it open, so it would be easier to find and people won't create duplicates again and again.
Yes, please, very much need Rust support from Kaitai!
Happy to help with discussions and possible implementation if needed.
@berkus You probably know of http://doc.kaitai.io/new_language.html — let's just follow. I'd be happy to launch a Rust-targeting branch as soon as we'll get basic hello_world.rs
and basic tests for it.
No, this is new to me - I just started actually using Kaitai today, loving it so far.
Will take a look!
I'm going to start tentatively taking a second look at this one because the second edition of the Rust book has a dedicated chapter on reference cycles which might help me solve the roadblocks I was hitting last year. I still have no experience with actual proper Rust code so if anybody has more experience with the language, I'd love some assistance!
Question for @GreyCat: I've manually assembled the code for a hello_world.rs
file which passes basic tests, where would I put it? I don't think it's ready for CI scripts at this point, I still have to figure out the best way to separate the test project from the code project.
For the time being, it'd be good to get some feedback so here's what I've got so far for hello_world:
extern crate kaitai_struct;
use kaitai_struct::{Stream, Struct};
use std::io::{Cursor, Read, Seek};
use std::fs::File;
struct HelloWorld {
one: u8,
}
impl Struct for HelloWorld {
// Rust requires all fields to be initialised so we auto-generate an empty ctor
fn empty() -> HelloWorld {
HelloWorld { one: 0 }
}
// Passes any io::Error through to the caller using the ? operator
fn from_file(path: &str) -> std::result::Result<HelloWorld, std::io::Error> {
let mut buf = File::open(path)?;
Ok(HelloWorld::new(
&mut buf,
&None::<Box<Struct>>,
&None::<Box<Struct>>,
))
}
// Constructor from a stream
// Box<> References to parent and root are temporary and the types will change.
fn new<S: Stream>(
stream: &mut S,
parent: &Option<Box<Struct>>,
root: &Option<Box<Struct>>,
) -> HelloWorld {
let mut this = HelloWorld::empty();
this.read(stream, &parent, &root);
this
}
// Read takes a reference to stream/parent/root, this may change later.
fn read<S: Stream>(
&mut self,
stream: &mut S,
parent: &Option<Box<Struct>>,
root: &Option<Box<Struct>>,
) {
self.one = stream.read_u1().unwrap();
}
}
#[cfg(test)]
mod tests {
use kaitai_struct::Struct;
use HelloWorld;
#[test]
fn test_hello_world() {
let hw = HelloWorld::from_file("./src/fixed_struct.bin")
.expect("File not found!");
assert_eq!(hw.one, 0x50);
}
}
I'm going to start working out the parent
and root
references, if I can figure that out then I'm hoping that it should be pretty basic stuff after that.
Looks really cool :)
As for code location, I'd just leave it here at the moment. It's not like putting it somewhere into the tests repo would help anything — we need test specs, we need the parser code to be generated, etc, so the hand-written generation result doesn't really help much in terms of CI or stuff like that.
May be we could ask some Rust online communities for some input / suggestions on this one?
Neat, you wouldn't by any chance know a good way to represent the parent/root references in Rust? I have looked at it a few times and it just seems to create a painful chain of types like Option<Weak<RefCell<Rc<T>>>>
and the interface it creates seems pretty unreasonable for somebody to want to use.
It's pretty painful because of borrow checker. Usually peeps do it via a Vec
Probably some rust tree package like ego_tree or idtree may give you help?
Otherwise I believe RefCell<Rc<T>>
is the only way (but i'm no expert - been doing rust for barely two weeks now)
Since I don't know the status of this, I decided to start an alternate implementation. Still very much a WIP, but hello world now successfully compiles to this:
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
use std::{
option::Option,
boxed::Box,
io::Result
};
use kaitai_struct::{
KaitaiStream,
KaitaiStruct
};
pub struct HelloWorld {
pub one: u8,
}
impl KaitaiStruct for HelloWorld {
fn new<S: KaitaiStream>(stream: &mut S,
_parent: &Option<Box<KaitaiStruct>>,
_root: &Option<Box<KaitaiStruct>>)
-> Result<Self>
where Self: Sized {
let mut s = Self {
one: 0,
};
s.read(stream, _parent, _root)?;
Ok(s)
}
fn read<S: KaitaiStream>(&mut self,
stream: &mut S,
_parent: &Option<Box<KaitaiStruct>>,
_root: &Option<Box<KaitaiStruct>>)
-> Result<()>
where Self: Sized {
self.one = stream.read_u1()?;
Ok(())
}
}
I've tested this and confirmed it all working. My next step is to port some of the test suite over, writing test harnesses for Rust. From there, I can get them all passing, one by one.
@CWood1 Thanks, looks really cool! Note that:
Nowadays there is a roadmap for implementation of new languages: looks like this, and can be generated using these scripts.
There is really no need to port majority of test specs manually: one can implement expression support for target language, and then harness the power of KST (see #253). The translator project is here and once you'll add support for the new language there, porting many tests is a breeze, as you get it to generate specs automatically.
Oh wow, that all looks much easier than I'd anticipated! Is there any documentation on generating and running the tests for a given language automatically? Tried to figure it out from travis.yml, but that does strange things with packages which won't work on my Arch installation.
Thanks for the help, I'll take a look at getting the test translator ported next.
Unfortunately, not now, as this whole thing was literally implemented a month or so ago. Travis yaml won't help much here, as specs are to autogenerated on the fly during normal build process.
To run test translator, you'd generally want to:
sbt publishLocal
to build compiler jars and "publish" it into local repo where translator project could find itsbt run
(or load that project into IDE and run it there) to try autogenerating all possible specs:
spec/kst
spec/kst/out/$LANG
spec/$LANG
after checking that it actually does the jobSo, I've got the translator outputting tests now. Few compilation issues here and there due to incorrect syntax, nothing too extreme.
Next question: how exactly does one run the compiler against the test suite, then the tests against the compiled specs? Once I get these compiler errors resolved, that's my next goal is to have 50something failing tests I can then make pass.
@CWood1 Could you show me what exactly have you achieved so far?
Okay, where we're at (I'll be pushing all this shortly, soon as I've got a couple compiler errors ironed out), I've got a rust library project under spec/rust
. Inside of there, tests/
houses all of the tests.
Therefore, open questions:
spec/rust/src
?spec/rust/src/lib.rs
, to publicly declare all of the compiled modules in a way the tests can access?cargo test
?Doing the above manually is relatively easy, though tedious. Are there ways by which I can script them, under existing frameworks? Or would that need to be developed from scratch?
How do I get the compiler to run, and output the results into
spec/rust/src
?
There is a huge mess with terminology we have here ;)
If by "compiler", you mean ksc (i.e. app that translates ksy files into parsing source code in target language), then normally, it is run with build-formats script, it runs the compiler on all formats for all target languages, and outputs results into compiled/$LANG
.
If by "compiler", you mean kst (i.e. app that translates kst files into test specs in target languages), then it is right now runnable by invoking sbt run
in its dir (or, equivalently, launching its main class in IDE).
I suspect there's slight misunderstanding on what needs to be done. Actually we have 3 "places" to update:
RustTranslator
in io/kaitai/struct/translators in compiler project; that would be "expression translator", which translates KS expression into Rust expression (typically expression is translated into a single string, but recently we've got support for languages like Go which require translation of expressions into multiple statements).RustCompiler
to io/kaitai/struct/languages in compiler project and register it here — this would be needed to actually run ksc -t rust
and be able to output any target language code from a given .ksy file, i.e. perform the normal function of a compiler.RustSG
spec generator to io/kaitai/struct/testtranslator/specgenerators in KST project. This would rely on RustTranslator
to generate the specs.That's why I asked you to show what you've got, so I could understand which of these 3 things you were working on :)
Can I script updating
spec/rust/src/lib.rs
, to publicly declare all of the compiled modules in a way the tests can access?
No equivalent of these exists so far in any other languages. C++ might benefit from similar automation, but so far we've just added all tests manually to CMake project. This is actually a somewhat sloppy moment, but for compiled languages you don't usually have an option to go with "build everything that would build, and run the tests with everything's that we've built". Normally (for C#, C++, Java, Go), a single broken file ruins the build, so we employ various tricks to reduce that risk. Having a manually maintained list of tests that "should run ok" is a first step to mitigate that problem.
Is there a framework by which I can automatically run the above, and then invoke
cargo test
?
ci-all script invokes all ci-*
scripts in sequence. We should probably create ci-rust
, which would run thte tests and deliver some kind of (ideally, JUnit-like XML) report to test_out/
.
Okay, that makes a little more sense now. To be explicit, for the first point, I was referring to ksc - I need to run ksc in order to generate the rust to then test with.
My situation is as follows:
RustCompiler
has been created, as a copy of another Compiler. I've modified this sufficiently to get HelloWorld
compiling and correctly testing, under a manually generated test framework.RustTranslator
has been created, as a copy of another Translator. This has been largely ported over, though a few functions still need to be updated. There's a large part of this which hasn't yet been tested, however.RustSG
has been created. As of right now, I'm yet to work out how to represent nullAssert
in Rust, and am entirely unsure what trueArrayAssert
is, however these will be worked out in time.Using these, I've generated a suite of tests from the kst
sources, and put them in a directory, spec/rust/tests
. spec/rust
is a crate (rust library) for use as a testing harness.
As I see it, the next things that need to happen are as follows:
spec/rust/src
directory to compiled/rust
, so that the test harness generated from kst
works with the files under test generated from ksc
.lib.rs
in spec/rust/src
to link to each of these packages, as each one must be manually specified.ci-rust
script, which runs cargo test
on the spec/rust
crate.cargo test
to output an XML results file, to go in test_out/
.ksc
, and every Rust test file generated from kst
, to properly compile, even if the test fails. Remove all syntax errors left over from copying the RustCompiler.scala
, RustTranslator.scala
, and RustSG.scala
from elsewhere.As an extension, I may look at autogenning the test harness itself - as mentioned, lib.rs
needs to link to every Rust file under test, and other languages could benefit from similar automation as you mentioned.
It may even be worth attempting to update the test translator itself, to allow for outputting of multiple files. Under this framework, it would be possible to create an individual crate for every file under test. This eliminates the problem of a syntax error in one file entirely halting the testnig procedure, and other compiled langauges would also benefit from this as well.
I believe that should carry me to the end of this particular project, though if I've missed anything, please let me know. I'll post more updates on here as each of these happen, so my progress is visible to the world. Thank you so much for your help, it's very very much appreciated.
As a progress update on the above, I used Cargo's build script facilities to automatically copy over everything from compiled/rust
into spec/rust/src
.
It first clears the src
directory. Then, one by one it copies the files across, building lib.rs
in the process. This removes the need to manually specify lib.rs
, as it now updates itself every time the test suite is executed.
As of right now, I'm yet to work out how to represent
nullAssert
in Rust,
Null assert is a comparison of some nullable values with null. "Nullable" are mostly the values that have if
condition which can be false, and thus there would be no value, and typically we have some sort of null
equivalent returned there.
and am entirely unsure what
trueArrayAssert
is, however these will be worked out in time.
"True" arrays are arrays which result from repeat
-style constructs, i.e. arrays of some type. Usually they are represented by some sort of ArrayList
, std::vector
or similar dynamically resizable generic array type.
Opposed to them, "non-true", byte arrays are a special type which usually results from just specifying size: X
without any type
. They are typically special, as it's possible to handle them in much more efficient manner: many languages allow some kind of byte[]
non-dynamic array or String
-like type with strings of bytes.
Typically, comparison and assertion of "byte arrays" is done in exactly the same manner as comparison of other primitive types, but comparison of arrays frequently requires some special call like "assertDeepEquals" or something like that, that will compare values inside the container, not just the identity of containers.
It may even be worth attempting to update the test translator itself, to allow for outputting of multiple files. Under this framework, it would be possible to create an individual crate for every file under test. This eliminates the problem of a syntax error in one file entirely halting the testnig procedure, and other compiled langauges would also benefit from this as well.
Test translator already outputs one file per test/spec. The idea to compile every file as a separate test suite and launch it separately is definitely a solution, but its usefulness would vary from one language to another. For example, running ~140 executables for C++ is possible, but for Java it would be very slow. Right now, a test run takes ~1.4 s, but launching separate JVM for every suite would be 140x times slower => i.e. ~3 minutes.
We actually employ some crazy techniques like the one you can see in run-java, lines 31-67, i.e. we try to compile everything in one go, but if it fails, we try compiling each file in separate compiler invocation, which is obviously very slow (i.e. ~140x times slower), but it allows us to isolate the culprit(s), mark it/them up as "failed to compile" and proceed with running the rest of the tests.
If you could think of better alternatives, especially cross-language, that would be most welcome. So far the only way I see is creation of some sort of "universal build" system, which could handle all languages, but this is clearly a huge overkill for a task like this.
Okay, now we have a major issue. Because of the way Kaitai works, it expects structs/types/classes/whatever you want to call them, to be nested. Becuase of the way Rust works, they can't be. I'm yet to work out a solution to this.
Initially my thoughts were to collect each struct into some class somewhere, and have each class output itself in turn, but as far as fields go, there's no indication of what belongs to what. So I'm not entirely convinced.
@CWood1 That's not a really major issue, quite a few languages work that way. There are 2 distinct problems here, I'm not sure both apply to Rust:
If you don't have any kind of "nested" class names in a language (for example, like in Go or Construct), you can just dump class names like foo::bar::baz
always as full names like Foo__Bar__Baz
. Every ClassSpec has a name
property, which is guaranteed to have a proper full name of class with all nesting components. For example, here is how it is used for Construct
If you are not satisfied with normal call order which generates stuff like
class Foo {
class Foo__Bar {
class Foo__Bar__Baz {
}
}
}
you can set up innerClasses
to false, for example, as PerlCompiler does. This would result in an order of calls to be like that:
class Foo {
}
class Foo__Bar {
}
class Foo__Bar__Baz {
}
This innerClasses
thing actually affects the order of calls in compileClass method. If you want something completely different, you can always subclass ClassCompiler (for example, we do that for Go), and implement it differently.
Is there a way I can get it to output fields before methods? Because of the way Rust works, it needs
struct Foo {
// fields
}
impl KaitaiStruct for Foo {
// methods
}
Yes, it's slightly more complicated. To achieve that, one needs to subclass ClassCompiler and override compileClass method with different order of calls.
Go actually does exactly that — i.e. "class declaration" comes first and a Read()
method and instance methods come after that.
In order to register a ClassCompiler-derived class, though, one needs to add it to Main.compile as well.
For full names, such as Foo__Bar
, how does one then use that as a type? In that example, the type used in the Foo
struct definition is Bar
, and I've not the foggiest how to attach Foo__
to that.
As a general update, however, RustClassCompiler
has now been defined, and compilation order works. A slew of errors have been ironed out, and progress is generally getting made on all fronts. In theory, the test suite should compile soon.
In that example, the type used in the
Foo
struct definition isBar
,
Could you show me the exact code that generates Bar
and not Foo__Bar
?
A slew of errors have been ironed out, and progress is generally getting made on all fronts.
That's really cool! Would you mind sharing your branch in public — may be I can review it and throw it some ideas, and may be help with integration into the CI?
Update: a bunch more issues have now been resolved. I managed to figure out the issue with class naming and type naming, so that all works. My next issue is to figure out the fact that sometimes parent
and root
are needed in attribute readers, and sometimes multi-level parent
s are needed. That means somehow storing both in the struct itself, which the lifetime manager has already cried at me for. I have a few suggestions from colleagues though, which I'll research into a little more.
I'm also yet to work out how switch_bytearray should work. It isn't possible to directly compare vectors as one can do in other languages. Clearly it must be possible to have a special comparison for things such as vectors, for languages like Java and C++, though I'm yet to find it. If someone can point me to that before I find it manually, I'd be grateful, but until then I'll keep looking.
@CWood1 What would you think about merging your current effort into master, and making it appear in CI and tests?
Clearly it must be possible to have a special comparison for things such as vectors, for languages like Java and C++, though I'm yet to find it. If someone can point me to that before I find it manually, I'd be grateful, but until then I'll keep looking.
There's no good magic there, this is how JavaCompiler does it:
var
named switchIfs
— see https://github.com/kaitai-io/kaitai_struct_compiler/blob/master/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala#L480-L484switchStart
is the first to be invoked, and it makes a decision which switch model to choose — i.e. either true switches or a series of ifs.@CWood1 What would you think about merging your current effort into master, and making it appear in CI and tests?
So, at the minute, the tests don't acutally compile and run. I'd like to get the tests compiling first, if possible, because otherwise I fear I may actually break CI :stuck_out_tongue:. Feel free to disagree with me on that one, though.
I'll take a look into switchIfs shortly, and see how far I get with that. That should be enough to clear the next couple of hurdles at least.
Thanks so much for all of your help. Sorry things have slowed down considerably from the start of this project, I've started a new job which has my attention during the week, and I don't think they'd be too happy if I just carried on with my own stuff on the clock.
I'm alive, just to let everyone know. Sorry about the long hiatus, personal things got in the way that took priority.
I've fixed the switch stuff, and that's now working. Among the errors I'm now getting are problems with process_custom.ksy
- it tries to import nested::deeply
and my_custom_fx::MyCustomFx
. Naturally, these don't exist, which results in a compilation error. I checked the other tests, doesn't exist there either, yet somehow they pass, so clearly something is being done at some level to make that work.
Where should these exist? Are these just "magic" files that need hand writing and checking into the test repo? Or should they be generated somehow, somewhere?
@CWood1 I'm super glad to hear that you're ok and still motivated to continue ;)
process_custom
is described in the docs. This is indeed a way to invoke language-specific processing routine where it's needed, so these files you're missing are indeed hand-written. For example,
We're actually developing something called kaitai_compress, which is a collection of wrapper routines related to data compression/decompression, implemented for different languages, compatible with this "custom processing" idea.
I've taken a quick look at that, it looks like I'm going to have to add CustomDecoder to the KaitaiStruct Rust crate before I can make any more headway on this specific problem. That doesn't look too hard.
Roadmap so far:
process_custom
compiling correctly_root
, _io
and _parent
variables (I thought I could get away without them to make pointers easier, turns out not)Right now that's as far as I can tell, the undervars and warnings are responsible, between the two, for a few thousand errors, so it gets a bit hard to see the forest through the trees with those around.
The obvious things that need to happen once we compile is to fix any failing tests once everything compiles, then to formalise both crates and get them submitted to crates.io.
On the subject of crates.io, how would one go about that? KaitaiStruct is not yet ready, and I've obviously not started the other one at all, but once they're formalised and v1.0, how would I get them on the repo under the Kaitai project? Does someone have to submit it under the project, and I don't worry about it? Or do I do it under my own email?
Sorry for delayed response.
Roadmap so far:
I would actually think of getting your work merged into the master repo as top priority. Could you create a PR?
Look into creating a kaitai-compress Rust crate
This is very experimental thing, so probably a very distant goal.
On the subject of crates.io, how would one go about that? KaitaiStruct is not yet ready, and I've obviously not started the other one at all, but once they're formalised and v1.0, how would I get them on the repo under the Kaitai project?
https://github.com/kaitai-io/kaitai_struct_rust_runtime/ already exists under kaitai-io, I guess. I can add it into main umbrella project as a submodule whenever you'll say so.
Does someone have to submit it under the project, and I don't worry about it? Or do I do it under my own email?
If you mean crates.io and similar submissions, we can create special account for that, I guess, something like crates@kaitai.io? That domain's mail is currently served by zohomail, so there would be a web interface for that and all that stuff...
PRs has been created, and since my last message that's all the work I've had the time to do, I'm afraid.
That makes sense about the crate, on both points, I assume I can just ping someone on here or something and that'll get done? Or, failing that, I'd be happy to look after the Rust crate if needed, and run crates@kaitai.io accordingly. This is all a long way off either which way.
To publish just use the agreed email and run cargo login / cargo package / cargo publish
- see here.
Coming at this with no context, is there anything I could work on? I'd be very glad to have Rust support in Kaitai.
@jonstewart Rust support was contributed by @CWood1, and the next major milestone would be to ensure that its tests run properly in CI. Unfortunately, I myself know very little about Rust, and my priorities for v0.9 lie in other tasks. If you'd be able to pick it up, that would be awesome ;)
Progress is being made, I'm sorry for the radio silence. I've been trying to fix the issue with the junit crate which has had me blocked. I'll be redoubling my effort in the new year.
If I do a little bit of reorganising, I'm hoping to be able to get the initial version merged in sometime in January.
@CWood1 Thanks for the update! I'd be happy to help, especially if you can point me at starting places. I have a modicum of Scala experience, a smidge of Rust (with a desire to learn more), and a heavy background in C++ and dealing with binary data. I'm trying to get my team to adopt both Kaitai and Rust, so am eager to learn more and participate.
So, to give full context to what's going on right now, cargo-test-junit appears to be dead. I've been trying other ways to get the xml file Travis needs, to no avail, so just now I've forked it. Reason being, one of its dependencies appears to be out of date. I'll get that updated and in, either today or tomorrow. At that point, updating the Kaitai repo to use the new dep will be nice and straight forward.
From there, process_custom hasn't been implemented at all, there's currently no way yet to walk back up the tree or process from root, and I'd like to look at getting the output nostd
if I can, as a stretch goal. More work may end up surfacing as these are completed, but that's where we're at right now.
You probably won't be able to help very much until the tests are in and successfully working, though if my new way works, it won't be January, it'll be like tomorrow. Following on from that though, given you're not so familiar with Rust yet, process_custom will probably be easier, and I'll play with some weak pointers to try and get root/etc working.
Hang fire for now, I'm hoping I can speed this along and actually get some code merged (I'm getting impatient on that myself). Once that's done, things will pick up a lot more steam again, and hopefully not take too much longer to get this project finished.
Guys, just a little ahead warning: we're slowly transitioning from old CI to new CI (URL is probably subject to change).
The main difference between old CI and new CI is that:
The workflow for new one is similar and tests still live in kaitai_struct_tests repo, what is changing is:
test_out/$LANG/ci.json
file.ci-$LANG
If you'd be interested in doing Rust CI support the same way, it would probably require:
prepare-rust
script in the root to install everything needed in a test VM to run Rust tests (i.e. pulling Rust KS runtime, installing Rust compiler, stdlibs, etc)and that's it. Format compilation results (i.e. compiled/rust/*.rs) are already available, waiting to be launched.
Ack, I'll factor that in to my work. You've actually reminded me, there also needs to be a crate that invokes kaitai from build.rs, so we've got proper cargo integration.
I do wonder if that can be used for the test framework later on as well.
Adding this so it can be tracked, but I plan on doing most of this myself. I've not yet had a need for Rust but I've been wanting to try it out anyway, figured this is a good excuse.
I've created a runtime for Rust: https://github.com/kaitai-io/kaitai_struct_rust_runtime
I'll be adding matching tests and a compiler for Rust in the future.
Note that I don't know Rust at all so I'm learning as I go. If anybody has coded with it before I would very much appreciate advice, suggestions, or even a code review of the runtime!