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

Struct fields numeric labels #160

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

gobwas
Copy link

@gobwas gobwas commented Jul 15, 2016

Hello!

This pull request is about this issue.

I think it could be useful. Some integration protocols use scheme, when map keys are numerical (int or uint), for example, to reduce network usage and other performance needs.

Regards,
Sergey.


This change is Reviewable

@gobwas
Copy link
Author

gobwas commented Jul 15, 2016

Also, I have a question about decision according to this thread.

If it is necessary to declare label types also as int32, int64, uint8 etc., that is, strong typed labels without dependency on a value, I could implement it.

@philhofer
Copy link
Member

Hey, thanks for the PR.

This is going to take me a day or two to review, since it's a substantial change.

Just for my own edification, could you point me to a place where this would be used 'in the wild?'

@philhofer
Copy link
Member

philhofer commented Jul 15, 2016

Also, can I suggest the following for syntax:

type Foo struct {
    Bar string `msg:0x03"
}

We should be able to disambiguate string field names from integer field names simply by the presence of quotes. I'd also make unsigned integers the default, and then make int(0x03) mean signed integers, since I'm imagining most use-cases will only use unsigned integers...?

gen/spec.go Outdated
case string:
t = msgp.StrType
default:
panic(fmt.Errorf("field %q has unknown tag type %T", f.FieldName, f.FieldTag))
Copy link
Member

Choose a reason for hiding this comment

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

Don't panic here; print an error and exit. Same goes for field label parsing.

Copy link
Author

Choose a reason for hiding this comment

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

There are already few cases when generator panics. For example, here. So is it really necessary to print error and do some of os.Exit(1)?

@gobwas
Copy link
Author

gobwas commented Jul 15, 2016

Hey @philhofer,

Yeah, I agree with syntax you suggested.

But my question above is still actual – should we take care on strong typed labels, like uint8?
For example, we could use uint by default, and then add ability to cast not only to signed int, but to any other type of int? How do you think?

About usage 'in the wild' I do not clearly understand your question. If this is about concrete use case – I need this to implement some binary protocol to integrate with. It is very much like, for example, this one.

@philhofer
Copy link
Member

I need this to implement some binary protocol to integrate with. It is very much like, for example, this one.

Great; I was just curious about who was serializing things this way already.

But my question above is still actual – should we take care on strong typed labels, like uint8?
For example, we could use uint by default, and then add ability to cast not only to signed int, but to any other type of int? How do you think?

Practically speaking, I'd imagine most things will end up being encoded as a 127-bit fixint anyway (and most everything else in one of the fixed-width unsigned types), so I don't think this is necessary, but I'm happy to be convinced otherwise.

@gobwas
Copy link
Author

gobwas commented Jul 22, 2016

Hello @philhofer!

Just returned to complete this feature. Please look what I have found about the use of field tag values without quotes: play.golang.org. That is, it is not possible to distinguish numeric label vs. string simply by presence of quoutes without breaking other tags cause it is violates "conventional format".
So I could suggest to use something like this (I decided that (uint)0x01 syntax is bad because of super low, but probability of shadowing user key):

type Foo struct {
    Bar string `msg:"0x03,uint"`
}

gen/spec.go Outdated
case string:
t = msgp.StrType
default:
panic(fmt.Sprintf(
Copy link
Author

@gobwas gobwas Jul 23, 2016

Choose a reason for hiding this comment

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

Will duplicate my previous comment to not loose it:

There are already few cases when generator panics. For example, here. So is it really necessary to print error and do some of os.Exit(1)?

If it is, I could move logging logic from parse package to separate package, e.g. internal/log, and reuse functions like warnf,warnln etc., and also refactor fatalf to print log message and do os.Exit(1).

Copy link
Member

Choose a reason for hiding this comment

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

That sounds great.

@gobwas
Copy link
Author

gobwas commented Jul 29, 2016

@philhofer ping 👀

parse/getast.go Outdated
var err error
switch tags[1] {
case "uint":
str, base := numeric(tags[0])
Copy link
Member

Choose a reason for hiding this comment

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

strconv.ParseInt(tags[0], 0, 64) will infer hex or octal based on the prefix; no need to do that yourself.

@gobwas
Copy link
Author

gobwas commented Aug 2, 2016

@philhofer thanks! Applied your comments, and moved logging logic to the internal/log package. I did not changed already written panic's to log.Fatal (except panic that I have wrote).

@gobwas
Copy link
Author

gobwas commented Aug 8, 2016

Hello @philhofer! Is it able to merge this? ) It becomes little bit uncomfortable to live with fork 😞

@gobwas
Copy link
Author

gobwas commented Sep 14, 2016

Ping @philhofer =)

@gobwas
Copy link
Author

gobwas commented Sep 14, 2016

I have also refactored code generation for maps – now you could marshal/unmarshal not only map[string]T.

@gobwas
Copy link
Author

gobwas commented Oct 17, 2016

@philhofer could you stop ignoring this? =)

@pwaller
Copy link
Contributor

pwaller commented Nov 11, 2016

FYI @gobwas, the tests failed (I'm not associated with this project, but just thought you might like to know):

--- FAIL: TestReadIntf (0.00s)
    read_test.go:63: map[thing-1:thing-1-value thing-2:800 thing-3:[115 111 109 101 32 105 110 110 101 114 32 98 121 116 101 115 46 46 46] thing-4:false] in; map[thing-4:false thing-1:thing-1-value thing-2:800 thing-3:[115 111 109 101 32 105 110 110 101 114 32 98 121 116 101 115 46 46 46]] out
FAIL
FAIL    github.com/tinylib/msgp/msgp    0.147s

@gobwas
Copy link
Author

gobwas commented Nov 19, 2016

@pwaller thanks =) Fixed.

@gobwas
Copy link
Author

gobwas commented Jan 19, 2017

@philhofer may be today? 🤣

* Add (*Reader).CopyNext(w) (int64, error)

It is useful to be able to efficiently copy objects without
decoding them.

My use case is filtering when I already know the indices of
the objects I want to keep, and for rewriting a dictionary
of objects as a column of objects.

* Remove ReadNext

* Add opportunistic optimization with m.R.Next

* Remove unused ReadNextError

* Remove commented code

* small fixup

- only call (*Reader).Next() when we're sure it won't realloc its buffer
- promote io.ErrUnexpectedEOF to msgp.ErrShortBytes
@potterdai
Copy link

@philhofer Wondering if this PR will still be merged?

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.

None yet

4 participants