On 11/13/2011 11:53 PM, David Rajchenbach-Teller wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

        Dear Rusties,

  I am currently in the early stages of writing a file system access
library for mozilla-central that might eventually replace some or all
of mozilla-central low-level file access code with something faster
and a little higher level. I also consider porting ? perhaps even
prototyping ? this library to Rust.

For this purpose, I need a little guidance on a few points.

*** #ifdef

My code heavily relies on #ifdefs with macros to compile code
conditionally, depending on both:
- - which platform is targeted (in mozilla-central, that's macros
XP_WIN, XP_UNIX);
- - which primitives are available in libc (through autoconf's
AC_CHECK_FUNS and the macros HAVE_xxxxx that it defines).

What is the best way to achieve this in Rust?


Rust items can be conditionally compiled with the 'cfg' attribute, so your build can call 'rustc --cfg FEATURE' (and you can provide --cfg any number of times) then you can have functions annotated #[cfg(FEATURE)]. The target platform is already set by default as 'target_os', so you can say #[cfg(target_os = "win32")].

If your question is more about how to integrate your autoconf-based build with Rust's anti-autoconf build then the answer is probably that they have to be kept separate.

*** Foreign types

- From what I see in the code of unix_os.rs, we can simply define `type
foobar` in a foreign module and use this in the code. Are there any
limitations to this that I should know before employing the technique?


These types are pointer sized, so they can be used to pass around pointers to opaque types, but not much else. If that doesn't work then you have to create a Rust declaration with the same structure as the C declaration. std does this in a few places.

*** Unicode

On Unix platforms, file names are `char*`. On Windows platforms, they
are `wchar*`. In mozilla-central, I use the strings API to make my
life simpler and to handle all conversions for me. How should I do
this with Rust?

As far as I understand, the current win32_os.rs simply assumes that
any `str` passed can be used as a valid `char*`, and relies on Cygwin
to handle any oddity. As most of the features of Win32 are not
available through Cygwin, this is probably something that I cannot use.

stdlib's string handling for win32 is wrong and I don't believe anybody has put much thought into what needs to happen. Suggestions welcome.

*** Garbage-collection / destruction

I am not familiar with Rust resources yet, but chances are that I will
need to interact with them to get destruction and garbage-collection
on file descriptors and directory structures.

- - Do I understand correctly that resources a the right tool for the task?
- - From the documentation, I understand that a failed task will not
call destructors. Do I understand correctly? If so, this seems like a
major issue, as a process with failed tasks will leak file descriptors.


Resources are what you want, but you usually want to box them and wrap them in some other type because they are a bit unwieldy from a user perspective. Failed tasks will call destructors during unwinding. Can you point me to the incorrect documentation? One thing to note is that we still don't implement unwinding on win32 so failure is currently unrecoverable on that platform.

*** Error-handling

For file access, some error conditions are indeed failures, while some
are simply information that should be propagated. As I understand,
Rust will not have ML/C++-style exceptions in any foreseeable future.
I therefore see the following possibilities:

- - Either aggressively `spawn_notify` tasks, `unsupervise` them and
`fail` in case of any error, with some convention to pass `errno`;

I've tried to implement this approach before and found that the language is not yet expressive enough to do this in a convenient way (because we can't spawn closures). It's also quite inefficient for general use.

- - or have each function return `either::t<Result, Error>` and
propagate error conditions manually, much as is done in current
mozilla-central code;

std has a 'result::t<T, U>' type that I am trying to use for this purpose. std::io makes use of this now.

- - or offer both styles, with some naming convention to differentiate
them ? say submodules `fails` / `dnf`.

Any suggestion on the best policy?

I prefer std::result

Well, that covers most of my interrogations. Any suggestion or idea?

Sounds promising.


_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to