Skip to content
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

Extend formatters: implement boolean compression #65

Merged
merged 1 commit into from
Aug 7, 2020

Conversation

Lotterleben
Copy link
Contributor

resolves #29 .

happy to hear feedback esp. on the decoder changes, surely there's a more idiomatic way to do this.

as always, will squash before merging :)

@Lotterleben Lotterleben requested a review from japaric August 4, 2020 16:45
@Lotterleben Lotterleben changed the title Extend formatters 2 Extend formatters: implement boolean compression Aug 4, 2020
@jonas-schievink jonas-schievink self-assigned this Aug 5, 2020
Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
decoder/src/lib.rs Outdated Show resolved Hide resolved
macros/src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
@Lotterleben Lotterleben force-pushed the extend_formatters_2 branch from 056021c to 84504e1 Compare August 5, 2020 11:54
decoder/src/lib.rs Outdated Show resolved Hide resolved
decoder/src/lib.rs Outdated Show resolved Hide resolved
decoder/src/lib.rs Outdated Show resolved Hide resolved
decoder/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a rebase + squash, but after that go ahead and merge!

impl Format for bool {
fn format(&self, fmt: &mut Formatter) {
let t = internp!("{:bool}");
fmt.write(&[t, *self as u8]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, wait, does this actually work in the decoder? It seems like it wouldn't

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this doesn't decode properly:

    #[derive(Format)]
    struct Flags {
        a: bool,
        b: bool,
        c: bool,
    }

    binfmt::info!(
        "{:bool} {:?}",
        true,
        Flags {
            a: true,
            b: false,
            c: true
        }
    );
Error: couldn't decode all data (remaining: [a, c, 10, d])

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not sure if this is even using the Format impl, but something is going wrong somewhere 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup.. 😅 looking into how I can best attack this with a debugger now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to help:

Encoded data: [0x0A, 0x0C, 0x10, 0x0D]

  • 0x0A - string index of "{:bool} {:?}"
  • 0x0C - timestamp (10 µs)
  • 0x10 - string index of Flags generatead format string (should be "Flags {{ a: {:bool}, b: {:bool}, c: {:bool} }}")
  • 0x0D - 0b1101 - all 4 compressed bools

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decoder doesn't seem to handle this correctly. When it encounters the {:?} it recursively calls parse_args, but doesn't do any special handling for the bool decoding state. Maybe it just needs to be passed down, but I'm not sure yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the record/note for future us:
from what I've gathered stepping through the bools_bool_struct() test, empty_bool_indices is overwritten when parse_args()is recursively called to handle the {:?} that catches our struct, which messes up the whole compression scheme etc. The question is whether we want to compress such nested bools into one u8 or if that's opening a whole can of worms. Will be mulling this over now but I don't expect any useful results before tomorrow morning

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next note: if we don't compress bools in structs like we would any other "flat" arrangement of arguments, the spec is going to get pretty tangled: compressed bools may be split (for example in a bool struct{bool bool} bool situation) and you have to keep track of which compression u8s cover which levels. plus, you may lose compression.
plus– to implement this, we have to keep track of state during encoding, which adds expense in terms of computation and code size.

So, I'll see how I can make flat compression work in the decoder :D

@Lotterleben Lotterleben force-pushed the extend_formatters_2 branch from 4ade024 to 45327f9 Compare August 5, 2020 14:02
@jonas-schievink jonas-schievink removed their assignment Aug 5, 2020
@@ -18,6 +18,23 @@ fn main() -> ! {
binfmt::info!("Hello {1:u16} {0:u8} {:bool}", 42u8, 256u16, false);
binfmt::info!("🍕 {:[u8]}", [3,14]);

#[derive(Format)]
struct Flags {
a: bool,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self: debug output; delete

Copy link
Member

@japaric japaric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments regarding the spec; haven't looked at the code yet. Will do so later.

book/src/ser-bool.md Show resolved Hide resolved

``` rust
binfmt::error!("x: {:bool}, y: {:bool}, z: {:bool}", false, false, true);
// on the wire: [1, 0b100]
// on the wire: [1, 0b001]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the value be 0b100 to match the bzyx in the comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other way round– the xyz comment is outdated. fixing now

book/src/ser-bool.md Outdated Show resolved Hide resolved
}

binfmt::error!("x: {:bool}, {:?}", false, Flags { a: true, b: false });
// on the wire: [1, 2, 0b010,]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 to compressing the whole thing in a single byte.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately it's not as easy as I thought...

book/src/ser-bool.md Outdated Show resolved Hide resolved
@@ -66,6 +66,13 @@ impl Format for &[u8] {
}
}

impl Format for bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thread below talks about structs that contain bool. This Format impl is going to appear in generic types like Option<bool> formatted with {:?}. I think this implementation as it is is correct for those types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup but the de/encoding is broken for fmt strings that contain bools in- and outside of a struct because the compression may transcend those type barriers, but the handling in the de/encoder does not.

Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a rebase, but looks good to merge otherwise.

@Lotterleben
Copy link
Contributor Author

👍 waiting a bit in case @japaric has code comments

Copy link
Member

@japaric japaric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Feel free to squash and merge.

src/lib.rs Outdated
}

fn flush_and_reset_bools(&mut self) {
self.write(&[self.bool_flags]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can use self.u8(self.bool_flags) here

@Lotterleben Lotterleben force-pushed the extend_formatters_2 branch 2 times, most recently from fb16131 to 3bbf2b1 Compare August 7, 2020 09:26
- teach encoder how to serialze bools
- change bool order in compression bytes
- change position of compressed bool from first `{:bool}` to last `{:bool}`
- update docs
- add test for known struct format bug
@Lotterleben Lotterleben force-pushed the extend_formatters_2 branch from 3bbf2b1 to c5e0bc4 Compare August 7, 2020 09:32
@Lotterleben Lotterleben merged commit 7c0dba8 into main Aug 7, 2020
@Lotterleben Lotterleben deleted the extend_formatters_2 branch August 7, 2020 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

encode and format bools
3 participants