aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/util/simple_reflection.cpp
blob: 913a01102820048820e1faa011647ba7124ad119 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "simple_reflection.h"

namespace NProtoBuf {
    const Message* GetMessageHelper(const TConstField& curField, bool) { 
        return curField.HasValue() && curField.IsMessage() ? curField.Get<Message>() : nullptr; 
    } 

    Message* GetMessageHelper(TMutableField& curField, bool createPath) { 
        if (curField.IsMessage()) { 
            if (!curField.HasValue()) { 
                if (createPath) 
                    return curField.Field()->is_repeated() ? curField.AddMessage() : curField.MutableMessage(); 
            } else { 
                return curField.MutableMessage(); 
            } 
        }
        return nullptr; 
    }

    template <class TField, class TMsg> 
    TMaybe<TField> ByPathImpl(TMsg& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { 
        if (fieldsPath.empty()) 
            return TMaybe<TField>();
        TMsg* curParent = &msg; 
        for (size_t i = 0, size = fieldsPath.size(); i < size; ++i) { 
            const FieldDescriptor* field = fieldsPath[i]; 
            if (!curParent) 
                return TMaybe<TField>(); 
            TField curField(*curParent, field); 
            if (size - i == 1) // last element in path 
                return curField; 
            curParent = GetMessageHelper(curField, createPath); 
        } 
        if (curParent) 
            return TField(*curParent, fieldsPath.back()); 
        else 
            return TMaybe<TField>(); 
    }

    TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TVector<const FieldDescriptor*>& fieldsPath) { 
        return ByPathImpl<TConstField, const Message>(msg, fieldsPath, false); 
    } 

    TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TStringBuf& path) { 
        TFieldPath fieldPath; 
        if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) 
            return TMaybe<TConstField>(); 
        return ByPathImpl<TConstField, const Message>(msg, fieldPath.Fields(), false); 
    } 

    TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TFieldPath& path) { 
        return ByPathImpl<TConstField, const Message>(msg, path.Fields(), false); 
    } 

    TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { 
        return ByPathImpl<TMutableField, Message>(msg, fieldsPath, createPath); 
    } 

    TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TStringBuf& path, bool createPath) { 
        TFieldPath fieldPath; 
        if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) 
            return TMaybe<TMutableField>(); 
        return ByPathImpl<TMutableField, Message>(msg, fieldPath.Fields(), createPath); 
    } 

    TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TFieldPath& path, bool createPath) { 
        return ByPathImpl<TMutableField, Message>(msg, path.Fields(), createPath); 
    } 
 
}