-
Notifications
You must be signed in to change notification settings - Fork 71
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
Add BorshSize trait #23
Comments
80% solution: pub fn borsh_len(value: &impl BorshSerialize) -> Result<usize> {
struct Writer {
len: usize,
}
impl Write for Writer {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.len += buf.len();
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
let mut w = Writer { len: 0 };
value.serialize(&mut w)?;
Ok(w.len)
} This won't do exactly what we want for types that use extra heap-allocated buffers for serilization, but my gut feeling is that that's rare. EDIT: didnt' resist the temptation to look at the asm, looks right for simple cases: 15:22:23|~/projects/borsh-rs|master⚡✚*
λ git diff --cached
diff --git a/borsh/examples/len.rs b/borsh/examples/len.rs
new file mode 100644
index 00000000..69b84a0c
--- /dev/null
+++ b/borsh/examples/len.rs
@@ -0,0 +1,17 @@
+#[derive(borsh::BorshSerialize)]
+pub struct Foo {
+ x: u8,
+ y: u32
+}
+
+#[no_mangle]
+#[inline(never)]
+pub fn size_of_foo(foo: &Foo) -> usize {
+ borsh::len(foo).unwrap_or_default()
+}
+
+fn main() {
+ let foo = Foo { x: 62, y: 92 };
+ let res = size_of_foo(&foo);
+ eprintln!("{}", res);
+}
diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs
index 51c81919..55088283 100644
--- a/borsh/src/lib.rs
+++ b/borsh/src/lib.rs
@@ -45,3 +45,23 @@ pub mod maybestd {
pub use hashbrown::hash_map::Entry;
}
}
+
+pub fn len(value: &impl BorshSerialize) -> std::io::Result<usize> {
+ struct Writer {
+ len: usize,
+ }
+ impl std::io::Write for Writer {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ self.len += buf.len();
+ Ok(buf.len())
+ }
+ #[inline]
+ fn flush(&mut self) -> std::io::Result<()> {
+ Ok(())
+ }
+ }
+ let mut w = Writer { len: 0 };
+ value.serialize(&mut w)?;
+ Ok(w.len)
+}
15:22:28|~/projects/borsh-rs|master⚡✚*
λ cargo build --example len --release -q
15:22:41|~/projects/borsh-rs|master⚡✚*
λ dis ./target/release/examples/len size_of_foo
Dump of assembler code for function size_of_foo:
0x0000000000011b70 <+0>: mov eax,0x5
0x0000000000011b75 <+5>: ret
End of assembler dump. |
And output for slightly more intersting #[derive(borsh::BorshSerialize)]
pub struct Foo {
x: u8,
y: u32,
zs: Vec<u32>,
} Dump of assembler code for function size_of_foo:
0x0000000000011be0 <+0>: mov rax,QWORD PTR [rdi+0x10]
0x0000000000011be4 <+4>: mov rcx,rax
0x0000000000011be7 <+7>: shr rcx,0x20
0x0000000000011beb <+11>: test rax,rax
0x0000000000011bee <+14>: lea rax,[rax*4+0x9]
0x0000000000011bf6 <+22>: mov edx,0x9
0x0000000000011bfb <+27>: cmovne rdx,rax
0x0000000000011bff <+31>: xor eax,eax
0x0000000000011c01 <+33>: test rcx,rcx
0x0000000000011c04 <+36>: cmove rax,rdx
0x0000000000011c08 <+40>: ret
End of assembler dump. |
What a trick :D |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Discussion started here: near/nearcore#4107 (comment)
The point is to wrap object' serialization and length computation in one method.
CC: @nearmax
The text was updated successfully, but these errors were encountered: