How to modify the de/serialization in protobuf compiler output? - protocol-buffers

I want to introduce a different method of deserialization and serialization when generating to protobuf files.
In essence, after running protoc -I=/home/ubuntu/protobuf-3.21.6/src -I=./ --cpp_out=./ addressbook.proto from the examples I would want to generate custom uint8_t* Person_PhoneNumber::_InternalSerialize functions.
Those functions should change the serialization method on a condition like the size of the message itself.
Ideally I would want to keep the function signatures same and use something like protobuf plugins to achieve this. The key is for the additional functionality to be be included without changing the API.
What is the best way to extend the protobuf compiler without changing the source code?

Related

How can I enforce correct construction whilst respecting the golang CodeReviewComments rule on interfaces?

The Interfaces rule in the official Go Code Review Comments document says that packages should return concrete types rather than interfaces. The motivation for this is so that:
...new methods can be added to implementations without requiring extensive refactoring.
which I accept could be a good thing.
But what if a type I'm writing has a dependency without which it cannot serve its purpose? If I export the concrete type, developers will be able to instantiate instances without that dependency. To code defensively for the missing dependency, I then have to check for it in every method implementation and return errors if it is absent. If the developer missed any hints not to do this in my documentation, she or he won't learn about the problem until run time.
On the other hand, if I declare and return an interface with the methods the client needs, I can unexport the concrete type and enforce the use of a factory method which accepts the dependency as an argument and returns the interface plus an error. This seems like a better way to ensure correct use of the package.
Am I somehow not properly getting into the go spirit by thinking like this? Is the ethic of the language that it's okay to have a less-than-perfect encapsulation to give more flexibility to developers?
You may expect developers to read the doc you provide, and you may rely on them following the rules you set. Yes, lazy developers will bump their head from time to time, but the process of developing isn't without having to learn. Everything cannot be made explicit or enforced, and that's all right.
If you have an exported struct type Example and you provide a constructor function NewExample(), that's a clear indication that NewExample() should be used to construct values of Example. Anyone attempting to construct Example manually is expected to know what fields must be set for it to be "operational". The aim is always to make the zero value fully functional, but if that can't be achieved, the constructor function is the idiomatic way to go.
This isn't uncommon, there are countless examples in the standard library, e.g. http.Request, json.Encoder, json.Decoder, io.SectionReader, template.Template.
What you must ensure is that if your package returns values of your structs, they must (should) be properly initialized. And also if others are expected to pass values of your structs created by them, you must provide an easy way for them to create valid values of your structs (constructor function). Whether the custom struct values other developers create themselves are "valid", that shouldn't be of your concern.

How to open/view .proto file extension

I am working on an open-source project(https://github.com/google/science-journal/tree/master/OpenScienceJournal). With this application, I can record an experiment. Recorded experiments are stored with the .proto extension. I tried to compile them to generate classes but failed.
Is there any way to open this kind of files?
In protocol-buffers, .proto files are usually the text-based schema DSL that describes messages, not data; however, it is possible that these files do indeed contain the binary data instead (just... unusual). Double-check the files : if they look like:
message Foo {
int32 bar = 1;
// etc
}
then it is the schema; if it is binary-looking, it is probably data.
As to how to read it: the simplest option is to already have the schema. If you don't, the data is technically ambiguous - you can probably reverse-engineer it by examining the data, but it can be awkward. You may find tools such as https://protogen.marcgravell.com/decode useful for that purpose.
Once you have a schema and the data, you would:
generate the necessary stubs in your chosen platform from the schema (https://protogen.marcgravell.com/ may be useful here)
then: use the protbuf library's "deserialize" API for your chosen platform to load the data into an object model
finally: inspect the object model, now populated with the data

How to check if an object conforms to the schema of an interface in typescript?

I have an interface which has certain properties defined.
For example:
interface Student {
name: string;
dob:string;
age:number;
city:string;
}
I read a JSON file which contains a record in this format and assign it to a variable.
let s1:Student = require('./student.json');
Now, I want to verify if s1 contains all the properties mentioned in interface Student. At runtime this is not validated. Is there any way I can do this?
There is an option of type guards, but that won't serve the purpose here. I do not know which fields would come from the JSON file. I also cannot add a discriminator(No data manipulation);
Without explicitly writing code to do so, this isn't possible in TypeScript. Why? Because once it's gone through the compiler, your code looks like this:
let s1 = require('./student.json');
Everything relating to types gets erased once compilation completes, leaving you with just the pure JavaScript. TypeScript will never emit code to verify that the type checks will actually hold true at runtime - this is explicitly outside of the language's design goals.
So, unfortunately, if you want this functionality you're going to have to write if (s1.name), if (s1.dob), etc.
(That said, it is worth noting that there are third-party projects which aim to add runtime type checking to TypeScript, but they're still experimental and it's doubtful they'll every become part of the actual TypeScript language.)

Get names of structs that implement an interface or inherit a struct

Is it possible to get a slice of strings that represent the names of all types that implement an interface or inherit from a specific struct in a specific package using reflection?
After some research on the reflect package's doc, I don't think it's possible. That's not the way reflection work in go: the interfaces mechanism not beeing declarative (but duck-typed instead), there is no such list of types.
That said, you may have more luck using the ast package to parse your project, get the list of types, and check wheter or not they implement an interface, then write some code to give you the said slice. That would add a step to compilation, but could work like a charm.
AFAIK, you can't do this with reflect, since packages are kinda out of reflect's scope.
You can do this the same way godoc's static analysis works. That is, using code.google.com/p/go.tools/go/types to parse the package's source code and get the type info.
The go oracle can do this. https://godoc.org/code.google.com/p/go.tools/oracle
Here is the relevant section of the user manual.

How to import package by path from string in Go?

I have a string with name of package (like "my/package/test") and I wanna import that and call some function from package.
Something like this:
func init() {
var pkg string = "test/my/pkg"
import pkg
pkg.Test()
}
PS. Thanks for help
The Go language does not allow what you mentioned in your example. This is a conscious choice. In my opinion, the reason behind this choice has to do with compiler performance and ease of code understanding by the machine. This for example enables tools such as gofix that can partially fix Go code without need for user intervention.
It also enables a programmer to clearly see all of the statically imported packages used by the program.
See also the grammar rules for source file organization in the Go language specification.
In relation to dynamically loading packages at run-time: Go has no support for loading packages at run-time. A future Go run-time might implement this feature (for example, it is occasionally being requested in messages in the golang-nuts mailing list), but the current state is that there is no support for this feature.
That's not possible in Go. The linker has to know the dependencies at compile-time, your string (and the init-function) are however evaluated at run-time. Also note, that parts of your programs which are not used, i.e. everything which isn't referred explicitly, wont even be part of the final binary - so reflection is not possible either.
If you need something like that, you have to manage the mapping on your own. You can for example use a global map in one package and use the init functions in the other packages to register the relevant functions, by adding them to the map. After that, you can use the map to do your look-ups dynamically.
Take a look at the http package for example. In a fictional blog package you might use the blog.init() function to register a couple of http handlers using the http.HandleFunc(pattern, handler) function. The main package then might call http.ListenAndServe() which looks up the right handlers at run-time.

Resources