-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Codec
s composable
#18
base: main
Are you sure you want to change the base?
Conversation
Codec
trait to make codecs composableCodec
s composable
(I ended up also adding the one-liner for this) |
* Replace `const CODE` with * `fn to_code` * `fn try_from_code`
Generally spoken, the design goal of this library is that it works for real world use cases. I haven't thought about the use case of having an enum of codecs, but I can see the point of it. To me this change looks good and I agree that the performance hit is negligible. @Stebalien do you have any thoughts on this? |
Yeah, this makes a lot of sense. |
/// The error that is returned if encoding or decoding fails. | ||
type Error; | ||
|
||
/// The multicodec code of the IPLD codec. | ||
fn to_code(&self) -> u64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd just call this code()
.
src/codec.rs
Outdated
fn to_code(&self) -> u64; | ||
/// Attempt to convert from a `u64` code to this `Codec`. | ||
fn try_from_code(code: u64) -> Option<Self> where Self: Sized; | ||
|
||
/// Decode a reader into the desired type. | ||
fn decode<R: BufRead>(reader: R) -> Result<T, Self::Error>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume these now need to take &self
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, this is going to become a "by value" instead of a "by type" trait.
@@ -45,7 +43,7 @@ fn main() { | |||
age: 91, | |||
}; | |||
|
|||
let cbor_encoded = encode_generic(DagCborCodec, &tree); | |||
let cbor_encoded = encode_generic::<DagCborCodec, Tree>(DagCborCodec, &tree); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised this was necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably not; it's having a hard time picking up the codec in the doctests and I'm troubleshooting. Because this spans multiple repos I need to push to git, so I've flipped the PR to Draft
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this spans multiple repos
Multiple repos with a dependency cycle, even (on the dev-dependencies
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I know that it's not required because in the library that I'm actually working on I now actually need fewer type annotations. For example:
//Before
let bytes = <DagCborCodec as Codec<Ipld>>::encode_to_vec(dag).unwrap();
// After
let bytes = DagCborCodec.encode_to_vec(dag).unwrap();
@vmx I'm happy to update the
serde_ipld_*
instances (which are all currently broken in the test suite), but I wanted to at least propose this change in case there was some reason to not do it.Note that the tests will currently fail because they pull in downstream libs (e.g.
serde_ipld_dagcbor
) which would need to be updated, so there's a bit of a chicken and egg situation.Rationale
From the docs:
I've been through this exact design loop in one of my own library modules that plugged holes in
libipld
in many of the same ways thatipld-core
does. Essentially, if the goal is to make codecs composable (e.g. "I support both DAG-CBOR and DAG-JSON and want to model that as 'a codec'"), thenconst CODE
doesn't let these stack because it requires runtime information.Proposal
I propose (per this PR) that
Codec
uses afn
instead of aconst
to make this dynamic.It's entirely possible that I'm interpreting this line incorrectly, but I've run into this in one of my libraries that I'm switching from
libipld
toipld-core
ahead of IPFS Camp.Another Option
Changing from
const CODE: u64
tofn code(&self) -> u64
may have a (very minor) performance implication (assuming that the compiler can't elide this on simple instances). Another option would be to have something like the following......which gives you the ability to restrict to the static variant, but this feels like an over optimisation to me.
from_code
I also have uses for a
from_code
as well. Right now I'm hacking it in withTryFrom<u64>
, butu64
and a codec are isomorphic. I see no reason to not put it right onCodec
, but you will know much more about the overall design philosophy foripld-core
:)