Hi, I’m trying to use ProtoBuf.jl to deserialize objects.
Managed to generate code from .proto files
Now I want to read and write objects with Protocol Buffer Text Format Language Specification.
However, I could only find usage for binary readproto/writeproto.
How can I use TextFormat?
Thanks!
drvi
2
Not ideal, but you should be able to convert the text format to binary with protoc
using the --encode
/--decode
flags, see this SO answer.
1 Like
Thanks!
I was able to build this solution:
using ProtoBuf
using protoc_jll
export protobuf_from_text, protobuf_to_text
# important: .proto files are required in runtime!
const _proj_path = normpath(joinpath(@__FILE__, "..", ".."))
const _proto_path = joinpath(_proj_path, "common")
const _plugin_dir = abspath(joinpath(dirname(pathof(ProtoBuf)), "..", "plugin"))
const _plugin = joinpath(_plugin_dir, Sys.iswindows() ? "protoc-gen-julia_win.bat" : "protoc-gen-julia")
const ENV_ = copy(ENV)
ENV_["PATH"] = string(_plugin_dir, Sys.iswindows() ? ";" : ":", ENV_["PATH"])
ENV_["JULIA"] = joinpath(Sys.BINDIR, Base.julia_exename())
function protobuf_from_text(input::String, proto_type::Type{T}, proto_file="default.proto") where {T <: ProtoType}
args = `--proto_path=$_proto_path --encode=mynamespace.$proto_type $proto_file`
protoc_jll.protoc() do protoc_path
inbuf = PipeBuffer()
write(inbuf, input)
outbuf = PipeBuffer()
run(pipeline(setenv(`$protoc_path --plugin=protoc-gen-julia=$_plugin $args`, ENV_); stdin=inbuf, stdout=outbuf))
return readproto(outbuf, proto_type())::T
end
end
function protobuf_to_text(input::T, proto_file="default.proto") where {T <: ProtoType}
proto_type = typeof(input)
args = `--proto_path=$_proto_path --decode=mynamespace.$proto_type $proto_file`
protoc_jll.protoc() do protoc_path
inbuf = PipeBuffer()
writeproto(inbuf, input)
outbuf = PipeBuffer()
run(pipeline(setenv(`$protoc_path --plugin=protoc-gen-julia=$_plugin $args`, ENV_); stdin=inbuf, stdout=outbuf))
return read(outbuf, String)
end
end
1 Like
Updated code for ProtoBuf.jl 1.0.0
# important: .proto files are required in runtime!
const _proj_path = normpath(joinpath(@__FILE__, "..", ".."))
const _proto_path = "some_path"
const ENV_ = copy(ENV)
ENV_["JULIA"] = joinpath(Sys.BINDIR, Base.julia_exename())
function protobuf_from_text(
input::String,
proto_type::Type{T},
proto_file = "my.proto"
) where {T}
proto_type_name = string(Base.typename(proto_type).wrapper)
args = `--proto_path=$_proto_path --encode=namespace.$proto_type_name $proto_file`
protoc_jll.protoc() do protoc_path
inbuf = PipeBuffer()
write(inbuf, input)
outbuf = PipeBuffer()
run(pipeline(setenv(`$protoc_path $args`, ENV_); stdin = inbuf, stdout = outbuf))
d = ProtoDecoder(outbuf)
return decode(d, proto_type)::T
end
end
function protobuf_to_text(input::T, proto_file = "my.proto") where {T}
proto_type = typeof(input)
proto_type_name = string(Base.typename(proto_type).wrapper)
args = `--proto_path=$_proto_path --decode=namespace.$proto_type_name $proto_file`
protoc_jll.protoc() do protoc_path
inbuf = PipeBuffer()
e = ProtoEncoder(inbuf)
encode(e, input)
outbuf = PipeBuffer()
run(pipeline(setenv(`$protoc_path $args`, ENV_); stdin = inbuf, stdout = outbuf))
return read(outbuf, String)
end
end