#Idea for better serialization framework

1 messages · Page 2 of 1

visual tartan
#

Do you srsly mean a parser which parses rust language?

fair acorn
#

yep

modern bone
#

No dependencies allowed, so she just copy-pasted their source in

restive ravine
#

more like "dawn was memeing about making a rust parser in a single file"

#

and wrote most of a lexer for it for the hell of it

fair acorn
#

does it work though

#

single file lexer would still be pretty cool

restive ravine
#

rustc_lexer is trivially single-filed tbh

fair acorn
#

we can force someone else to finish it /s

restive ravine
#

it's extremely simple

last furnace
#

How big would rustc in a single file be

modern jetty
#

cargo llvm-lines /hj

silver bolt
#

its not that bad

#

rust parsing doesnt seem too bad

#

i should attempt some time

fair acorn
#

treaty when

thorn badger
fair acorn
#

take a day off work to work on treaty? ferrisOwO

visual tartan
#

Lmao

#

I mean, it seems reasonably progressed (I only looked superficially tho)

last furnace
#

Step 1 of world domination is now complete

fair acorn
minor cobalt
thorn badger
#

I did go ahead and merge it

#

I will make sure to keep it when I manually merge it with my working branch

wintry path
visual tartan
#

Oh wow, you made it?

#

Awww test is yet to be updated

modern bone
silver bolt
#

guys its just a power of two number

red kettle
#

1000 more.

fair acorn
untold crane
#

aw tests are super broken rn cant test

#

lets see... sequences have regressed?

#

yep, and when they worked it's was super WIP. Looks like this needs some more time in the oven ^^

thorn badger
visual tartan
#

Please let me know when you update the tests!

open oriole
#

Any updates on this? @thorn badger

thorn badger
#

I had some issues with the code gen because of the async support, but I think that's all fixed now

open oriole
#

When will it be ready in a alpha state ig

visual tartan
#

.

#

Why is this in help forum

modern bone
#

It was a discussion/code review originally

visual tartan
#

Ahh

last furnace
thorn badger
visual tartan
#

Ahhh

thorn badger
#

This was actually sort of a continuation of a thread that was made during the serde binary incident

last furnace
#

what proportion of those involve using dungeon cell unnecessarily

thorn badger
#

I only use dungeon-cell style cursed code for 1 thing in treaty ferrisPlead

visual tartan
#

Gotta use more then, since it is going to need dark magic

thorn badger
last furnace
#

why

thorn badger
last furnace
#

why

#

wait

#

what the fuck?

visual tartan
thorn badger
#

For the protocol lookup system

#

Basically runtime trait lookup

visual tartan
#

Does type erasing helps?

thorn badger
#

But in a way that llvm makes not runtime

last furnace
#

are you recreating a better Any

visual tartan
#

Or do you mean just passing around type information

last furnace
visual tartan
thorn badger
# last furnace ogga booga?

One of my core ideas with treaty is when not using async (because it has issues out of scope) the serialization process is optimized almost perfectly

visual tartan
#

Runtime trait lookup but.. not runtime? Sounds like dark magic

thorn badger
#

As if treaty wasn't there

visual tartan
#

Ah, like optimization in specific case

thorn badger
#

Here let me get the inspiration for this system

south terrace
#

sometimes I think I know rust, and then I look at crates like treaty and reliaze I am only at the starting of a rabbit hole.

thorn badger
#

Which happens to be out of date in terms of the code it references

#

But the idea hasn't changed

last furnace
thorn badger
#

Which I use yandros' bijective traits to implement

last furnace
#

what what

#

bijective traits

thorn badger
#

Which allows proving uniqueness

#

Without unsafe

#

Where as in dungeon-cell the same construct needs unsafe

last furnace
#

I'm so confused

#

this is beautiful

modern bone
#

I think the issue with treaty is that you (and maybe yandros) will be the only one capable of maintaining it, because it will be so arcane

thorn badger
#

Yeah...

last furnace
#

is that not an issue for serde at all

modern bone
thorn badger
#

You know you peeps interrupted me in the middle of trying to solve for the non linear vector field of the look_at function in 3d graphics

last furnace
#

isn't that your fault for being on discord

thorn badger
#

I cannot be held accountable ferrisEvil

last furnace
#

what makes you think we can ferrisEvil

#

I for one am excited for your villian arc where in five years where treaty rules the rust ecosystem, to see you silently sneak a wasm intepreter into the crate

thorn badger
visual tartan
#

Hmm, wait Nonlinear vector field

#

ferrisballSweat what the

thorn badger
#

Technically I want the tensor

last furnace
thorn badger
#

Basically how the reference frame of a camera on a gimbal changes as it moves

last furnace
#

technically I am at work

visual tartan
#

Maybe you are dealing with some distorted space time?

thorn badger
#

Wait a second I have solved this before... it's the local tangent plane coordinates but with a different orientation

visual tartan
#

Ahh

dawn herald
#

it turns out LLVM (the optimizer) is able to see through this style of runtime reflection. As such, we still gain the benefits of IDETs but with more flexibility.

full hedge
#

@simple surge

#

Why is there a dude called silent* lmao

#

<@silent*>

silver bolt
#

to make this happen

open oriole
#

so real

#

:3

visual tartan
#

Argh, I was excited thinking there was some announcement by frog

modern jetty
#

how's this going then @thorn badger

whole berry
#

@thorn badger status update...?

#

last commit 2 weeks ago

thorn badger
#

It's that or not supporting async

modern bone
#

When would Send restrict sync code?

#

(you never did get back to me when you asked earlier ferrisBut)

thorn badger
modern bone
#

Are you deserializing Rc? Ig it would make sense in some cases, actually

thorn badger
#

Yeah the restriction would be for any type touching treaty's API

modern jetty
#

I might have asked this before, but what do you mean by "supporting async"

#

asynchronous deserialisation?

thorn badger
#

Or async writers

modern bone
#

I suppose that'd be neat, but how often would it actually be useful? The same argument could be made for Rc, I suppose, but async reader/writers seems like a niche optimization, not a required feature

thorn badger
#

And how it has to load the entire Json blob before deserialization

modern jetty
#

What's stopping async parsers requiring the values to be Send... or is this arcane magic?

thorn badger
modern bone
#

This entire thing is arcane magic

thorn badger
#

So it's either have the bound or not have async

#

I tried really hard to have both (no bound and async)

modern jetty
#

I'd say have the bound, but I do a load of tokio programming so I've never done async without a Send bound (and don't think it's a good idea anyway)

modern bone
#

I suppose this could also be an issue regarding tokio interop, but personally I've never seen a !Send value get deserialized so idk how common that is

thorn badger
#

Yeah that's my thought, is serializable/deserializable things should be sendable because you know they are being serialized

#

My worry is this will become a fundamental limitation of treaty

modern jetty
#

this is already a fundamental limitation of a lot of libraries, it's nothing special and easily explained

thorn badger
#

But treaty ferrisSob

modern bone
#

(not advocating that, just curious)

modern bone
#

So it's either sync is unrestricted, async is possible, or neither are clean?

thorn badger
#

Yeah

#

Oh also by supporting async I loose perfect code generation

#

But those cases were kind of rare in the first place so 🤷‍♂️

modern bone
#

Ooh, tipped the scales for me there, but I'm biased because I don't really use async anyways

thorn badger
modern jetty
#

serialisation/deserialisation is mostly done over IO boundaries, which should be asynchronous, so prioritising async (with Send, as that's what tokio needs) sounds sensible

thorn badger
#

Yeah that's what I'm leaning towards

modern bone
thorn badger
#

the other reason I haven't worked on it recently was at work it was crunch week to get deliverables ready

modern bone
#

I suppose you could detect token boundaries and spawn a task to deser the token itself, but in any case you need context

#

E.g. 123 could be an integer, a part of a string, part of an ident, part of a float

modern jetty
#

Ah, I understand what you are saying, but this is for data being fed into the parser right? This just sounds like a way to do a bit of deserialisation while waiting for the whole response and therefore reducing latency.

modern bone
#

Mmm, that's valid, though I can't see that being very noticable in the grand scheme of things

#

Especially if you start parsing a token, only to realize you don't have all the info yet and have to backtrack

modern jetty
#

This conversation isn't going to be very productive anymore because I have absolutely no clue what the API looks like and this is getting into specifics

modern bone
#

Fair

thorn badger
thorn badger
dawn herald
#

If only Tokio didn't make it impossible to be agnostic over async runtimes

woven roost
#

Interesting stuff! Would love to read a small write-up to get the big ideas across.

glacial terrace
modern bone
#

When crates rely on tokio::fs et. al., they are no longer independent of runtime

fair acorn
#

and also it looks like the main uring lib is tokio-uring so if you use that then have fun lmao

glacial terrace
dense oasis
#

Ye, the practical difficulties with defining a single universal Runtime trait don't really stop libraries from defining their own

visual tartan
#

Is async claiming another victim ferrisHmm

dawn herald
#

Yes, it is

last furnace
visual tartan
#

Low level asynchronous handling sounds like such a churn

full hedge
#

Wait until he tries to maintain both async and sync implementation

#

(I'm unexperienced. Don't mind me)

thorn badger
#

My week (really 2 weeks) of work is almost done ferrisOwO

open oriole
#

:3

thorn badger
#

So I can finally work on treaty more

open oriole
#

It optimizations seem solid tbh

#

musli ones :3

thorn badger
#

Like why can't I just use a csv decoder directly into a Json encoder ferrisSob

#

I should add modes to treaty

open oriole
#

but seemingly in a sane way

#

for optimization purposes :3

thorn badger
#

The double fat pointers are ...

open oriole
#

:3

thorn badger
#

Yeah

open oriole
open oriole
#

also first release when ;3

thorn badger
open oriole
#

nice :3

thorn badger
#

Right now I am just working out how I want the included protocols to be used to describe things like structs and enums

#

Like how a struct is the protocol sequence:

  • Empty tag of kind "Struct"
  • Tag of kind "Type Name": name string
  • Tag of kind "Type Id": TypeId
  • Tag of kind "Field Names": sequence of field names ...
  • sequence of fields
dawn herald
#

Ah fuck I was scrolled up lmfao

modern bone
modern jetty
#

you should def reserve that name @thorn badger

last furnace
#

yes

#

it's too important to be lost

modern bone
spring folio
south terrace
#

already stole it

#

||/j||

thorn badger
#

I did the thing

mellow thistle
#

omg

last furnace
modern jetty
#

omg treaty full release /j

full hedge
#

What was the difference between GitLab and GitHub that you choose the first?

thorn badger
#

And I prefer it's UI

#

Also gitlab actually got the name of merge requests right ferrisHotTake

thorn badger
#

I had one class use bitbucket because of that ferrisSorrow

full hedge
#

oh

#

how long ago was that?

thorn badger
#

2017 ish

#

Also gitlab's organization management is (or at least was) a million times better than GitHub's

#

Made my life as the software lead on a robotic club way nicer

#

Also I like that gitlab offers their software for free for self hosting

#

And that they manage the development of the free components using gitlab itself

full hedge
#

Is that aspect in GitLab and GitHub comparable, or it falls in the category of "Depends on what you personal taste is like"

thorn badger
minor cobalt
#

^

open oriole
#

@thorn badger Does Treaty steal borrow the optimizations that musli does?

#

oo this is cool

#

:3

thorn badger
dawn herald
#

"with the blazing performance." ferrisHmm

silver bolt
#

also, their benchmarks dont compare with rapidjson..... very sus

open oriole
thorn badger
#

I stole borrowed the mode system

modern bone
#

When will you return it ferrisHmm

modern jetty
#

keeping the thread alive lol

digital gazelle
#

quaint raft
high depot
#

drop(Box::from_raw(&self)) its over

#

jsiouh wu uh083uh@@@@@

sharp condor
rustic glade
#

all the code he writes is automatically wrapped in an unsafe block

silver bolt
#

i have a fork of rustc that forgets to check for safety of functions

silver bolt
#

no thats mrustc

#

that turns off the borrowck

modern bone
#

mrustc isn't a fork of rustc, it's its own thing ferrisHmm

silver bolt
#

mrustc still checks safety of functions

modern bone
#

But... they said your fork was crustc, you said no it's mrustc... I'm very confused

silver bolt
#

i was saying that the real crustc is called mrustc

modern bone
#

But... what they were calling crustc was a fork with no safety checks, while mrustc is not that

silver bolt
#

yes but like crustc implies that there isnt a borrowck

modern bone
#

But that's not what they said

#

(I love arguments about frivolous things ferrisClueless)

silver bolt
#

._ .

#

i just feel like crustc doesnt have the feel of a unsafe less safety check thing

thorn badger
#

Bump

visual tartan
#

Oh it alive

open oriole
#

Mrow

open oriole
thorn badger
#

After that should be good for a alpha

modern bone
sharp condor
wanton basin
open oriole
#

:3

last furnace
#

Poke

fair acorn
#

prod

wraith sequoia
#

So reading it over, there's a lot of catering to dyn. I'm not a dynamic-dispatch wizard yet, and I see it in a lot of larger libraries. Are the performance gains really that significant, or is it another reason, like ease of use for the client?

thorn badger
#

So there is no dynamic dispatch

last furnace
#

what's the cool link that explains this with a cool name

silver bolt
#

it has performance penaltys not gains

thorn badger
silver bolt
#

it has binary size gains

#

and here the compiler is all knowing

thorn badger
#

I'm currently fighting async block generation

#

If that gets solved then treaty can optimize to perfect code

#

Currently it optimizes to one stack frame that is like 300 bytes long

dawn herald
#

Oof

wraith sequoia
thorn badger
wraith sequoia
#

Too bad I don't know what the fucking significance of a HRTB is

thorn badger
wraith sequoia
#

You better tell me what those runes mean right now or you're getting burned at the stake for witchcraft

wraith sequoia
#

So what's the relationship between Builders, Walkers, Visitors and Effects?

thorn badger
#

So data flow is Walker -> Visitor

#

And almost all visitors are actually just builders

#

In serde land: Walker = Serialize/Deserializer, Builder = Serializer/Deserialize

#

In iterator land my_iter.for_each(|item| ...) the my_iter is the walker and the closure is the visitor

wraith sequoia
#

And so how do you plan for users to implement their own constructs (visitors, walkers)?

#

I see in some of your code visitors are functions that accept a DynVisitor<'ctx>

#

But I may have them misconstrued

thorn badger
thorn badger
thorn badger
wraith sequoia
#

I did notice that it fucked me up. I was like why are there two definitions of the same type

thorn badger
#

yeah 😅 the AnyTrait type erases all notion of what the real value is

#

it even erases what traits the value implements

thorn badger
#

walker: &mut dyn AnyTrait, visitor: &mut dyn AnyTrait

#

if you accidentally use one where the other is expected then weird things happen at runtime

wraith sequoia
#

Yeah, I'm sure. So the intention is that Builders construct the final value, but most of the time Visitors can also be Builders?

thorn badger
#

from an idea perspective builders add the build() function to the idea of a visitor

dawn herald
#

Finally got around to bookmarking the current URL for this project's repo lmao

silver bolt
#

what is a ! derive

visual tartan
silver bolt
#

i see

thorn badger
next tundra
#

Meow

wraith sequoia
#

Where is AnyTrait defined?

wraith sequoia
#

I know it has something to do with higher_ranked_type!, but I don't think I fully understand the nature of TypeName and its members. What are they facilitating?

thorn badger
#

The higher_ranked_type macro gives a bijection between a 'static type and a non-'static type mod the lifetimes it contains

#

Which allows for the safe transmutation (downcasting) based on the TypeId of the 'static associated type

wraith sequoia
thorn badger
thorn badger
wraith sequoia
#

Thank you sm :3

thorn badger
#

Just formalized differently

thorn badger
wraith sequoia
#

Most of my questions are really just centered around what you've already wrote. I want to get a better understanding of this code not only to improve my Rust abilities, but because I want to really understand how to harness DIDETs for the future.

#

I've actually learned a few things reading so far. I think the thing I still wonder is what part of this will apply to Readers and Writers

next tundra
#

Wtf is a DIDET yall need to chill with the acronyms

#

RPITIT was enough

thorn badger
next tundra
#

The what what what what what

thorn badger
#

Or the W5 for short

next tundra
#

WxW

thorn badger
next tundra
#

w3w

#

Gives me “k8s is just k9” vibes

last furnace
next tundra
#

I wish to know but I just got acronym jokes instead of an explanation :(

last furnace
#

There’s a good link explaining it somewhere

thorn badger
last furnace
#

Basically you just use dyn stuff in such a way rustc can devirtusise it

thorn badger
#

The dynamic part at the first is my addition

#

Which removes the big trait of extensions

last furnace
#

On an unrelated note I’m still trying to hunt down and ban the author of dungeoncell from adding crates to crates.io

#

Does anyone know where I can find them

next tundra
#

What they do

thorn badger
thorn badger
last furnace
thorn badger
last furnace
#

Someone once told me their name rhymes with dog

next tundra
thorn badger
#

I do need to report that OOM at some point

next tundra
thorn badger
last furnace
#

Forgetting to tell anyone about an Out of Memory error

thorn badger
next tundra
#

OooOoOOm

#

Do we have

#

-linux

#

-gnu

thorn badger
#

Every time I opened neovim the system went ... dead

next tundra
#

Damn

next tundra
thorn badger
next tundra
#

Get moar ram that you otherwise would have had to get with VSC*de

thorn badger
next tundra
#

What’s your cpu? (Also damn that’s a lot of data)

thorn badger
last furnace
thorn badger
next tundra
#

Wtf how can I not find a max ram spec on that shit nvm, joke ruined

next tundra
#

-tag

#

:(

#

-guthib

zealous frigateBOT
dawn herald
wraith sequoia
south terrace
fair acorn
fair acorn
#

unreadable on my phone though

thorn badger
thorn badger
fair acorn
thorn badger
fair acorn
#

ah rip

#

dont imagine theres a way to be generic over lifetimes while being useful for that?

thorn badger
#

Not really

#

You would need a lot more powerful type system

wraith sequoia
thorn badger
#

That's what AnyTrait was called before

south terrace
#

or do you only support certain traits

thorn badger
fair acorn
#

fair enough

thorn badger
#

Treaty is still very much in the experimental stage of pushing rust to the limit

fair acorn
#

btw hows async lowering going

thorn badger
thorn badger
fair acorn
#

nice!

thorn badger
#

It still surprises me that llvm is able to see through all of this and optimize everything away

thorn badger
#

Which also does allow it to expose some traits based on runtime state but I don't currently use that

dawn herald
#

@thorn badger ferrisballSweat

wraith sequoia
#

This crate has taught me if I want optimizations from LLVM I should use match everywhere

thorn badger
dawn herald
#

What in the unholy Hells even happened there

thorn badger
#

I'm not sure

dawn herald
#

How did you make rustc consume 32 GB of RAM in 10 seconds?

thorn badger
#

I did something bad with GATS

thorn badger
whole berry
#

I wonder how cranelift would handle this

last furnace
#

It might fail to see all the way through

whole berry
#

I doubt it would but I'd like to know how far it gets

#

Since it's opts is just "simple" IR rewriting

#

From what I've read

last furnace
#

I’d definitely suspect simple ir rewriting would be terrible at devirtualising

#

Could be a fun thing to find out

next tundra
#

Just pop on an impl Trait for &dyn Trait if that’s not already a thing

thorn badger
next tundra
#

Wouldn't it be the same just uh, different return type? Or do you want the trait to be object safe?

thorn badger
next tundra
#

I don't know what AnyTrait is or what the structure of treaty is

#

So uh yeah I have no idea

thorn badger
next tundra
#

Lifetime skill issue?

whole berry
#

progress update?

fair acorn
silver bolt
whole berry
#

effect system ferrisThonk

modern bone
#

"tests compile" is always a good sign ferrisBut

thorn badger
whole berry
visual tartan
#

Introducing some system to handle async vs. sync sounds like pain

thorn badger
#

It is painful

wraith sequoia
thorn badger
#

Basically what async was before edition 2018

dense oasis
thorn badger
dense oasis
#

So, exactly like how async blocks work, neat

thorn badger
dense oasis
#

In fact, that's also how async closures work. The returned future can borrow the arguments, but its output can't

thorn badger
#

The upside of this system is it doesn't cause the buildup of mutable borrows when using only synchronous code that happens when using async blocks everywhere

#

Because async blocks are their own types they can't be optimized away usually

thorn badger
fair acorn
sharp condor
whole berry
#

what are plans for first party parsers?

#

I'd like to see a first party json parser at minimum since while JSON isn't great it's by far the most universal

thorn badger
#

for the alpha I probably wont have any first class formats

#

or well I may have a demo one for RSV (and maybe SML and/or WSV)

whole berry
#

RSV?

thorn badger
whole berry
#

neat

thorn badger
whole berry
#

The main reason I would want to use this is to try to get rid of serde but I'll take a compat layer until it gets fleshed out

thorn badger
#

Im currently finishing up how structs are defined with the protocols, and next I need to do enums

thorn badger
#

maybe

full orbit
#

And how much overhead would the wrapper add?

thorn badger
#

At alpha it's unlikely treaty will have a convincing "use this over serde" for the average user. Except for maybe untagged enums which treaty has better handling of

thorn badger
thorn badger
#

Still need to finish the enum representation

full orbit
thorn badger
# full orbit and what this aim to achieve in later versions when its more mature (other then ...

The main aspects are:

  • it allows formats basically unlimited freedom (toml can have its date/time be first class, xml can have attributes and namespaces, yaml can have cyclic references, ...),
  • it provides full support for untagged and flattened types (instead of serde's half working hacks),
  • it allows Value to custom type and back directly (no more extra Serializer and Deserializer),
  • it allows async serialization sinks and deserializtion sources (so Json over http can be done on the stream instead of loading it all then doing it),
  • provides modes, which allows types to change their behavior when used with treaty (think using camelCase for xml and snake_case for Json, or leaving out fields when sending a http response but having them when talking to your database)
full orbit
thorn badger
#

Getting async was one of the hardest parts

#

That's why the effects system now exists

full orbit
#

tbh its really a good thing that you created treaty with serde support in mind... serde is too big and used in rust ecosystem to be replaced anytime soon...

thorn badger
#

Yeah I don't expect someone to convert their whole codebase over to treaty, it's unlikely treaty will ever actually make serde go away if it becomes popular (still a big if)

#

I may have all the pieces of this worked out, but we don't know if it will result in a cohesive whole when put together

#

I also want to implement functional lenses with treaty but that's a stretch goal

thorn badger
last furnace
#

frog has a long chunk of cursed code he was posting about

#

to try and get the async stuff working

thorn badger
#

I only broke rustc like 3 times with it

#

(and rust analyzer still doesn't understand it)

full orbit
thorn badger
#

Yep ferrisOwO

modern jetty
#

it's not like serde is hard to modify, it's that the developer doesn't accept PRs

#

lol

last furnace
modern jetty
thorn badger
last furnace
#

maybe I should abandon this metaphor

full orbit
# thorn badger I only broke rustc like 3 times with it

Now that you mentioned async
if I remember correctly treaty aimed to support both sync and async... how are you doing that and keeping the sync and async implementation in "sync"? I mean I seen so many libraries struggle with having both sync and async...

last furnace
#

frog show the effects system show the effects system

thorn badger
last furnace
#

worthwhile

thorn badger
full orbit
modern jetty
#

no codegen, just generics

thorn badger
last furnace
modern jetty
#

:3

last furnace
#

this bullet in my foot is just a rock

full orbit
thorn badger
# full orbit how exactly are you doing code generation magic? <:ferrisHmm:857440844171575326>
fn new_walk<'a: 'c, 'b: 'c, 'c>(
    &'a mut self,
    visitor: DynVisitor<'b, 'ctx>,
) -> ErasedEffective<'c, Status, E> {
    // Reset the errors to default state.
    self.error = None;

    // Reset the field index to the default.
    self.index = 0;

    E::as_ctx((self, visitor), |(this, visitor)| {
        visit_request_hint::<E>(visitor.cast(), DynWalker(*this))
            .map(VisitResult::unit_skipped)
            .cast()
    })
    .if_not_finished(|(this, visitor)| {
        visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.value))
            .map(VisitResult::unit_skipped)
            .cast()
    })
    .if_not_finished(|(this, visitor)| {
        visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
            TagConst,
            visitor.cast(),
            ValueWalker::new(TypeId::of::<I::T>()),
        )
        .map(|result| this.record_tag_error(result).unit_skipped())
        .cast()
    })
    .if_not_finished(|(this, visitor)| {
        visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>(
            TagConst,
            visitor.cast(),
            NoopWalker::new(),
        )
        .map(|result| this.record_tag_error(result).unit_skipped())
        .cast()
    })
    .if_skipped(|(this, visitor)| {
        visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(
            TagConst,
            visitor.cast(),
            NoopWalker::new(),
        )
        .map(|result| this.record_tag_error(result).unit_skipped())
        .cast()
    })
    .if_not_finished(|(this, visitor)| {
        visit_sequence::<E>(visitor.cast(), *this)
            .map(VisitResult::unit_skipped)
            .cast()
    })
    .remove_ctx()
    .map(VisitResult::to_status)
}
#

there are 6 yield points here

last furnace
#

boom boom cat boom boom cat if_not_finished if_not_finished if_not_finished

last furnace
#

also how does this work at all

thorn badger
#

want to see the function that makes this all work?

#
fn r#do<
    'ctx: 'lt,
    'wrap,
    Pre,
    Ctx,
    Owned,
    First,
    FirstOutput,
    FirstPost,
    Done,
    Extra,
    Repeat,
    RepeatOutput,
    RepeatPost,
    Post,
    Return,
>(
    self,
    pre: Pre,
    first: First,
    first_post: FirstPost,
    repeat: Repeat,
    repeat_post: RepeatPost,
    post: Post,
) -> ErasedEffective<'wrap, Return, Self::Effect>
where
    Pre: Ss + FnOnce(Self::Output) -> (Ctx, ControlFlow<Done, Owned>),
    First: Ss
        + for<'temp> FnOnce(
            &'temp mut Ctx,
            Owned,
        )
            -> ErasedEffective<'temp, FirstOutput, Self::Effect, &'wrap ()>,
    FirstPost: Ss + for<'temp> FnOnce(&'temp mut Ctx, FirstOutput) -> ControlFlow<Done, Extra>,
    Repeat: Ss
        + for<'temp> FnMut(
            &'temp mut Ctx,
            &'temp mut Extra,
        )
            -> ErasedEffective<'temp, RepeatOutput, Self::Effect, &'wrap ()>,
    RepeatPost: Ss
        + for<'temp> FnMut(&'temp mut Ctx, &'temp mut Extra, RepeatOutput) -> ControlFlow<Done>,
    Post: Ss + FnOnce(Ctx, Option<Extra>, Done) -> Return,
    Return: Ss,
    RepeatOutput: Ss,
    FirstOutput: Ss,
    'lt: 'wrap;
#

thats the signature

last furnace
#

how does this work at all again

#

I don't understand how this is possible

thorn badger
full orbit
thorn badger
#

I havent ran into any other issues so far

modern jetty
last furnace
#

hopefully

thorn badger
modern jetty
thorn badger
#

the function just abstracts the notion of borrowing a value while in a loop

#

thats all it does

#
let (ctx, done, extra) = match pre(self.0) {
    (mut ctx, ControlFlow::Continue(owned)) => {
        let first_output = first(&mut ctx, owned).0;

        let (done, extra) = match first_post(&mut ctx, first_output) {
            ControlFlow::Continue(mut extra) => loop {
                let repeat_output = repeat(&mut ctx, &mut extra).0;

                match repeat_post(&mut ctx, &mut extra, repeat_output) {
                    ControlFlow::Continue(()) => {}
                    ControlFlow::Break(done) => break (done, Some(extra)),
                }
            },
            ControlFlow::Break(done) => (done, None),
        };

        (ctx, done, extra)
    }
    (ctx, ControlFlow::Break(done)) => (ctx, done, None),
};

Value(post(ctx, extra, done), Default::default())

is the sync impl

thorn badger
#

now the compilation times...

#

no comment

full orbit
thorn badger
thorn badger
last furnace
#

rustfmt not built for the normal usecase of having 13 generic arguments and approximately 15 million where clauses

thorn badger
#

this reminds me I haven't actually moved the async context to this new do function yet

#

I should do that

modern jetty
#

honestly who needs async syntax and compiler support

#

if_not_finished

thorn badger
# full orbit if this is the signature Im scared of the function itself on a unrelated not you...
fn then<'wrap, U, F>(self, f: F) -> ErasedEffective<'wrap, U, Self::Effect>
where
    F: FnOnce(Self::Output) -> ErasedEffective<'wrap, U, Self::Effect>,
    U: Ss,
    F: Ss,
    'lt: 'wrap,
{
    self.r#do(
        |v| ((), ControlFlow::Continue(v)),
        |_, v| f(v).cast(),
        |_, v| ControlFlow::<_, Never>::Break(v),
        |_, _| unreachable!(),
        |_, _, _: Never| unreachable!(),
        |_, _, v| v,
    )
}

here is the Future::then function written in the effects system with the do operator

modern jetty
#

frog will just do it for you

last furnace
#

did you have to call it do

thorn badger
last furnace
#

based

thorn badger
last furnace
#

fair

#

I won't point out the obvious implication of what that says about you calling it

full orbit
thorn badger
# modern jetty if_not_finished
fn if_not_finished<'ctx, 'wrap, Ctx, F>(
    self,
    f: F,
) -> ErasedEffective<'wrap, (Ctx, VisitResult<()>), Self::Effect>
where
    Self: Effective<'lt, Output = (Ctx, VisitResult<()>)>,
    F: for<'temp> FnOnce(
        &'temp mut Ctx,
    )
        -> ErasedEffective<'temp, VisitResult<()>, Self::Effect, &'ctx ()>,
    'ctx: 'lt,
    Ctx: Ss,
    F: Ss,
    'lt: 'wrap,
{
    self.r#do(
        |(ctx, v)| {
            (
                ctx,
                match v {
                    VisitResult::Skipped(()) | VisitResult::Control(Flow::Continue) => {
                        ControlFlow::Continue(())
                    }
                    v => ControlFlow::Break(v),
                },
            )
        },
        |ctx, ()| f(ctx).cast(),
        |_, v| ControlFlow::<_, Never>::Break(v),
        |_, _| unreachable!(),
        |_, _, _: Never| unreachable!(),
        |ctx, _, v| (ctx, v),
    )
}
last furnace
#

somedays I wake up feeling Effective but other days I wake up feeling ErasedEffective

thorn badger
#

literally every Future adapter can be written with r#do (minus join which I separate out)

last furnace
#

that's kinda amazing

#

can we have a Frog Thoughts post about a simplier example of how this mixing async and sync works

thorn mantle
#

what i am curious about is when one would want an async serializer 🤔

thorn badger
#

or well thats the other way

#

but in treaty both the serialize and deserialize are the same operation

thorn mantle
#

so like deserializing a body as it comes in?

thorn badger
thorn mantle
#

yeah ok

full orbit
thorn badger
#

treaty doesn't have serde's (in my opinion wrong) distinction between serialization and deserialization

thorn badger
#

otherwise the async support wouldn't mean anything because it wouldn't work with tokio and other multithreaded runtimes

full orbit
last furnace
#

like how can you not have that distinction

thorn badger
last furnace
#

hmm

thorn badger
#

mapping it to serde its Deserializer/Serialize = Walker, Deserialize/Serializer = Builder

thorn badger
# full orbit how it work both side?

so when serializing a value to json we walk the Rust value and build a sequence of text that is the json value, when we deserialize a json strict to a Rust value we iterate over the json string and build the rust value

#

in reality formats are the same thing as any other data type

#

for example serde_json's Value type

#

which you can serialize into and deserialize from

thorn mantle
#

so treaty would let you convert between 2 rust values automatically right?

thorn badger
#
pub fn transform<'a, 'ctx: 'a, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>(
    seed: B::Seed,
    walker: W,
) -> ErasedEffective<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> {
    B::from_seed(seed)
        .as_ctx(|builder| walker.walk(builder.as_visitor()).cast())
        .then(|(builder, walker_result)| {
            builder
                .build()
                .map(|builder_result| (builder_result, walker_result))
        })
}

this operation allows doing things like converting one struct into another, and json to toml

#

along with struct to json, and json to struct

#

This was one of the foundational ideas of treaty I designed in from looking at discussions around serde

#

We simplify the API surface to 1 abstraction instead of 2

#

the abstraction being getting data in format A into format B where A and B don't know about each other beforehand

full orbit
#

so on the ground treaty should perform much faster in both serialize and deserialize then serde?

thorn badger
forest osprey
#

you're taking the "everything is a file" approach to another level:
"everything is a data format, including rust data types"

thorn badger
#

I haven't been able to benchmark against serde yet as I don't have enough types for it to be a fair comparison

thorn badger
#

hence the name treaty, format A and B work together to find what protocols they know about to allow passing data from A to B

#

What we define to allow this to work is a flow for what to try in what order

thorn badger
#

I do admit this makes writing a maximally compatible serialize/deserializer challenging compared to serde's data model

full orbit
#

it would be nice to see some benchmark when possible...
btw one unrelated question
serde for example doesn't use const generic and because of that it can only (de)serialize lists with a fixed size that are already are predefined in code (just because [T; 0] I think)...
does treaty also like this?

thorn badger
#
impl<'ctx, E: Effect> Value<'ctx, OwnedStatic<bool>, E> for Builder<E> {
    fn visit<'a>(
        &'a mut self,
        OwnedStatic(value): OwnedStatic<bool>,
    ) -> ErasedEffective<'a, VisitResult<OwnedStatic<bool>>, E>
    where
        'ctx: 'a,
    {
        self.0 = Some(value);
        E::ready(Flow::Done.into())
    }
}

here is an example from the code as it is now showing how a bool value is transferred to a builder

last furnace
#

so now all you need is a big chunk of examples to convince people away from serde

thorn badger
thorn badger
full orbit
thorn badger
#

I also have ones like pub struct BorrowedStatic<'ctx, T: ?Sized>(pub &'ctx T);

last furnace
#

scary

#

that's kinda cool

thorn badger
#

The past few months have been "is all this possible without compromising one of the other main features"

thorn badger
#

and at this point the answer is yes

thorn badger
#

I refrained from going with more than one context lifetime

#

so a type like

pub Demo<'a, 'b> {
  a: &'a str,
  b: &'b str,
}

isn't going to be supported (assuming we dont use Demo<'a, 'a>)

full orbit
thorn badger
#

If I could pass around lifetime like I do types then it would be possible, but alas we cant

thorn badger
#

it really depends on how much free time I end up with after work

last furnace
#

that's pog

thorn badger
#

and probably a descent into madness post about the effects system since a lot of people have wanted me to do that

full orbit
thorn badger
last furnace
#

lol

thorn badger
#

Also it would be very bad to promise all these things and then I never actually tested they work together ferrisballSweat (hence the last few months of convincing rustc its ok)

last furnace
#

me when treaty releases

thorn badger
#

Oh also I had a goal of minimal unsafe, which I think I have accomplished. I only need unsafe in 1 spot (2 depending on how you count it)

#

and thats for the lifetime containing downcasting

#

because I already have to worry about the higher ranked soundness hole, worrying about a treaty sized block of unsafe code would be ferrisballSweat

thorn mantle
#

miri catches it when hrtb fucks up right?

thorn badger
#

I think I have made it unlikely for a user to accidentally cause it with treaty's API, but im also not 100% sure how I would even quantify that in practice

#

Like I have never managed to do it by accident so far even though its very close to the examples

thorn badger
#

and to my knowledge we have no static analysis tools to check for the soundness hole

thorn badger
#

I am 95% sure thats the only spot that uses unsafe

#

If I do that I would probably also spin off the const symbols

next tundra
#

rg unsafe

last furnace
thorn badger
#

and probably the effects

full orbit
thorn badger
#

but we can do that after the alpha

next tundra
#

betterer any

sharp condor
full orbit
thorn badger
thorn badger
#

and the giant lookup table makes me smile every time

last furnace
#

oh this is just arithemetic coding

#

lol

thorn mantle
thorn badger
last furnace
#

why not

#

are these just ratios

thorn mantle
#

Const limitations?

thorn badger
last furnace
#

oh lol

full orbit
thorn badger
#

because the whole string has to fit into the space of 2 utf32 chars

#

also I once again dislike that we can't use strings for const generics

last furnace
#

yeah

#

kinda sucks

full orbit
full orbit
thorn badger
#

also mine allows a few more characters than his (assuming you don't use a custom alphabet)

full orbit
thorn badger
#

The goal was to allow most "programming" terms/names

#

sam's crate uses a fixed width encoding

full orbit
thorn badger
#

So if crate A uses ConstTag<{ Symbol::new("My Name").to_int() }> and crate B also uses that then they are the same

#

this is used by treaty's tag protocol to add meta information

#

This is to allow for some external source to define a new tag and crates don't have to depend on one definition crate to use it

full orbit
#

oh ok, I haven't seen much of treaty Tag system so Im not sure how it works, but this seem interesting

thorn badger
#

this tells the builder the walker has a struct to send it

#
visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
    TagConst,
    visitor.cast(),
    ValueWalker::new(TypeId::of::<I::T>()),
)

here is one with a value

full orbit
#

so tag are used by visitor to know which walker to use for it?

thorn badger
#

they are also used for things like keys in a map

#

the key is a tag

#
visit_tag::<tags::Key, E, _>(TagConst, visitor.cast(), key_walker)
#

so for a map/struct it does

visit map/struct tag
for field:
  visit key tag
    visit key value
  visit field value
full orbit
#

got it
the overall system is so complex ngl, but how it work all together is so interesting

#

does serde have something similar to treaty tags?

thorn badger
#

yep, I am probably going to need to make some diagrams to help people understand how the flows work

thorn badger
#

what people usually do instead in serde is magic field names

#

even serde does this internally

thorn badger
full orbit
modern bone
#

So in the process of trying to develop my own lib, the main problem I found myself running into is nesting structures. For example, if you want to serialize an array as a field, that array needs to ask the object collector for a list collector. Is this where IDETs come in to treaty, to allow you to try and treat a given Visitor in a certain way?

thorn badger
# modern bone So in the process of trying to develop my own lib, the main problem I found myse...

In treaty this specific form is done here ```rs
pub fn visit_sequence<'a, 'ctx, E: Effect>(
visitor: DynVisitor<'a, 'ctx>,
scope: DynSequenceScope<'a, 'ctx, E>,
) -> ErasedEffective<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> {
if let Some(object) = visitor.0.upcast_mut::<SequenceProto<E>>() {
// Allow the visitor to walk the sequence scope.
object.visit(scope)
} else {
// If the visitor doesn't support sequence then we continue.
VisitResult::Skipped(scope).ready()
}
}

#

DynSequenceScope here is basically Iterator

#
pub trait SequenceScope<'ctx, E: Effect> {
    fn size_hint(&mut self) -> ErasedEffective<'_, (usize, Option<usize>), E>;

    fn next<'a: 'c, 'b: 'c, 'c>(
        &'a mut self,
        visitor: DynVisitor<'b, 'ctx>,
    ) -> ErasedEffective<'c, Flow, E>
    where
        'ctx: 'c + 'a + 'b;
}
#

the visitor.0.upcast_mut::<SequenceProto<E>>() is where the DIDET is

thorn badger
modern bone
#

Interesting

last furnace
#

we must fuel frog

thorn badger
visual tartan
#

If so, I see.

#

Effect system has connotation of handling all sorts of things ime

thorn badger
#

so not the programming theory effects

visual tartan
#

Yeah

#

Would be sucky to implement..

#

Borrow checker will hate that

thorn mantle
#

will you have an effect for coroutines

thorn badger
#

thats it

#

technically you probably could get coroutines to work out

#

I don't think the do function forbids them

#

you know the do function probably allows quite a few effects now that I think about it ...

#

I already have fallibility

last furnace
thorn badger
#

const is definitely not one of them

#

and I have repetition...

#

great I have a full alternative to conrad's effective apparently ferrisSorrow

last furnace
#

That moment when you accidentally write a full effects system when all you want to do is serialise json

thorn badger
#

The thought: what if it was like javascript promises before async await
The outcome: full effects system

thorn mantle
#

surely someday rust will have its own effects system ferrisCluelesser

last furnace
visual tartan
thorn badger
visual tartan
#

Why and how

thorn badger
visual tartan
thorn badger
thorn badger
#

welcome to my effects system in stable rust

visual tartan
#

Devil magic

#

What happened to result in this monstrosity?

thorn badger
visual tartan
#

I mean

#

How did this monstrosity come to being

thorn badger
#

ah

visual tartan
#

FirstPost RepeatPost ferrisballSweat

thorn badger
visual tartan
#

Is it doing event handling here?

thorn badger
visual tartan
#

Wha, how

thorn badger
#

in async mode ErasedEffective becomes a Box<dyn Future>

visual tartan
#

So do you handle the difference of sync/async with some kind of event handling logic?

#

I bet everything as future could have been easier ferrisBut

thorn badger
#

in my system you write everything as blocking code

#

and when its about to yield the scope ends

visual tartan
thorn badger
visual tartan
#

Like, blocking code is fundamentally different from nonblocking code, right

visual tartan
thorn badger
visual tartan
#

Oh so you wrote entire async framework ferrisballSweat

thorn badger
thorn badger
visual tartan
#

Yeah but still

thorn badger
#

all based on one function

#

namely r#do

visual tartan
#

You are converting some blocking-lookalike-code automatically into nonblocking one

#

Devil magic really

thorn badger
# visual tartan Oh so you wrote entire async framework <:ferrisballSweat:678714352450142239>
E::as_ctx((self, visitor), |(this, visitor)| {
    visit_request_hint::<E>(visitor.cast(), DynWalker(*this))
        .map(VisitResult::unit_skipped)
        .cast()
})
.if_not_finished(|(this, visitor)| {
    visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.value))
        .map(VisitResult::unit_skipped)
        .cast()
})
.if_not_finished(|(this, visitor)| {
    visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
        TagConst,
        visitor.cast(),
        ValueWalker::new(TypeId::of::<I::T>()),
    )
    .map(|result| this.record_tag_error(result).unit_skipped())
    .cast()
})
.if_not_finished(|(this, visitor)| {
    visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>(
        TagConst,
        visitor.cast(),
        NoopWalker::new(),
    )
    .map(|result| this.record_tag_error(result).unit_skipped())
    .cast()
})
.if_skipped(|(this, visitor)| {
    visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(
        TagConst,
        visitor.cast(),
        NoopWalker::new(),
    )
    .map(|result| this.record_tag_error(result).unit_skipped())
    .cast()
})
.if_not_finished(|(this, visitor)| {
    visit_sequence::<E>(visitor.cast(), *this)
        .map(VisitResult::unit_skipped)
        .cast()
})
.remove_ctx()
.map(VisitResult::to_status)

here is some "async" code ferrisCluelesser

last furnace
#

Ctfl f “await” 0 results found

#

Funky

#

Hopefully we’ll get plenty of Frog Thoughts about however the fuck this works

visual tartan
#

I am having difficulty how this chains

thorn badger
#

fun thing is this works in the before async time

visual tartan
#

Parens are hard

thorn badger
#

and I wrote the stupid thing

visual tartan
#

There does seem to be tons of workers doing stuff

#

And maps, no idea what they do

visual tartan
thorn badger
#

its how pieces talk to eachother

visual tartan
#

So it's not going to be exposed?

thorn badger
visual tartan
#

Ah

last furnace
#

Or even a weird format like json

thorn badger
#

like handling a graph

visual tartan
#

Can it parse XML

last furnace
#

you'd still have to write an xml parser ferrisHmm

visual tartan
#

F

spring folio
thorn badger
#

But maybe

spring folio
#

rustfmt may unexplode if you do that xd

#

also i see you have a lot of unreachable!()s, I may do a mr where i just inline the shit out of the do's (by hand.)

#

also is there a derive yet? (if there isnt i can write one)

thorn badger
spring folio
#

oh

thorn badger
spring folio
#

I know derives so once i can i will do a merge req

thorn badger
#

Which is what I plan on having for the alpha

thorn badger
#

Just no guarantees I will accept it as is

spring folio
#

absolutely expected, i dont even know what you're aiming for for the syntax

#

if you can tell me any ideas that would be 👍

thorn badger
# spring folio oh

Having each context implement each adapter was extremely painful and didn't allow for easy custom adapters

spring folio
#

#[inline(always)] ferrisClueless

thorn badger
#

Yep

#

It's slightly sad that llvm messes up eventually as it starts running out of virtual registers when inlining so has to stop some of its optimizations

#

So instead of perfect code gen you get a few extra branches

spring folio
#

inline asm

thorn badger
#

No unsafe

spring folio
#

frog: perfect codegen
also frog: no unsafe

#

wait no you can do a feature flag with inline mir

#

naming idea: rename .r#do to .magic or .explode (||JOKE||)

visual tartan
silver bolt
#

eh idk

silver bolt
silver bolt
silver bolt
#

inline mir isnt very good either

spring folio
#

yeah its platform specific (=pain)

silver bolt
#

thats not the problem

#

the problem is that this code works with functions

#

inline asm doesnt fix function inlining

spring folio
#

oh yes

full orbit
thorn badger
visual tartan
#

Ah thats good to hear

quaint raft
#

frog has achieved maximum job security

#

there can't be many people capable of that much Rust black magic

digital gazelle
#

Wondering how much of a size difference it will make versus serde (and miniserde)

thorn badger
#
enum X {
    A(f32),
    B(bool),
}

let mut builder = X::new_builder();

// Use the recoverable flow.
{
    let mut scope = MockRecoverableScopeVisitor::<Blocking>::new();

    // The first builder for a f32 won't work.
    // In a real walker the scope would always walk the same.
    scope.expect_new_walk().once().return_const(Status::Ok);

    // The second builder will work.
    scope.expect_new_walk().once().returning(|visitor| {
        // The value for the B variant.
        visitor.visit_value_and_done(OwnedStatic(true));

        Status::Ok
    });

    // Visit a recoverable scope the enum builder can use to try and find
    // a variant that can be built.
    assert_eq!(
        visit_recoverable(builder.as_visitor(), &mut scope).value(),
        Flow::Done.into()
    );
}

// The enum should have a value now.
assert_eq!(builder.build().value().unwrap(), X::B(true));

Untagged enums work ferrisOwO (it tries each variant's builder until one works)

last furnace
#

woh

thorn badger
#
let mut builder = X::new_builder();

assert_eq!(
    visit_tag::<tags::Variant, Blocking, _>(
        TagConst,
        builder.as_visitor(),
        ValueWalker::new(0u32),
    )
    .value()
    .unwrap(),
    Flow::Done.into()
);

builder
    .as_visitor()
    .visit_value_and_done(OwnedStatic(1.23f32));

assert_eq!(builder.build().value().unwrap(), X::A(1.23));

Giving a tag also works now

#
fn guess_variant<'a>(
    _seed: Self::Seed,
    scope: DynRecoverableScope<'a, 'ctx, E>,
) -> ErasedEffective<'a, Result<Self::T, Self::Error>, E> {
    E::as_ctx(scope, |scope| {
        <<f32 as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default())
            .map(|builder| (scope, builder))
            .as_ctx(|(scope, builder)| scope.new_walk(builder.as_visitor()).cast())
            .then(|((_, builder), result)| builder.build())
            .map(|result| result.map(X::A))
            .cast()
    })
    .as_ctx(|(scope, result)| {
        <<bool as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default())
            .map(|builder| (scope, builder))
            .as_ctx(|(scope, builder)| scope.new_walk(builder.as_visitor()).cast())
            .then(|((_, builder), result)| builder.build())
            .map(|result| result.map(X::B))
            .cast()
    })
    .map(|((scope, _), result)| match result {
        Ok(value) => Ok(value),
        Err(err) => todo!("{}", err),
    })
}

the internals of the guessing hurts my soul

full orbit
nimble dawn
#

I just read about half of this thread and my head is spinning

dense oasis
#

The internals are, uh, complicated. My understanding is that the surface API is less incomprehensible

#

Or at least, will be, when it comes out.

nimble dawn
#

from what I've read there is some fascinating (and horrifying) stuff in the internals

#

the async/sync effect abstraction in particular looks quite interesting

silver bolt
#

also that unwrap written with match is funny

whole berry
whole berry
dense oasis
#

We have it, it's expect("todo")

thorn mantle
#

that doesn't get caught by warn(clippy::todos) tho

visual tartan
#

Tbh I expect the internals to be rather messy, as you have to go around typesystem

#

Otherwise it is like, rather, chain of

impl TryFrom<A> for SomeKnownFoo
impl TryFrom<SomeKnownFoo> for B

or sth

thorn badger
#

I think this quote is going to describe treaty's docs very well

I am going to give what I will call an elementary demonstration. But elementary does not mean easy to understand. Elementary means that very little is required to know ahead of time in order to understand it, except to have an infinite amount of intelligence. --Richard Feynman

visual tartan
#

I recall that it goes through some kind of translation to known types (which could be optimized out)

wraith sequoia
modern jetty
#

reminder that you are gonna have to get a less than 60 line example, because 99% of users are looking for ```rs
#[derive(serde::Deserialize)]
struct User {
name: String,
email: String,
}

let user: User = serde_json::from_str("...").expect("json deserialization failed");```

last furnace
dense oasis
thorn badger
#

On a serious note I am wondering if I should put my extension methods for walkers and builders into one trait

#

Maybe I can use a super trait with both of them as children ferrisThink

#

As ctx I have some extension traits that provide the "normal" API

modern jetty
#

I think having two traits will be confusing, and follow Iterator's example here.

thorn badger
#

It's kind of more like the Future trait and FutureExt

#

I guess I could squish everything into truly one trait ferrisThink the bounds would be super weird though

visual tartan
#

I don't think it's like Iterator

red kettle
#

so that there's a one-stop-shop

#

however, Iterator only does this because all Iterators are logically quite similar.

#

it sounds like walking and building are quite possibly very different

red kettle
open oriole
#

:3

open oriole
#

How the progress on this btw

digital gazelle
#

you can't rush perfection

austere saddle
#

just took a look at the sources

#

I wish I could understand it

#

One day I will

#

but not today

mellow thistle
sharp condor
wraith sequoia
#

Me af

sharp condor
wraith sequoia
#

ME. AS. FUCK

sharp condor
south terrace
#

@thorn badger will you ever create a blog on the theory behind any.rs? because its making my head hurt to understand it, and i do not want to learn type theory to understand a single file of code.

thorn badger
#

I haven't yet

thorn badger
#

#rust-discussions-1 message

visual tartan
wraith sequoia
full orbit
thorn badger
wraith sequoia
# thorn badger Yes

So does each value get visited with a different protocol by a different Walk implementation, or does a Walker only receive one DynVisitor that it reuses

thorn badger
thorn badger
#

If the visitor doesn't want to hint anything then the walker proceeds as normal driving the visitor

#

Also Walk exists to assign a canonical Walker to a type (same for Build)

#

the core API of treaty doesn't actually care that Walk is a thing, it's used for the derive default and helper methods

wraith sequoia
#

Okay, very good to know

#

So does every visitor have the opportunity to provide a hint? As in every protocol, in technicality, can carry two protocols?

thorn badger
#

The hint protocol takes any* other protocol

wraith sequoia
#

So protocols are composable?

thorn badger
#

Yep

#

Though hint is the only one I have that uses this

wraith sequoia
#

How do you compose them?

thorn badger
#

This is an application of treaty's lack of a given data model and protocol set, all the base crate gives are some well agreed upon protocols (abstractions of serde and other crate's abilities)

#

The base protocols being, Value, Tag, Sequence, Recoverable, and Hint (also RequestHint)

#

For two parties (walker and visitor) to communicate what we lay out are flows for how they should negotiate data transfer between themselves using some set of protocols in some order

#

So if a given walker or visitor doesn't respect a specific flow then they are incompatible (at runtime) but that's what we give up in order for the massive flexibility and extendability

#

Serde suffers from the same issue but doesn't really acknowledge it

#

For example attempting to deserialize a untagged enum from bincode

#

In treaty this case still doesn't work, but it's considered a case of neither party having enough information to do a successful data transfer

dense oasis
#

Honestly I can't complain, treaty does enough that I can put up with an unlikely runtime error that I already put up with in serde 😄

thorn badger
thorn badger
#

But I'm considering this out of scope for treaty

wraith sequoia
#

Would it be weird of me to make a dumbed down reimplementation of treaty's concepts?

thorn badger
#

I'm sure the same concepts could be applied in a much simpler form

#

My self imposed requirements are quite limiting on the simplicity I can achieve

#

Basically toss out async generics and lifetime containing types and everything becomes much easier

wraith sequoia
#

Speaking of, why are the protocols implemented as free functions?

modern bone
#

That's what I've been trying to do, but without all the runtime negotiation (partially because it's not comptime, but mostly because i'm not smart enough)

austere saddle
#

what do I need to learn to understand hkt.rs and any.rs(TypeName)? Type theory?

thorn badger
thorn badger