Jump to page: 1 2 3
Thread overview
I wrote an AR archive (.a files) parser in D
Aug 04
Renato
Aug 04
Renato
Aug 06
IchorDev
Aug 08
IchorDev
Aug 08
IchorDev
Aug 09
IchorDev
Aug 10
IchorDev
Aug 17
Renato
Aug 17
IchorDev
Aug 19
Renato
Aug 20
Renato
Aug 22
IchorDev
Aug 22
IchorDev
Aug 25
Renato
August 04

Hey,

I wanted to learn how AR archives work, and use D for something not so hard to practice a little bit.
Unfortunately, they don't seem to be standardized, but the Wikipedia entry helped me a lot.

I got it mostly working and it's able to parse several .a files I've tried, including libphobos.a and .a files generated on my system. It's not complete yet as I didn't parse the "file mode" bytes and I didn't consider "System V extensions" (though I did include the "BSD Variant" as D uses that on MacOS), but that should be easy to do soon.

Just announcing here in case someone may be interested in that (the code is very easy to read) and wants to give some feedback on my usage of D (I'm not experienced in D, just using it for some fun every now and then).

August 04

On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:

>

I wanted to learn how AR archives work, and use D for something not so hard to practice a little bit.
Unfortunately, they don't seem to be standardized, but the Wikipedia entry helped me a lot.

LINK: https://github.com/renatoathaydes/dar

August 05

On Sunday, 4 August 2024 at 20:15:46 UTC, Renato wrote:

>

On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:

>

I wanted to learn how AR archives work, and use D for something not so hard to practice a little bit.
Unfortunately, they don't seem to be standardized, but the Wikipedia entry helped me a lot.

LINK: https://github.com/renatoathaydes/dar

Nice way to practice!

August 06

On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:

>

Just announcing here in case someone may be interested in that (the code is very easy to read) and wants to give some feedback on my usage of D

First of all, you should really be using const instead of in.
Second, do not cast from const(ubyte[]) to string. This is a violation of D’s type system. string is an alias of immutable(char)[]. You’re casting to immutable—never cast to immutable! Immutable data must never change during the lifetime of a program, but const data may be changed from elsewhere (e.g. another thread), so this cast violates all the assumptions we make for immutable data! Instead, you should cast to const(char[]) in those places.
You also cast to immutable here.

Since both mutable and immutable data implicitly cast to const, if you want to take both as parameters, then always make your parameters const.

August 08

On Tuesday, 6 August 2024 at 14:55:50 UTC, IchorDev wrote:

>

On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:

>

Just announcing here in case someone may be interested in that (the code is very easy to read) and wants to give some feedback on my usage of D

First of all, you should really be using const instead of in.
Second, do not cast from const(ubyte[]) to string. This is a violation of D’s type system. string is an alias of immutable(char)[]. You’re casting to immutable—never cast to immutable! Immutable data must never change during the lifetime of a program, but const data may be changed from elsewhere (e.g. another thread), so this cast violates all the assumptions we make for immutable data! Instead, you should cast to const(char[]) in those places.
You also cast to immutable here.

Since both mutable and immutable data implicitly cast to const, if you want to take both as parameters, then always make your parameters const.

Why shouldn't I cast the read result directly to immutable when it's literally impossible to get a reference to those bytes that is not immutable? It seems like the best way to achieve what I need.

Also, I thought in is the new way of using const parameters, and they're equivalent according to the docs.

August 08

On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes wrote:

>

On Tuesday, 6 August 2024 at 14:55:50 UTC, IchorDev wrote:

>

On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:

>

Just announcing here in case someone may be interested in that (the code is very easy to read) and wants to give some feedback on my usage of D

Second, do not cast from const(ubyte[]) to string

I supposed this is the code bothering you?

auto file = (cast(string) input[0 .. 16]).strip;

I do want a string there, but I think you're saying that because input had a in attribute, it "may" be mutable via another reference.
I agree with that, specially when the "default" implementation get the bytes from a memory-mapped file. What's the best solution in this case, to dup the bytes and then cast to string?

Or you mean I can't even use string at all in this case, and therefore can't use functions like std.string : strip, startsWith?

August 08

On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes wrote:

>

Why shouldn't I cast the read result directly to immutable when it's literally impossible to get a reference to those bytes that is not immutable? It seems like the best way to achieve what I need.

You’re still violating the guarantees of immutability—data can’t go from mutable to immutable, that’s what const is for. Using const would be totally fine, or you can use .idup to create an immutable copy of the array.

>

Also, I thought in is the new way of using const parameters

No, it’s an old redundant way of using const for parameters. It also doesn’t let you specify what part of the type is constant, like const(ubyte)[] vs const(ubyte[]). It’s completely useless.

>

and they're equivalent according to the docs.

In the future in might be replaced with a functional equivalent of scope ref const that binds rvalues, which is also mentioned in the spec. You can try this newer functionality with -preview=in, but using previews is not ideal for libraries. Also the new behaviour of in is basically a waste of time for arrays. It’s moreso for medium-sized structs that would actually be expensive to copy.

August 08

On Thursday, 8 August 2024 at 10:55:49 UTC, Renato Athaydes wrote:

>

I supposed this is the code bothering you?

auto file = (cast(string) input[0 .. 16]).strip;

I do want a string there, but I think you're saying that because input had a in attribute, it "may" be mutable via another reference.
I agree with that, specially when the "default" implementation get the bytes from a memory-mapped file. What's the best solution in this case, to dup the bytes and then cast to string?

For file you should probably use .idup since your struct requires a string, but for sizeStr you can just cast to const(char)[].

>

Or you mean I can't even use string at all in this case, and therefore can't use functions like std.string : strip, startsWith?

That is plainly ridiculous. Read the documentation for these functions below and take note of how neither of them take immutable(char)[] (AKA string) as parameters:

  • strip takes an array of any const char (char, wchar, or dchar). As a reminder, mutable and immutable both implicitly convert to const.
  • startsWith takes any kind of input range.

Also about why you should never cast to immutable:
The reason we have immutable is that while const may be useful, it doesn’t guarantee anything:

  • mutable: this data can be modified here
  • const: this data can’t be modified here
  • immutable: this data will NEVER be modified after initialisation

The guarantee that immutable data is actually immutable is important. Casting the contents of an array to immutable completely nullifies this guarantee, and might cause problems with code that is optimised around that guarantee. Is this likely to affect your small case? Technically no, but it’s the first step down the dangerous path of lying to the compiler, which might end up causing you a lot of headaches when everything breaks later. Sometimes violating D’s type system is necessary or even desirable (see: shared w/ mutexes), but I wouldn’t recommend it for a beginner or even an intermediate D user.

August 08

On Thursday, 8 August 2024 at 11:07:35 UTC, IchorDev wrote:

>

On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes wrote:

>

Why shouldn't I cast the read result directly to immutable when it's literally impossible to get a reference to those bytes that is not immutable? It seems like the best way to achieve what I need.

You’re still violating the guarantees of immutability—data can’t go from mutable to immutable, that’s what const is for. Using const would be totally fine, or you can use .idup to create an immutable copy of the array.

>

Also, I thought in is the new way of using const parameters

No, it’s an old redundant way of using const for parameters. It also doesn’t let you specify what part of the type is constant, like const(ubyte)[] vs const(ubyte[]). It’s completely useless.

Wait a second... is that your opinion or official D's position? Because in is documented as being used for function inputs:

>

Input parameters behave as if they have the const scope storage classes. Input parameters may also be passed by reference by the compiler.

That's EXACTLY what I want! And it's shorter and nicer looking than const. Sorry, but I will keep using it :).

>

That is plainly ridiculous. Read the documentation for these functions...

Sorry, but have I made you angry somehow?

Can we just talk in a civilized way please?

I thought that functions from a module called std.string would take, you know, strings.

>

Is this likely to affect your small case? Technically no, but it’s the first step down the dangerous path of lying to the compiler,

The program works and I didn't lie to the compiler. read doesn't keep a reference to the byte array, and there's no way to access it since I cast it before assigning it. I get your point, but I don't see why insist on not casting to immutable even when it's patently safe to do so.

August 09

On Thursday, 8 August 2024 at 16:42:30 UTC, Renato Athaydes wrote:

>

On Thursday, 8 August 2024 at 11:07:35 UTC, IchorDev wrote:

>

Input parameters behave as if they have the const scope storage classes. Input parameters may also be passed by reference by the compiler.

That's EXACTLY what I want! And it's shorter and nicer looking than const. Sorry, but I will keep using it :).

You might’ve neglected to read the note above:

>

Note: The following requires the -preview=in switch, available in v2.094.0 or higher. When not in use, in is equivalent to const.

Again, using previews in libraries is generally not great for code compatibility, but you will have to add the preview switch to your project for in to behave the way you want. Right now, your code is still using in as an alias to const, which could potentially become an issue if the new in behaviour becomes the default and your code doesn’t treat those parameters as if they’re also scope.

>

Sorry, but have I made you angry somehow?
Can we just talk in a civilized way please?

You were just wrong. It’s not uncivilised to point out how absurdly wrong you were. If you do not like being told that you’re wrong then don’t be wrong.

>

I thought that functions from a module called std.string would take, you know, strings.

string AKA immutable(char)[] and char[] are both ‘strings’, it’s just that we don’t usually pass around mutable strings.
Also startsWith is a public import from std.range.searching. How did you manage to call these functions without reading their documentation?

>

read doesn't keep a reference to the byte array

That depends on the implementation of the function, which could change to keep a mutable reference without any warning since it isn’t pure or anything. Is it right to assume that a given impure function does not and will never in a future revision keep a mutable reference to its return value? I think not opening that can of worms is just simpler to manage, and const will work the same way in your case anyway. You’re not sharing data between threads or anything.

In your new code you’re casting to const char[] a lot when it would probably be preferable to cast to const(char)[] to avoid the headaches of having the array itself be const, thereby preventing you from reassigning to it. There’s rarely a reason to make an array const because it’s just a pointer and a length—it’d be like using char const * const in C.

« First   ‹ Prev
1 2 3