diff --git a/USAGE.md b/USAGE.md index ec9449a..e51260f 100644 --- a/USAGE.md +++ b/USAGE.md @@ -46,11 +46,9 @@ meta(t::Type{MyType}) = meta(t, [], [8,10], Dict()) ```` ## Setting and Getting Fields -Types used as protocol buffer structures are regular Julia types and the Julia syntax to set and get fields can be used on them. But with fields that are set as optional, it is quite likely that some of them may not have been present in the instance that was read. Similarly, fields that need to be sent need to be explicitly marked as being set. The following methods are exported to assist doing this: +Types used as protocol buffer structures are regular Julia types and the Julia syntax to set and get fields can be used on them. But with fields that are set as optional, it is quite likely that some of them may not have been present in the instance that was read. The following methods are exported to assist doing this: - `get_field(obj::Any, fld::Symbol)` : Gets `obj.fld` if it has been set. Throws an error otherwise. -- `set_field!(obj::Any, fld::Symbol, val)` : Sets `obj.fld = val` and marks the field as being set. The value would be written on the wire when `obj` is serialized. Fields can also be set the regular way, but then they must be marked as being set using the `fillset` method. -- `add_field!(obj::Any, fld::Symbol, val)` : Adds an element with value `val` to a repeated field `fld`. Essentially appends `val` to the array `obj.fld`. - `has_field(obj::Any, fld::Symbol)` : Checks whether field `fld` has been set in `obj`. - `clear(obj::Any, fld::Symbol)` : Marks field `fld` of `obj` as unset. - `clear(obj::Any)` : Marks all fields of `obj` as unset. @@ -63,14 +61,14 @@ Types generated through the Julia protoc plugin generates constructors that use ```` julia> using ProtoBuf -julia> mutable struct MyType # a Julia composite type +julia> mutable struct MyType <: ProtoType # a Julia composite type intval::Int # fillunset (documented below is similar to clear) # ProtoBuf._protobuild is an internal method similar to protobuild MyType(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o) end -julia> mutable struct OptType # and another one to contain it +julia> mutable struct OptType <: ProtoType # and another one to contain it opt::MyType OptType(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o) end @@ -102,11 +100,11 @@ julia> using ProtoBuf julia> import ProtoBuf.meta -julia> mutable struct TestType +julia> mutable struct TestType <: ProtoType val::Any end -julia> mutable struct TestFilled +julia> mutable struct TestFilled <: ProtoType fld1::TestType fld2::TestType TestFilled(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o) @@ -120,7 +118,7 @@ TestFilled(#undef,#undef) julia> isinitialized(tf) # false, since fld1 is not set false -julia> set_field!(tf, :fld1, TestType("")) +julia> tf.fld1 = TestType(""); julia> isinitialized(tf) # true, even though fld2 is not set yet true diff --git a/src/utils.jl b/src/utils.jl index f533a05..1ffe8e2 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,8 +2,8 @@ isinitialized(obj::Any) = isfilled(obj) -set_field!(obj::Any, fld::Symbol, val) = (setfield!(obj, fld, val); fillset(obj, fld); nothing) -@deprecate set_field(obj::Any, fld::Symbol, val) set_field!(obj, fld, val) +Base.setproperty!(obj::ProtoType, fld::Symbol, val) = (Core.setfield!(obj, fld, val); fillset(obj, fld); val) +@deprecate set_field!(obj::Any, fld::Symbol, val) setproperty!(obj, fld, val) get_field(obj::Any, fld::Symbol) = isfilled(obj, fld) ? getfield(obj, fld) : error("uninitialized field $fld") @@ -18,7 +18,7 @@ function copy!(to::T, from::T) where T <: ProtoType for idx in 1:length(fnames) if fill[1, idx] name = fnames[idx] - set_field!(to, name, getfield(from, name)) + setproperty!(to, name, getfield(from, name)) end end nothing @@ -44,7 +44,7 @@ protobuild(::Type{T}, nv::Dict{Symbol}=Dict{Symbol,Any}()) where {T} = _protobui function _protobuild(obj::T, nv) where T for (n,v) in nv fldtyp = fld_type(obj, n) - set_field!(obj, n, isa(v, fldtyp) ? v : convert(fldtyp, v)) + setproperty!(obj, n, isa(v, fldtyp) ? v : convert(fldtyp, v)) end obj end diff --git a/test/services/testsvc.jl b/test/services/testsvc.jl index 053a792..4e48338 100644 --- a/test/services/testsvc.jl +++ b/test/services/testsvc.jl @@ -23,7 +23,7 @@ mutable struct TestRpcChannel <: ProtoRpcChannel end close(channel::TestRpcChannel) = close(channel.sock) -mutable struct SvcHeader +mutable struct SvcHeader <: ProtoType method::String SvcHeader() = (o=new(); fillunset(o); o) end @@ -31,7 +31,7 @@ end function write_request(channel::TestRpcChannel, controller::TestRpcController, service::ServiceDescriptor, method::MethodDescriptor, request) io = channel.sock hdr = SvcHeader() - set_field!(hdr, :method, method.name) + hdr.method = method.name iob = IOBuffer() @@ -119,13 +119,13 @@ end # implementations of our test services function Add(req::BinaryOpReq) resp = BinaryOpResp() - set_field!(resp, :result, req.i1 + req.i2) + resp.result = req.i1 + req.i2 resp end function Mul(req::BinaryOpReq) resp = BinaryOpResp() - set_field!(resp, :result, req.i1 * req.i2) + resp.result = req.i1 * req.i2 resp end @@ -164,8 +164,8 @@ function run_client(debug::Bool) let channel=TestRpcChannel(connect(9999)), stub=TestMathBlockingStub(channel) for i in 1:10 inp = BinaryOpReq() - set_field!(inp, :i1, Int64(rand(Int8))) - set_field!(inp, :i2, Int64(rand(Int8))) + inp.i1 = Int64(rand(Int8)) + inp.i2 = Int64(rand(Int8)) out = Add(stub, controller, inp) chk_results(out, inp.i1+inp.i2) @@ -179,8 +179,8 @@ function run_client(debug::Bool) debug_log(controller, "testing non blocking stub...") for i in 1:10 inp = BinaryOpReq() - set_field!(inp, :i1, Int64(rand(Int8))) - set_field!(inp, :i2, Int64(rand(Int8))) + inp.i1 = Int64(rand(Int8)) + inp.i2 = Int64(rand(Int8)) nresults -= 1 let channel=TestRpcChannel(connect(9999)), stub=TestMathStub(channel), expected=inp.i1+inp.i2 diff --git a/test/services/testsvc_pb.jl b/test/services/testsvc_pb.jl index a33e26e..ba8089b 100644 --- a/test/services/testsvc_pb.jl +++ b/test/services/testsvc_pb.jl @@ -3,7 +3,7 @@ using ProtoBuf import ProtoBuf.meta import Base: hash, isequal, == -mutable struct BinaryOpReq +mutable struct BinaryOpReq <: ProtoType i1::Int64 i2::Int64 BinaryOpReq(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o) @@ -12,7 +12,7 @@ hash(v::BinaryOpReq) = ProtoBuf.protohash(v) isequal(v1::BinaryOpReq, v2::BinaryOpReq) = ProtoBuf.protoisequal(v1, v2) ==(v1::BinaryOpReq, v2::BinaryOpReq) = ProtoBuf.protoeq(v1, v2) -mutable struct BinaryOpResp +mutable struct BinaryOpResp <: ProtoType result::Int64 BinaryOpResp(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o) end #type BinaryOpResp diff --git a/test/testcodec.jl b/test/testcodec.jl index 523db6c..bd0faed 100644 --- a/test/testcodec.jl +++ b/test/testcodec.jl @@ -334,7 +334,7 @@ function test_nested() writeproto(pb, testval, meta) readfld2.iVal2 = Int64[] - readval.fld3 = TestType[] + readval.fld3 = TestStr[] readproto(pb, readval, meta) assert_equal(testval, readval) @@ -363,19 +363,19 @@ function test_oneofs() @test isfilled(testval, :iVal3) @test which_oneof(testval, :optval) === :iVal3 - set_field!(testval, :iVal2, 10) + testval.iVal2 = 10 @test isfilled(testval, :iVal1) @test isfilled(testval, :iVal2) @test !isfilled(testval, :iVal3) @test which_oneof(testval, :optval) === :iVal2 - set_field!(testval, :iVal1, 10) + testval.iVal1 = 10 @test isfilled(testval, :iVal1) @test isfilled(testval, :iVal2) @test !isfilled(testval, :iVal3) @test which_oneof(testval, :optval) === :iVal2 - set_field!(testval, :iVal3, 10) + testval.iVal3 = 10 @test isfilled(testval, :iVal1) @test !isfilled(testval, :iVal2) @test isfilled(testval, :iVal3) @@ -394,28 +394,28 @@ function test_maps() testval = TestMaps() readval = TestMaps() - set_field!(testval, :d1, Dict{Int,Int}()) + testval.d1 = Dict{Int,Int}() writeproto(pb, testval) readproto(pb, readval) @test !isfilled(readval, :d1) testval = TestMaps() readval = TestMaps() - set_field!(testval, :d2, Dict{Int32,String}()) + testval.d2 = Dict{Int32,String}() writeproto(pb, testval) readproto(pb, readval) @test !isfilled(readval, :d2) testval = TestMaps() readval = TestMaps() - set_field!(testval, :d3, Dict{String,String}()) + testval.d3 = Dict{String,String}() writeproto(pb, testval) readproto(pb, readval) @test !isfilled(readval, :d3) testval = TestMaps() readval = TestMaps() - set_field!(testval, :d1, Dict{Int,Int}()) + testval.d1 = Dict{Int,Int}() testval.d1[1] = 1 testval.d1[2] = 2 writeproto(pb, testval) @@ -425,7 +425,7 @@ function test_maps() testval = TestMaps() readval = TestMaps() - set_field!(testval, :d2, Dict{Int32,String}()) + testval.d2 = Dict{Int32,String}() testval.d2[Int32(1)] = convert(String, "One") testval.d2[Int32(2)] = convert(String, "Two") writeproto(pb, testval) @@ -435,7 +435,7 @@ function test_maps() testval = TestMaps() readval = TestMaps() - set_field!(testval, :d3, Dict{String,String}()) + testval.d3 = Dict{String,String}() testval.d3["1"] = "One" testval.d3["2"] = "Two" writeproto(pb, testval) diff --git a/test/testutilapi.jl b/test/testutilapi.jl index b3766cb..2bf55ef 100644 --- a/test/testutilapi.jl +++ b/test/testutilapi.jl @@ -5,7 +5,7 @@ import ProtoBuf.meta print_hdr(tname) = println("testing $tname...") -mutable struct TestType +mutable struct TestType <: ProtoType a::AbstractString b::Bool TestType() = (o=new(); fillunset(o); o) @@ -20,14 +20,12 @@ function test_apis() @test false == try get_field(t, :a); true; catch; false; end - set_field!(t, :b, true) + t.b = true @test has_field(t, :b) @test (get_field(t, :b) == true) @test !isinitialized(t) - t.a = "hello" - @test !isinitialized(t) - set_field!(t, :a, "hello world") + t.a = "hello world" @test isinitialized(t) @test (get_field(t, :a) == "hello world")