diff --git a/src/ProtoBuf.jl b/src/ProtoBuf.jl index 0d73ed7..479f8d1 100644 --- a/src/ProtoBuf.jl +++ b/src/ProtoBuf.jl @@ -1,10 +1,10 @@ module ProtoBuf -import Base: show, copy!, hash, isequal, == +import Base: setproperty!, show, copy!, deepcopy, hash, isequal, == export writeproto, readproto, ProtoMeta, ProtoMetaAttribs, meta, protobuild export filled, isfilled, isfilled_default, which_oneof, fillset, fillset_default, fillunset -export show, copy!, set_field, set_field!, get_field, clear, add_field, add_field!, has_field, isinitialized +export setproperty!, show, copy!, deepcopy, set_field, set_field!, get_field, clear, add_field, add_field!, has_field, isinitialized export hash, isequal, == export ProtoEnum, ProtoType, lookup, enumstr export ProtoServiceException, ProtoRpcChannel, ProtoRpcController, MethodDescriptor, ServiceDescriptor, ProtoService, diff --git a/src/utils.jl b/src/utils.jl index 1ffe8e2..628ba3b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,7 +2,7 @@ isinitialized(obj::Any) = isfilled(obj) -Base.setproperty!(obj::ProtoType, fld::Symbol, val) = (Core.setfield!(obj, fld, val); fillset(obj, fld); val) +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") @@ -24,6 +24,20 @@ function copy!(to::T, from::T) where T <: ProtoType nothing end +function deepcopy(from::T) where T <: ProtoType + to = T() + fillunset(to) + fill = filled(from) + fnames = fld_names(T) + for idx in 1:length(fnames) + if fill[1, idx] + name = fnames[idx] + setproperty!(to, name, deepcopy(getfield(from, name))) + end + end + to +end + function add_field!(obj::Any, fld::Symbol, val) typ = typeof(obj) attrib = meta(typ).symdict[fld] diff --git a/test/testutilapi.jl b/test/testutilapi.jl index 2bf55ef..a05d090 100644 --- a/test/testutilapi.jl +++ b/test/testutilapi.jl @@ -38,8 +38,17 @@ function test_apis() @test t.a == "hello" @test t.b == false end + +function test_deepcopy() + ts = ProtoBuf.google.protobuf.Timestamp() + ts.seconds = 123 + @test !has_field(ts, :nanos) + ts2 = deepcopy(ts) + @test !has_field(ts2, :nanos) +end + end # module ProtoBufTestApis print_hdr("utility api methods") ProtoBufTestApis.test_apis() - +ProtoBufTestApis.test_deepcopy()