OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package flagpb | 5 package flagpb |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/hex" | 8 "encoding/hex" |
9 "fmt" | 9 "fmt" |
10 "strconv" | 10 "strconv" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 return nil, fmt.Errorf("a flag was expected") | 68 return nil, fmt.Errorf("a flag was expected") |
69 } | 69 } |
70 flagName := strings.TrimPrefix(firstArg, "-") // -foo | 70 flagName := strings.TrimPrefix(firstArg, "-") // -foo |
71 flagName = strings.TrimPrefix(flagName, "-") // --foo | 71 flagName = strings.TrimPrefix(flagName, "-") // --foo |
72 if strings.HasPrefix(flagName, "-") { | 72 if strings.HasPrefix(flagName, "-") { |
73 // Triple dash is too much. | 73 // Triple dash is too much. |
74 return nil, fmt.Errorf("bad flag syntax") | 74 return nil, fmt.Errorf("bad flag syntax") |
75 } | 75 } |
76 | 76 |
77 // Split key-value pair x=y. | 77 // Split key-value pair x=y. |
78 » flagName, value, hasValue := p.splitKeyValuePair(flagName) | 78 » flagName, valueStr, hasValueStr := p.splitKeyValuePair(flagName) |
79 if flagName == "" { | 79 if flagName == "" { |
80 return nil, fmt.Errorf("bad flag syntax") | 80 return nil, fmt.Errorf("bad flag syntax") |
81 } | 81 } |
82 | 82 |
83 // Split field path "a.b.c" and resolve field names. | 83 // Split field path "a.b.c" and resolve field names. |
84 fieldPath := strings.Split(flagName, ".") | 84 fieldPath := strings.Split(flagName, ".") |
85 pathMsgs, err := p.subMessages(root, fieldPath[:len(fieldPath)-1]) | 85 pathMsgs, err := p.subMessages(root, fieldPath[:len(fieldPath)-1]) |
86 if err != nil { | 86 if err != nil { |
87 return nil, err | 87 return nil, err |
88 } | 88 } |
89 | 89 |
90 » // Where to assign a value? | 90 » // Where to assign the value? |
91 target := &root | 91 target := &root |
92 if len(pathMsgs) > 0 { | 92 if len(pathMsgs) > 0 { |
93 lastMsg := pathMsgs[len(pathMsgs)-1] | 93 lastMsg := pathMsgs[len(pathMsgs)-1] |
94 target = &lastMsg.message | 94 target = &lastMsg.message |
95 } | 95 } |
96 | 96 |
97 // Resolve last field name. | 97 // Resolve last field name. |
98 name := fieldPath[len(fieldPath)-1] | 98 name := fieldPath[len(fieldPath)-1] |
99 fi := target.desc.FindField(name) | 99 fi := target.desc.FindField(name) |
100 if fi == -1 { | 100 if fi == -1 { |
101 return nil, fmt.Errorf("field %s not found in message %s", name,
target.desc.GetName()) | 101 return nil, fmt.Errorf("field %s not found in message %s", name,
target.desc.GetName()) |
102 } | 102 } |
103 field := target.desc.Field[fi] | 103 field := target.desc.Field[fi] |
104 | 104 |
105 » if !hasValue { | 105 » var value interface{} |
| 106 » hasValue := false |
| 107 |
| 108 » if !hasValueStr { |
106 switch { | 109 switch { |
107 // Boolean and repeated message fields may have no value and ign
ore | 110 // Boolean and repeated message fields may have no value and ign
ore |
108 // next argument. | 111 // next argument. |
109 case field.GetType() == descriptor.FieldDescriptorProto_TYPE_BOO
L: | 112 case field.GetType() == descriptor.FieldDescriptorProto_TYPE_BOO
L: |
110 » » » target.data[name] = true | 113 » » » value = true |
111 » » » return flags, nil | 114 » » » hasValue = true |
112 case field.GetType() == descriptor.FieldDescriptorProto_TYPE_MES
SAGE && field.Repeated(): | 115 case field.GetType() == descriptor.FieldDescriptorProto_TYPE_MES
SAGE && field.Repeated(): |
113 » » » target.data[name] = append(asSlice(target.data[name]), m
ap[string]interface{}{}) | 116 » » » value = map[string]interface{}{} |
114 » » » return flags, nil | 117 » » » hasValue = true |
115 | 118 |
116 // Read next argument as a value. | |
117 default: | 119 default: |
| 120 // Read next argument as a value. |
118 if len(flags) == 0 { | 121 if len(flags) == 0 { |
119 return nil, fmt.Errorf("value was expected") | 122 return nil, fmt.Errorf("value was expected") |
120 } | 123 } |
121 » » » value, flags = flags[0], flags[1:] | 124 » » » valueStr, flags = flags[0], flags[1:] |
122 } | 125 } |
123 } | 126 } |
124 | 127 |
125 // Check if the value is already set. | 128 // Check if the value is already set. |
126 if target.data[name] != nil && !field.Repeated() { | 129 if target.data[name] != nil && !field.Repeated() { |
127 repeatedFields := make([]string, 0, len(pathMsgs)) | 130 repeatedFields := make([]string, 0, len(pathMsgs)) |
128 for _, m := range pathMsgs { | 131 for _, m := range pathMsgs { |
129 if m.repeated { | 132 if m.repeated { |
130 repeatedFields = append(repeatedFields, "-"+stri
ngs.Join(m.path, ".")) | 133 repeatedFields = append(repeatedFields, "-"+stri
ngs.Join(m.path, ".")) |
131 } | 134 } |
132 } | 135 } |
133 if len(repeatedFields) == 0 { | 136 if len(repeatedFields) == 0 { |
134 return nil, fmt.Errorf("value is already set to %v", tar
get.data[name]) | 137 return nil, fmt.Errorf("value is already set to %v", tar
get.data[name]) |
135 } | 138 } |
136 return nil, fmt.Errorf( | 139 return nil, fmt.Errorf( |
137 "value is already set to %v. Did you forgot to insert %s
in between to declare a new repeated message?", | 140 "value is already set to %v. Did you forgot to insert %s
in between to declare a new repeated message?", |
138 target.data[name], strings.Join(repeatedFields, " or ")) | 141 target.data[name], strings.Join(repeatedFields, " or ")) |
139 } | 142 } |
140 | 143 |
141 » // Parse the value and set/append it. | 144 » if !hasValue { |
142 » parsedValue, err := p.parseFieldValue(value, target.desc.GetName(), fiel
d) | 145 » » value, err = p.parseFieldValue(valueStr, target.desc.GetName(),
field) |
143 » if err != nil { | 146 » » if err != nil { |
144 » » return nil, err | 147 » » » return nil, err |
| 148 » » } |
145 } | 149 } |
146 | 150 |
147 if !field.Repeated() { | 151 if !field.Repeated() { |
148 » » target.data[name] = parsedValue | 152 » » target.data[name] = value |
149 } else { | 153 } else { |
150 » » target.data[name] = append(asSlice(target.data[name]), parsedVal
ue) | 154 » » target.data[name] = append(asSlice(target.data[name]), value) |
151 } | 155 } |
| 156 |
152 return flags, nil | 157 return flags, nil |
153 } | 158 } |
154 | 159 |
155 type subMsg struct { | 160 type subMsg struct { |
156 message | 161 message |
157 path []string | 162 path []string |
158 repeated bool | 163 repeated bool |
159 } | 164 } |
160 | 165 |
161 // subMessages returns message field values at each component of the path. | 166 // subMessages returns message field values at each component of the path. |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 } | 328 } |
324 return enum.Value[i].GetNumber(), nil | 329 return enum.Value[i].GetNumber(), nil |
325 } | 330 } |
326 | 331 |
327 func asSlice(x interface{}) []interface{} { | 332 func asSlice(x interface{}) []interface{} { |
328 if x == nil { | 333 if x == nil { |
329 return nil | 334 return nil |
330 } | 335 } |
331 return x.([]interface{}) | 336 return x.([]interface{}) |
332 } | 337 } |
OLD | NEW |