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