1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "action.hpp"
19 #include "and_action.hpp"
20 #include "chassis.hpp"
21 #include "compare_presence_action.hpp"
22 #include "compare_vpd_action.hpp"
23 #include "configuration.hpp"
24 #include "device.hpp"
25 #include "i2c_capture_bytes_action.hpp"
26 #include "i2c_compare_bit_action.hpp"
27 #include "i2c_compare_byte_action.hpp"
28 #include "i2c_compare_bytes_action.hpp"
29 #include "i2c_interface.hpp"
30 #include "i2c_write_bit_action.hpp"
31 #include "i2c_write_byte_action.hpp"
32 #include "i2c_write_bytes_action.hpp"
33 #include "if_action.hpp"
34 #include "log_phase_fault_action.hpp"
35 #include "not_action.hpp"
36 #include "or_action.hpp"
37 #include "phase_fault.hpp"
38 #include "phase_fault_detection.hpp"
39 #include "pmbus_read_sensor_action.hpp"
40 #include "pmbus_write_vout_command_action.hpp"
41 #include "presence_detection.hpp"
42 #include "rail.hpp"
43 #include "rule.hpp"
44 #include "run_rule_action.hpp"
45 #include "sensor_monitoring.hpp"
46 #include "sensors.hpp"
47 #include "set_device_action.hpp"
48 
49 #include <nlohmann/json.hpp>
50 
51 #include <cstdint>
52 #include <filesystem>
53 #include <memory>
54 #include <stdexcept>
55 #include <string>
56 #include <tuple>
57 #include <vector>
58 
59 namespace phosphor::power::regulators::config_file_parser
60 {
61 
62 /**
63  * Parses the specified JSON configuration file.
64  *
65  * Returns the corresponding C++ Rule and Chassis objects.
66  *
67  * Throws a ConfigFileParserError if an error occurs.
68  *
69  * @param pathName configuration file path name
70  * @return tuple containing vectors of Rule and Chassis objects
71  */
72 std::tuple<std::vector<std::unique_ptr<Rule>>,
73            std::vector<std::unique_ptr<Chassis>>>
74     parse(const std::filesystem::path& pathName);
75 
76 /*
77  * Internal implementation details for parse()
78  */
79 namespace internal
80 {
81 
82 /**
83  * Returns the specified property of the specified JSON element.
84  *
85  * Throws an invalid_argument exception if the property does not exist.
86  *
87  * @param element JSON element
88  * @param property property name
89  */
90 #pragma GCC diagnostic push
91 #pragma GCC diagnostic ignored "-Wdangling-reference"
92 inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element,
93                                                  const std::string& property)
94 {
95     auto it = element.find(property);
96     if (it == element.end())
97     {
98         throw std::invalid_argument{"Required property missing: " + property};
99     }
100     return *it;
101 }
102 #pragma GCC diagnostic pop
103 
104 /**
105  * Parses a JSON element containing an action.
106  *
107  * Returns the corresponding C++ Action object.
108  *
109  * Throws an exception if parsing fails.
110  *
111  * @param element JSON element
112  * @return Action object
113  */
114 std::unique_ptr<Action> parseAction(const nlohmann::json& element);
115 
116 /**
117  * Parses a JSON element containing an array of actions.
118  *
119  * Returns the corresponding C++ Action objects.
120  *
121  * Throws an exception if parsing fails.
122  *
123  * @param element JSON element
124  * @return vector of Action objects
125  */
126 std::vector<std::unique_ptr<Action>>
127     parseActionArray(const nlohmann::json& element);
128 
129 /**
130  * Parses a JSON element containing an and action.
131  *
132  * Returns the corresponding C++ AndAction object.
133  *
134  * Throws an exception if parsing fails.
135  *
136  * @param element JSON element
137  * @return AndAction object
138  */
139 std::unique_ptr<AndAction> parseAnd(const nlohmann::json& element);
140 
141 /**
142  * Parses a JSON element containing a bit position (from 0-7).
143  *
144  * Returns the corresponding C++ uint8_t value.
145  *
146  * Throws an exception if parsing fails.
147  *
148  * @param element JSON element
149  * @return uint8_t value
150  */
151 inline uint8_t parseBitPosition(const nlohmann::json& element)
152 {
153     // Verify element contains an integer
154     if (!element.is_number_integer())
155     {
156         throw std::invalid_argument{"Element is not an integer"};
157     }
158     int value = element.get<int>();
159     if ((value < 0) || (value > 7))
160     {
161         throw std::invalid_argument{"Element is not a bit position"};
162     }
163     return static_cast<uint8_t>(value);
164 }
165 
166 /**
167  * Parses a JSON element containing a bit value (0 or 1).
168  *
169  * Returns the corresponding C++ uint8_t value.
170  *
171  * Throws an exception if parsing fails.
172  *
173  * @param element JSON element
174  * @return uint8_t value
175  */
176 inline uint8_t parseBitValue(const nlohmann::json& element)
177 {
178     // Verify element contains an integer
179     if (!element.is_number_integer())
180     {
181         throw std::invalid_argument{"Element is not an integer"};
182     }
183     int value = element.get<int>();
184     if ((value < 0) || (value > 1))
185     {
186         throw std::invalid_argument{"Element is not a bit value"};
187     }
188     return static_cast<uint8_t>(value);
189 }
190 
191 /**
192  * Parses a JSON element containing a boolean.
193  *
194  * Returns the corresponding C++ boolean value.
195  *
196  * Throws an exception if parsing fails.
197  *
198  * @param element JSON element
199  * @return boolean value
200  */
201 inline bool parseBoolean(const nlohmann::json& element)
202 {
203     // Verify element contains a boolean
204     if (!element.is_boolean())
205     {
206         throw std::invalid_argument{"Element is not a boolean"};
207     }
208     return element.get<bool>();
209 }
210 
211 /**
212  * Parses a JSON element containing a chassis.
213  *
214  * Returns the corresponding C++ Chassis object.
215  *
216  * Throws an exception if parsing fails.
217  *
218  * @param element JSON element
219  * @return Chassis object
220  */
221 std::unique_ptr<Chassis> parseChassis(const nlohmann::json& element);
222 
223 /**
224  * Parses a JSON element containing an array of chassis.
225  *
226  * Returns the corresponding C++ Chassis objects.
227  *
228  * Throws an exception if parsing fails.
229  *
230  * @param element JSON element
231  * @return vector of Chassis objects
232  */
233 std::vector<std::unique_ptr<Chassis>>
234     parseChassisArray(const nlohmann::json& element);
235 
236 /**
237  * Parses a JSON element containing a compare_presence action.
238  *
239  * Returns the corresponding C++ ComparePresenceAction object.
240  *
241  * Throws an exception if parsing fails.
242  *
243  * @param element JSON element
244  * @return ComparePresenceAction object
245  */
246 std::unique_ptr<ComparePresenceAction>
247     parseComparePresence(const nlohmann::json& element);
248 
249 /**
250  * Parses a JSON element containing a compare_vpd action.
251  *
252  * Returns the corresponding C++ CompareVPDAction object.
253  *
254  * Throws an exception if parsing fails.
255  *
256  * @param element JSON element
257  * @return CompareVPDAction object
258  */
259 std::unique_ptr<CompareVPDAction>
260     parseCompareVPD(const nlohmann::json& element);
261 
262 /**
263  * Parses a JSON element containing a configuration object.
264  *
265  * Returns the corresponding C++ Configuration object.
266  *
267  * Throws an exception if parsing fails.
268  *
269  * @param element JSON element
270  * @return Configuration object
271  */
272 std::unique_ptr<Configuration>
273     parseConfiguration(const nlohmann::json& element);
274 
275 /**
276  * Parses a JSON element containing a device.
277  *
278  * Returns the corresponding C++ Device object.
279  *
280  * Throws an exception if parsing fails.
281  *
282  * @param element JSON element
283  * @return Device object
284  */
285 std::unique_ptr<Device> parseDevice(const nlohmann::json& element);
286 
287 /**
288  * Parses a JSON element containing an array of devices.
289  *
290  * Returns the corresponding C++ Device objects.
291  *
292  * Throws an exception if parsing fails.
293  *
294  * @param element JSON element
295  * @return vector of Device objects
296  */
297 std::vector<std::unique_ptr<Device>>
298     parseDeviceArray(const nlohmann::json& element);
299 
300 /**
301  * Parses a JSON element containing a double (floating point number).
302  *
303  * Returns the corresponding C++ double value.
304  *
305  * Throws an exception if parsing fails.
306  *
307  * @param element JSON element
308  * @return double value
309  */
310 inline double parseDouble(const nlohmann::json& element)
311 {
312     // Verify element contains a number (integer or floating point)
313     if (!element.is_number())
314     {
315         throw std::invalid_argument{"Element is not a number"};
316     }
317     return element.get<double>();
318 }
319 
320 /**
321  * Parses a JSON element containing a byte value expressed as a hexadecimal
322  * string.
323  *
324  * The JSON number data type does not support the hexadecimal format.  For this
325  * reason, hexadecimal byte values are stored as strings in the configuration
326  * file.
327  *
328  * Returns the corresponding C++ uint8_t value.
329  *
330  * Throws an exception if parsing fails.
331  *
332  * @param element JSON element
333  * @return uint8_t value
334  */
335 inline uint8_t parseHexByte(const nlohmann::json& element)
336 {
337     if (!element.is_string())
338     {
339         throw std::invalid_argument{"Element is not a string"};
340     }
341     std::string value = element.get<std::string>();
342 
343     bool isHex = (value.compare(0, 2, "0x") == 0) && (value.size() > 2) &&
344                  (value.size() < 5) &&
345                  (value.find_first_not_of("0123456789abcdefABCDEF", 2) ==
346                   std::string::npos);
347     if (!isHex)
348     {
349         throw std::invalid_argument{"Element is not hexadecimal string"};
350     }
351     return static_cast<uint8_t>(std::stoul(value, 0, 0));
352 }
353 
354 /**
355  * Parses a JSON element containing an array of byte values expressed as a
356  * hexadecimal strings.
357  *
358  * Returns the corresponding C++ uint8_t values.
359  *
360  * Throws an exception if parsing fails.
361  *
362  * @param element JSON element
363  * @return vector of uint8_t
364  */
365 std::vector<uint8_t> parseHexByteArray(const nlohmann::json& element);
366 
367 /**
368  * Parses a JSON element containing an i2c_capture_bytes action.
369  *
370  * Returns the corresponding C++ I2CCaptureBytesAction object.
371  *
372  * Throws an exception if parsing fails.
373  *
374  * @param element JSON element
375  * @return I2CCaptureBytesAction object
376  */
377 std::unique_ptr<I2CCaptureBytesAction>
378     parseI2CCaptureBytes(const nlohmann::json& element);
379 
380 /**
381  * Parses a JSON element containing an i2c_compare_bit action.
382  *
383  * Returns the corresponding C++ I2CCompareBitAction object.
384  *
385  * Throws an exception if parsing fails.
386  *
387  * @param element JSON element
388  * @return I2CCompareBitAction object
389  */
390 std::unique_ptr<I2CCompareBitAction>
391     parseI2CCompareBit(const nlohmann::json& element);
392 
393 /**
394  * Parses a JSON element containing an i2c_compare_byte action.
395  *
396  * Returns the corresponding C++ I2CCompareByteAction object.
397  *
398  * Throws an exception if parsing fails.
399  *
400  * @param element JSON element
401  * @return I2CCompareByteAction object
402  */
403 std::unique_ptr<I2CCompareByteAction>
404     parseI2CCompareByte(const nlohmann::json& element);
405 
406 /**
407  * Parses a JSON element containing an i2c_compare_bytes action.
408  *
409  * Returns the corresponding C++ I2CCompareBytesAction object.
410  *
411  * Throws an exception if parsing fails.
412  *
413  * @param element JSON element
414  * @return I2CCompareBytesAction object
415  */
416 std::unique_ptr<I2CCompareBytesAction>
417     parseI2CCompareBytes(const nlohmann::json& element);
418 
419 /**
420  * Parses a JSON element containing an i2c_interface.
421  *
422  * Returns the corresponding C++ i2c::I2CInterface object.
423  *
424  * Throws an exception if parsing fails.
425  *
426  * @param element JSON element
427  * @return i2c::I2CInterface object
428  */
429 std::unique_ptr<i2c::I2CInterface>
430     parseI2CInterface(const nlohmann::json& element);
431 
432 /**
433  * Parses a JSON element containing an i2c_write_bit action.
434  *
435  * Returns the corresponding C++ I2CWriteBitAction object.
436  *
437  * Throws an exception if parsing fails.
438  *
439  * @param element JSON element
440  * @return I2CWriteBitAction object
441  */
442 std::unique_ptr<I2CWriteBitAction>
443     parseI2CWriteBit(const nlohmann::json& element);
444 
445 /**
446  * Parses a JSON element containing an i2c_write_byte action.
447  *
448  * Returns the corresponding C++ I2CWriteByteAction object.
449  *
450  * Throws an exception if parsing fails.
451  *
452  * @param element JSON element
453  * @return I2CWriteByteAction object
454  */
455 std::unique_ptr<I2CWriteByteAction>
456     parseI2CWriteByte(const nlohmann::json& element);
457 
458 /**
459  * Parses a JSON element containing an i2c_write_bytes action.
460  *
461  * Returns the corresponding C++ I2CWriteBytesAction object.
462  *
463  * Throws an exception if parsing fails.
464  *
465  * @param element JSON element
466  * @return I2CWriteBytesAction object
467  */
468 std::unique_ptr<I2CWriteBytesAction>
469     parseI2CWriteBytes(const nlohmann::json& element);
470 
471 /**
472  * Parses a JSON element containing an if action.
473  *
474  * Returns the corresponding C++ IfAction object.
475  *
476  * Throws an exception if parsing fails.
477  *
478  * @param element JSON element
479  * @return IfAction object
480  */
481 std::unique_ptr<IfAction> parseIf(const nlohmann::json& element);
482 
483 /**
484  * Parses a JSON element containing an 8-bit signed integer.
485  *
486  * Returns the corresponding C++ int8_t value.
487  *
488  * Throws an exception if parsing fails.
489  *
490  * @param element JSON element
491  * @return int8_t value
492  */
493 inline int8_t parseInt8(const nlohmann::json& element)
494 {
495     // Verify element contains an integer
496     if (!element.is_number_integer())
497     {
498         throw std::invalid_argument{"Element is not an integer"};
499     }
500     int value = element.get<int>();
501     if ((value < INT8_MIN) || (value > INT8_MAX))
502     {
503         throw std::invalid_argument{"Element is not an 8-bit signed integer"};
504     }
505     return static_cast<int8_t>(value);
506 }
507 
508 /**
509  * Parses a JSON element containing a relative inventory path.
510  *
511  * Returns the corresponding C++ string containing the absolute inventory path.
512  *
513  * Inventory paths in the JSON configuration file are relative.  Adds the
514  * necessary prefix to make the path absolute.
515  *
516  * Throws an exception if parsing fails.
517  *
518  * @param element JSON element
519  * @return absolute D-Bus inventory path
520  */
521 std::string parseInventoryPath(const nlohmann::json& element);
522 
523 /**
524  * Parses a JSON element containing a log_phase_fault action.
525  *
526  * Returns the corresponding C++ LogPhaseFaultAction object.
527  *
528  * Throws an exception if parsing fails.
529  *
530  * @param element JSON element
531  * @return LogPhaseFaultAction object
532  */
533 std::unique_ptr<LogPhaseFaultAction>
534     parseLogPhaseFault(const nlohmann::json& element);
535 
536 /**
537  * Parses a JSON element containing a not action.
538  *
539  * Returns the corresponding C++ NotAction object.
540  *
541  * Throws an exception if parsing fails.
542  *
543  * @param element JSON element
544  * @return NotAction object
545  */
546 std::unique_ptr<NotAction> parseNot(const nlohmann::json& element);
547 
548 /**
549  * Parses a JSON element containing an or action.
550  *
551  * Returns the corresponding C++ OrAction object.
552  *
553  * Throws an exception if parsing fails.
554  *
555  * @param element JSON element
556  * @return OrAction object
557  */
558 std::unique_ptr<OrAction> parseOr(const nlohmann::json& element);
559 
560 /**
561  * Parses a JSON element containing a phase_fault_detection object.
562  *
563  * Returns the corresponding C++ PhaseFaultDetection object.
564  *
565  * Throws an exception if parsing fails.
566  *
567  * @param element JSON element
568  * @return PhaseFaultDetection object
569  */
570 std::unique_ptr<PhaseFaultDetection>
571     parsePhaseFaultDetection(const nlohmann::json& element);
572 
573 /**
574  * Parses a JSON element containing a PhaseFaultType expressed as a string.
575  *
576  * Returns the corresponding PhaseFaultType enum value.
577  *
578  * Throws an exception if parsing fails.
579  *
580  * @param element JSON element
581  * @return PhaseFaultType enum value
582  */
583 PhaseFaultType parsePhaseFaultType(const nlohmann::json& element);
584 
585 /**
586  * Parses a JSON element containing a pmbus_read_sensor action.
587  *
588  * Returns the corresponding C++ PMBusReadSensorAction object.
589  *
590  * Throws an exception if parsing fails.
591  *
592  * @param element JSON element
593  * @return PMBusReadSensorAction object
594  */
595 std::unique_ptr<PMBusReadSensorAction>
596     parsePMBusReadSensor(const nlohmann::json& element);
597 
598 /**
599  * Parses a JSON element containing a pmbus_write_vout_command action.
600  *
601  * Returns the corresponding C++ PMBusWriteVoutCommandAction object.
602  *
603  * Throws an exception if parsing fails.
604  *
605  * @param element JSON element
606  * @return PMBusWriteVoutCommandAction object
607  */
608 std::unique_ptr<PMBusWriteVoutCommandAction>
609     parsePMBusWriteVoutCommand(const nlohmann::json& element);
610 
611 /**
612  * Parses a JSON element containing a presence_detection object.
613  *
614  * Returns the corresponding C++ PresenceDetection object.
615  *
616  * Throws an exception if parsing fails.
617  *
618  * @param element JSON element
619  * @return PresenceDetection object
620  */
621 std::unique_ptr<PresenceDetection>
622     parsePresenceDetection(const nlohmann::json& element);
623 
624 /**
625  * Parses a JSON element containing a rail.
626  *
627  * Returns the corresponding C++ Rail object.
628  *
629  * Throws an exception if parsing fails.
630  *
631  * @param element JSON element
632  * @return Rail object
633  */
634 std::unique_ptr<Rail> parseRail(const nlohmann::json& element);
635 
636 /**
637  * Parses a JSON element containing an array of rails.
638  *
639  * Returns the corresponding C++ Rail objects.
640  *
641  * Throws an exception if parsing fails.
642  *
643  * @param element JSON element
644  * @return vector of Rail objects
645  */
646 std::vector<std::unique_ptr<Rail>>
647     parseRailArray(const nlohmann::json& element);
648 
649 /**
650  * Parses the JSON root element of the entire configuration file.
651  *
652  * Returns the corresponding C++ Rule and Chassis objects.
653  *
654  * Throws an exception if parsing fails.
655  *
656  * @param element JSON element
657  * @return tuple containing vectors of Rule and Chassis objects
658  */
659 std::tuple<std::vector<std::unique_ptr<Rule>>,
660            std::vector<std::unique_ptr<Chassis>>>
661     parseRoot(const nlohmann::json& element);
662 
663 /**
664  * Parses a JSON element containing a rule.
665  *
666  * Returns the corresponding C++ Rule object.
667  *
668  * Throws an exception if parsing fails.
669  *
670  * @param element JSON element
671  * @return Rule object
672  */
673 std::unique_ptr<Rule> parseRule(const nlohmann::json& element);
674 
675 /**
676  * Parses a JSON element containing an array of rules.
677  *
678  * Returns the corresponding C++ Rule objects.
679  *
680  * Throws an exception if parsing fails.
681  *
682  * @param element JSON element
683  * @return vector of Rule objects
684  */
685 std::vector<std::unique_ptr<Rule>>
686     parseRuleArray(const nlohmann::json& element);
687 
688 /**
689  * Parses the "rule_id" or "actions" property in a JSON element.
690  *
691  * The element must contain one property or the other but not both.
692  *
693  * If the element contains a "rule_id" property, the corresponding C++
694  * RunRuleAction object is returned.
695  *
696  * If the element contains an "actions" property, the corresponding C++ Action
697  * objects are returned.
698  *
699  * Throws an exception if parsing fails.
700  *
701  * @param element JSON element
702  * @return vector of Action objects
703  */
704 std::vector<std::unique_ptr<Action>>
705     parseRuleIDOrActionsProperty(const nlohmann::json& element);
706 
707 /**
708  * Parses a JSON element containing a run_rule action.
709  *
710  * Returns the corresponding C++ RunRuleAction object.
711  *
712  * Throws an exception if parsing fails.
713  *
714  * @param element JSON element
715  * @return RunRuleAction object
716  */
717 std::unique_ptr<RunRuleAction> parseRunRule(const nlohmann::json& element);
718 
719 /**
720  * Parses a JSON element containing a SensorDataFormat expressed as a string.
721  *
722  * Returns the corresponding SensorDataFormat enum value.
723  *
724  * Throws an exception if parsing fails.
725  *
726  * @param element JSON element
727  * @return SensorDataFormat enum value
728  */
729 pmbus_utils::SensorDataFormat
730     parseSensorDataFormat(const nlohmann::json& element);
731 
732 /**
733  * Parses a JSON element containing a sensor_monitoring object.
734  *
735  * Returns the corresponding C++ SensorMonitoring object.
736  *
737  * Throws an exception if parsing fails.
738  *
739  * @param element JSON element
740  * @return SensorMonitoring object
741  */
742 std::unique_ptr<SensorMonitoring>
743     parseSensorMonitoring(const nlohmann::json& element);
744 
745 /**
746  * Parses a JSON element containing a SensorType expressed as a string.
747  *
748  * Returns the corresponding SensorType enum value.
749  *
750  * Throws an exception if parsing fails.
751  *
752  * @param element JSON element
753  * @return SensorType enum value
754  */
755 SensorType parseSensorType(const nlohmann::json& element);
756 
757 /**
758  * Parses a JSON element containing a set_device action.
759  *
760  * Returns the corresponding C++ SetDeviceAction object.
761  *
762  * Throws an exception if parsing fails.
763  *
764  * @param element JSON element
765  * @return SetDeviceAction object
766  */
767 std::unique_ptr<SetDeviceAction> parseSetDevice(const nlohmann::json& element);
768 
769 /**
770  * Parses a JSON element containing a string.
771  *
772  * Returns the corresponding C++ string.
773  *
774  * Throws an exception if parsing fails.
775  *
776  * @param element JSON element
777  * @param isEmptyValid indicates whether an empty string value is valid
778  * @return string value
779  */
780 inline std::string parseString(const nlohmann::json& element,
781                                bool isEmptyValid = false)
782 {
783     if (!element.is_string())
784     {
785         throw std::invalid_argument{"Element is not a string"};
786     }
787     std::string value = element.get<std::string>();
788     if (value.empty() && !isEmptyValid)
789     {
790         throw std::invalid_argument{"Element contains an empty string"};
791     }
792     return value;
793 }
794 
795 /**
796  * Parses a JSON element containing an 8-bit unsigned integer.
797  *
798  * Returns the corresponding C++ uint8_t value.
799  *
800  * Throws an exception if parsing fails.
801  *
802  * @param element JSON element
803  * @return uint8_t value
804  */
805 inline uint8_t parseUint8(const nlohmann::json& element)
806 {
807     // Verify element contains an integer
808     if (!element.is_number_integer())
809     {
810         throw std::invalid_argument{"Element is not an integer"};
811     }
812     int value = element.get<int>();
813     if ((value < 0) || (value > UINT8_MAX))
814     {
815         throw std::invalid_argument{"Element is not an 8-bit unsigned integer"};
816     }
817     return static_cast<uint8_t>(value);
818 }
819 
820 /**
821  * Parses a JSON element containing an unsigned integer.
822  *
823  * Returns the corresponding C++ unsigned int value.
824  *
825  * Throws an exception if parsing fails.
826  *
827  * @param element JSON element
828  * @return unsigned int value
829  */
830 inline unsigned int parseUnsignedInteger(const nlohmann::json& element)
831 {
832     // Verify element contains an unsigned integer
833     if (!element.is_number_unsigned())
834     {
835         throw std::invalid_argument{"Element is not an unsigned integer"};
836     }
837     return element.get<unsigned int>();
838 }
839 
840 /**
841  * Parses a JSON element containing a VoutDataFormat expressed as a string.
842  *
843  * Returns the corresponding VoutDataFormat enum value.
844  *
845  * Throws an exception if parsing fails.
846  *
847  * @param element JSON element
848  * @return VoutDataFormat enum value
849  */
850 pmbus_utils::VoutDataFormat parseVoutDataFormat(const nlohmann::json& element);
851 
852 /**
853  * Verifies that the specified JSON element is a JSON array.
854  *
855  * Throws an invalid_argument exception if the element is not an array.
856  *
857  * @param element JSON element
858  */
859 inline void verifyIsArray(const nlohmann::json& element)
860 {
861     if (!element.is_array())
862     {
863         throw std::invalid_argument{"Element is not an array"};
864     }
865 }
866 
867 /**
868  * Verifies that the specified JSON element is a JSON object.
869  *
870  * Throws an invalid_argument exception if the element is not an object.
871  *
872  * @param element JSON element
873  */
874 inline void verifyIsObject(const nlohmann::json& element)
875 {
876     if (!element.is_object())
877     {
878         throw std::invalid_argument{"Element is not an object"};
879     }
880 }
881 
882 /**
883  * Verifies that the specified JSON element contains the expected number of
884  * properties.
885  *
886  * Throws an invalid_argument exception if the element contains a different
887  * number of properties.  This indicates the element contains an invalid
888  * property.
889  *
890  * @param element JSON element
891  * @param expectedCount expected number of properties in element
892  */
893 inline void verifyPropertyCount(const nlohmann::json& element,
894                                 unsigned int expectedCount)
895 {
896     if (element.size() != expectedCount)
897     {
898         throw std::invalid_argument{"Element contains an invalid property"};
899     }
900 }
901 
902 } // namespace internal
903 
904 } // namespace phosphor::power::regulators::config_file_parser
905