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