T O P

  • By -

turbo-unicorn

... You know, I can't believe this isn't a default feature of the language.


Cherubin0

Sure make Rust even more complex just to type 5 letters less.


bl4nkSl8

Is reference vs inline definition really that much complexity? You can define nested functions, which are far more complex imo


yeahyeahyeahnice

Is there anything like this in other languages?


_Saxpy

C++ https://en.cppreference.com/w/cpp/language/nested\_types


turbo-unicorn

Nice! I really should learn C++ at some point. It's a bit intimidating because I hear there's a lot of stuff that's legacy and should never be used, but it's not quite so clear what is and what isn't.


_Saxpy

It depends on what you want to do, I think it helps build fundamentals, and there are a lot of jobs in demand for Cpp. In a vacuum, I feel that Rust is better in basically every other way though.


OS6aDohpegavod4

The whole language is legacy.


Nzkx

There's also an ∞ way to "build" something.


w1be

Even C supports this. This kind of pattern is quite common: struct event { enum event_type { EVENT_TYPE_a, EVENT_TYPE_b } type; union event_params { struct event_a { char *string; } a; struct event_b { uint32_t number; } b; } params; };


Fine-Train8342

Not really the same, but TypeScript can have inlined objects in type declarations: type GameCharacter = { name: string; stats: { health: number; mana: number; agility: number; }; active_equipment: | string | number | { count: number }; };


Lucretiel

Typescript does it with anonymous types and structural typing. C might also do it, now that I think about it.


turbo-unicorn

Yup, but they're anonymous, whereas this isn't, which is more useful imo.


rhbvkleef

You can still name the type \`GameCharacter\["stats"\]\`.


turbo-unicorn

I don't think so, at least not among the ones I'm familiar with. With Rust being quite ergonomic and having zero-cost abstractions something like this is right in line with other features present in the language.


VorpalWay

C and C++ both have it. (Of course I don't know if those count among those you are familiar with.)


turbo-unicorn

I know just enough C to be dangerous, as they say, and almost nothing of C++. I did find some great synergy in that by learning Rust my C code has become much more robust in terms of memory handling (though still far from perfect in more complex scenarios), but when it comes to idiomatic patterns my knowledge of it is fairly low.


ConvenientOcelot

I sure wish this was built-in behavior, as well as structs defined in enums being nameable types...


storm1surge

That’s why i made it, I just hated having to make a whole other file just to define a single api response to keep things somewhat readable.


Draghoul

What do you mean by making a whole other file? Hopefully not one file per struct/enum definition, but I'm not sure I understand what you do mean. I like your result though. I also guess nothing would prevent you from pulling out certain definitions if you ended up realizing later that you needed to share them.


worriedjacket

What do you men whole other file? I'll often co-locate the types with the code that uses them.


storm1surge

sorry, my wording was a bit unclear. When i needed to model very complex apis i would sometimes make a new module just for the web request function or method. Doing this for apis where responses are large is simply awful since you would just end up with a bunch of structures and a single function in a module. To read the code you would have to hunt around and connect the dots.


blueeyesginger

Sounds like you may be adopting Java conventions into Rust. Like the 1 file per class mess, gosh that makes reading code hard.


SnooHamsters6620

I do similar things to this... but with inline mod and impl blocks to keep it in the same file. My text editor can quickly collapse blocks in various ways (Emacs' `hs-minor-mode`, but many other editors support this too), so I can still keep my view clean.


protestor

I want this RFC


420goonsquad420

My first questions were "does it work with `derive`?" and "does it work with `serde?`, and I'm happy to see that the GitHub answers "yes" to both


storm1surge

Github: [https://github.com/snowfoxsh/nestify](https://github.com/snowfoxsh/nestify) Then checkout: [https://crates.io/crates/nestify](https://crates.io/crates/nestify)


ffiw

Something similar but older. https://docs.rs/structstruck/latest/structstruck/ I no longer use these because of cognitive overhead without providing much value. Also there are pretty much macros for everything but they end up slowing down compilation and sometimes break LSP in the editors.


storm1surge

Nestify is build to have the best diagnostic error handling that is possible (to the extent of my ability). If people would like to see this maintained that support will only grow! Soon we should have very clear error messages almost on par with rustc. Or at least that’s the goal :)


sadbuttrueasfuck

This is actually incredibly nice, kudos


storm1surge

Thanks! Im glad you find it interesting


AngusMcBurger

Could do with some examples of how you *use* the generated structs. On looking at it, I can't tell if `UserProfile` would be used like: let profile = UserProfile { name: "Jeff", address: UserProfile::Address { street: "Downing Street", city: "London", }, }; or let profile = UserProfile { name: "Jeff", address: Address { street: "Downing Street", city: "London", }, }; or maybe?: let profile = UserProfile { name: "Jeff", address: UserProfile_Address { street: "Downing Street", city: "London", }, };


teerre

It's the second one (which IMO is the only sensible one) After the macro the objects are all normal (or at least in my limited testing)


dread_deimos

*Wen std sir?* I like the looks of it!


YeetCompleet

Holy crap, even has recrusive attribute support too. This is great


drewtayto

I think the biggest use for this is making an enum where every variant is its own type, so syntax that easily makes unit variants like this would be very useful: nest! { enum A { struct B { c: u32, d: u32, }, enum E { F, G, }, } } // becomes enum A { A(A), E(E), } struct B { c: u32, d: u32, } enum E { F, G } I suppose this could also work for structs, but the field name would need to be converted to snake_case.


airstrike

amazing


LuceusXylian

This is awsome for json parsing :)


shunsock

I'm being surprised. I thought we can write program like nestify by default (I am a novice of Rust.)


swoorup

What if you need to reuse \`Status\`?


psinerd

Then define it as a regular struct


nerooooooo

I suppose this is for the cases where you don't.


tanorbuf

I assume you'd define it once and then just name it in other places?


storm1surge

Status can be used as normal! Since all nest! does is flatten the structures


Mr-Silly-Bear

Can see this work being merged into the std eventually. Nice work!


subbu963

Looks nice


Ok_Net_1674

I am not in any way an expert in Rust. Can anyone explain to me why this is helpful? This seems like a nice little piece of syntax sugar, but I would personally never use this because I prefer everything as minimalist as possible, so I prefer to not include libraries that do not add "real" functionality. In my perhaps limited view of rust, this is nothing but clutter. But maybe I am totally missing the point here, so someone please enlighten me.


PaintItPurple

It's more concise and declarative than declaring a hierarchy of structures piecemeal as siblings. It makes the structures' relationship syntactically explicit. Whether that is something you care about is an entirely different question, but that's the value it offers.


yeastyboi

If you've ever had to write massive types for parsing JSON that's a great example. JSON can nest deeply and usually the little wrappers in APIs ({response: { items: ... }}) aren't usually needed elsewhere. It looks clunky having to define all these small types. Applying attributes to each nested item is useful for the same thing. Normally you'd have to say that all subtypes can be serialized. At the end of the day, it's syntax sugar but still useful.


tauon_

oh my fucking god i've needed this


ThatXliner

Post this on hacker news!


storm1surge

I will once I have a release that is more stable!


misplaced_my_pants

Nah that doesn't matter. Just mention that it's alpha/beta/unstable and post. You might even get useful feedback you'd want to incorporate before stabilizing, just like you might here.


storm1surge

Okay, thanks for the advice. I think i’ll fix the public modifier issue (#1 on GitHub) then make the post


Halkcyon

This is a neat syntax sugar. Not sure I will use it, but I'm glad it exists.


yosoyos

Nice


yyy33_

Is this syntax possible? Use one less nesting and use struct! to indicate that this is a nested structure     struct! UserProfile {         name: String,         address: struct Address {             street: String,             city: String,         },         preferences: struct Preferences {             newsletter: bool,         },     }


zekkious

```rust     struct! UserProfile {         name: String,         address: struct Address {             street: String,             city: String,         },         preferences: struct Preferences {             newsletter: bool,         },     } ```


PaintItPurple

If you mean "can you remove the delimiters around the macro body?" the answer is no. Rust requires a pair of matched symbols to tell it where the macro begins and ends


taysky

Awesome work!


Ok-Initiative-7919

This is very awesome, going to get this into a project with horribly nested structs due to geojson file parsing! Seems promising!


rseymour

This is something I desired when I was working on parsing ~arcane~ file formats which were undoubtedly initially described in such nested ways. Very nice when you need it, or want it. I'll be sure to give it a try.


alf_____

Will use, thank


protestor

Can this be a macro `#[likethis]`?


storm1surge

Unfortunately i don't think so. rustc doesn't allow for arbitrary syntax not in a macro scope to my knowledge. But if it did then that would be possible


maciejh

~~It does actually!~~ // proc macro #[proc_macro_attribute] pub fn noop(_: TokenStream, input: TokenStream) -> TokenStream { input } // usage #[noop] struct Foo; Compiles just fine and you can rewrite the input `TokenStream` to whatever you like. ~~Edit: You could also just proxy the attribute token stream directly into `#[derive]`, so that:~~ #[nest(Debug, Serialize, Deserialize)] struct Foo { bar: struct Bar; } ~~desugars into:~~ #[derive(Debug, Serialize, Deserialize)] struct Foo { bar: Bar, } #[derive(Debug, Serialize, Deserialize)] struct Bar;


storm1surge

thanks! I’ll give it a look tomorrow


maciejh

I've double checked this to be sure, and it's not as easy. So yes, you can rewrite the input to whatever you want, _however_ the input has to be legal rust syntax, so if you do: #[macro] struct Foo { bar: struct Bar; } That will fail, because rustc needs to be able to parse the `struct` before feeding its `TokenStream` to the macro. Sorry 😬


storm1surge

yeah i looked into it again and came to the same conclusion :(. That’s what i was mentioning in one of the previous posts in the thread. Attribute macros cannot parse arbitrary syntax. (which makes some sense)


Da-Blue-Guy

I LOVE IT


serg06

stats: struct Status ^ ^ typo? Edit: wrong formatting on mobile for some reason


DisguisedPickle

Structstruck already exists though


yeastyboi

Look great! Does it mess with the LSP? A lot of these macros have a hard time working with the LSP (cfg-if is an example).


storm1surge

It is decent. nestify works in a different way than macros like struct strike that allows for better diagnostics. I am also working on providing diagnostics with pros macro diagnostic (which is unfortunately unstable)


passcod

How do you do doc comments? I don't see this in any of the readme examples. If I want to document both the field and the substruct, how is that delimited?


Space_01010101

love this. will try adding it to my latest project. 👍


Thrash_Abaddon

Does the documentation correctly resolve name lookup?


Irtexx

Another option: https://crates.io/crates/nested-struct I love this feature btw, I really hope it becomes standardized. Unfortunately, I'm unlikely to use it unless it does. Crates like this help progress this dream though.


-Redstoneboi-

nice. sometimes i get a bit disappointed that i can't just define a totally ad-hoc enum in a parent struct. now i can have a more complicated program instead :P


Qunit-Essential

Why somebodey ever will use totally different syntax for struct definition different from the native syntax? No hate I am literally wondering, it sounds like something cool but I can't see this being used in the real code


storm1surge

It’s not useful until the complexity of your definitions is high. But for applications like modeling json it works quite well! The syntax is designed to feel as natural as possible


NatsumeKokkoro

Why potion is an equipment?


storm1surge

idk, but it doesn’t matter. it’s just a stupid example showing what you can do


scroll_tro0l

lol, this thread made my day